From 1e679b957ae244cd839b8792b589ea5a671482e8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:39 +0200 Subject: net: dpaa: Improve error reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of the generic error message emitted by the driver core when a remove callback returns an error code ("remove callback returned a non-zero value. This will be ignored."), emit a message describing the actual problem and return zero to suppress the generic message. Note that apart from suppressing the generic error message there are no side effects by changing the return value to zero. This prepares changing the remove callback to return void. Acked-by: Madalin Bucur Reviewed-by: Michal Kubiak Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-2-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 431f8917dc39..e0e5bf0587fc 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -3516,6 +3516,9 @@ static int dpaa_remove(struct platform_device *pdev) phylink_destroy(priv->mac_dev->phylink); err = dpaa_fq_free(dev, &priv->dpaa_fq_list); + if (err) + dev_err(dev, "Failed to free FQs on remove (%pE)\n", + ERR_PTR(err)); qman_delete_cgr_safe(&priv->ingress_cgr); qman_release_cgrid(priv->ingress_cgr.cgrid); @@ -3528,7 +3531,7 @@ static int dpaa_remove(struct platform_device *pdev) free_netdev(net_dev); - return err; + return 0; } static const struct platform_device_id dpaa_devtype[] = { -- cgit From 9c3ddc44d0c005ac3138efd53d6037dd99e43ccb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:40 +0200 Subject: net: dpaa: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Acked-by: Madalin Bucur Reviewed-by: Michal Kubiak Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-3-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index e0e5bf0587fc..85e38a1ec22a 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -3497,7 +3497,7 @@ free_netdev: return err; } -static int dpaa_remove(struct platform_device *pdev) +static void dpaa_remove(struct platform_device *pdev) { struct net_device *net_dev; struct dpaa_priv *priv; @@ -3530,8 +3530,6 @@ static int dpaa_remove(struct platform_device *pdev) dpaa_bps_free(priv); free_netdev(net_dev); - - return 0; } static const struct platform_device_id dpaa_devtype[] = { @@ -3549,7 +3547,7 @@ static struct platform_driver dpaa_driver = { }, .id_table = dpaa_devtype, .probe = dpaa_eth_probe, - .remove = dpaa_remove + .remove_new = dpaa_remove }; static int __init dpaa_load(void) -- cgit From 12d6cc19f29b86982d16e15486f8bc5f520e84a0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:41 +0200 Subject: net: fec: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Michal Kubiak Reviewed-by: Wei Fang Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-4-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 5 ++--- drivers/net/ethernet/freescale/fec_mpc52xx.c | 6 ++---- drivers/net/ethernet/freescale/fec_mpc52xx_phy.c | 6 ++---- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 8fbe47703d47..1280da699fa3 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -4458,7 +4458,7 @@ failed_ioremap: return ret; } -static int +static void fec_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); @@ -4494,7 +4494,6 @@ fec_drv_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); free_netdev(ndev); - return 0; } static int __maybe_unused fec_suspend(struct device *dev) @@ -4650,7 +4649,7 @@ static struct platform_driver fec_driver = { }, .id_table = fec_devtype, .probe = fec_probe, - .remove = fec_drv_remove, + .remove_new = fec_drv_remove, }; module_platform_driver(fec_driver); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index b88816b71ddf..984ece5cd64f 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -974,7 +974,7 @@ err_netdev: return rv; } -static int +static void mpc52xx_fec_remove(struct platform_device *op) { struct net_device *ndev; @@ -998,8 +998,6 @@ mpc52xx_fec_remove(struct platform_device *op) release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec)); free_netdev(ndev); - - return 0; } #ifdef CONFIG_PM @@ -1042,7 +1040,7 @@ static struct platform_driver mpc52xx_fec_driver = { .of_match_table = mpc52xx_fec_match, }, .probe = mpc52xx_fec_probe, - .remove = mpc52xx_fec_remove, + .remove_new = mpc52xx_fec_remove, #ifdef CONFIG_PM .suspend = mpc52xx_fec_of_suspend, .resume = mpc52xx_fec_of_resume, diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c index 95f778cce98c..61d3776d6750 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c @@ -117,7 +117,7 @@ static int mpc52xx_fec_mdio_probe(struct platform_device *of) return err; } -static int mpc52xx_fec_mdio_remove(struct platform_device *of) +static void mpc52xx_fec_mdio_remove(struct platform_device *of) { struct mii_bus *bus = platform_get_drvdata(of); struct mpc52xx_fec_mdio_priv *priv = bus->priv; @@ -126,8 +126,6 @@ static int mpc52xx_fec_mdio_remove(struct platform_device *of) iounmap(priv->regs); kfree(priv); mdiobus_free(bus); - - return 0; } static const struct of_device_id mpc52xx_fec_mdio_match[] = { @@ -145,7 +143,7 @@ struct platform_driver mpc52xx_fec_mdio_driver = { .of_match_table = mpc52xx_fec_mdio_match, }, .probe = mpc52xx_fec_mdio_probe, - .remove = mpc52xx_fec_mdio_remove, + .remove_new = mpc52xx_fec_mdio_remove, }; /* let fec driver call it, since this has to be registered before it */ -- cgit From 4875b2a362e97a25d5f0ec905bb5b8672f951aeb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:42 +0200 Subject: net: fman: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Acked-by: Madalin Bucur Reviewed-by: Michal Kubiak Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-5-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fman/mac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 43665806c590..c5045891d694 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -331,12 +331,11 @@ _return_of_node_put: return err; } -static int mac_remove(struct platform_device *pdev) +static void mac_remove(struct platform_device *pdev) { struct mac_device *mac_dev = platform_get_drvdata(pdev); platform_device_unregister(mac_dev->priv->eth_dev); - return 0; } static struct platform_driver mac_driver = { @@ -345,7 +344,7 @@ static struct platform_driver mac_driver = { .of_match_table = mac_match, }, .probe = mac_probe, - .remove = mac_remove, + .remove_new = mac_remove, }; builtin_platform_driver(mac_driver); -- cgit From ead29c5e0888ddf25300962bd18f8776b89390a0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:43 +0200 Subject: net: fs_enet: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Michal Kubiak Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-6-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 5 ++--- drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c | 6 ++---- drivers/net/ethernet/freescale/fs_enet/mii-fec.c | 6 ++---- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 8844a9a04fcf..f9f5b28cc72e 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -1051,7 +1051,7 @@ out_free_fpi: return ret; } -static int fs_enet_remove(struct platform_device *ofdev) +static void fs_enet_remove(struct platform_device *ofdev) { struct net_device *ndev = platform_get_drvdata(ofdev); struct fs_enet_private *fep = netdev_priv(ndev); @@ -1066,7 +1066,6 @@ static int fs_enet_remove(struct platform_device *ofdev) if (of_phy_is_fixed_link(ofdev->dev.of_node)) of_phy_deregister_fixed_link(ofdev->dev.of_node); free_netdev(ndev); - return 0; } static const struct of_device_id fs_enet_match[] = { @@ -1113,7 +1112,7 @@ static struct platform_driver fs_enet_driver = { .of_match_table = fs_enet_match, }, .probe = fs_enet_probe, - .remove = fs_enet_remove, + .remove_new = fs_enet_remove, }; #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 21de56345503..91a69fc2f7c2 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -192,7 +192,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct platform_device *ofdev) +static void fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = platform_get_drvdata(ofdev); struct bb_info *bitbang = bus->priv; @@ -201,8 +201,6 @@ static int fs_enet_mdio_remove(struct platform_device *ofdev) free_mdio_bitbang(bus); iounmap(bitbang->dir); kfree(bitbang); - - return 0; } static const struct of_device_id fs_enet_mdio_bb_match[] = { @@ -219,7 +217,7 @@ static struct platform_driver fs_enet_bb_mdio_driver = { .of_match_table = fs_enet_mdio_bb_match, }, .probe = fs_enet_mdio_probe, - .remove = fs_enet_mdio_remove, + .remove_new = fs_enet_mdio_remove, }; module_platform_driver(fs_enet_bb_mdio_driver); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 59a8f0bd0f5c..1910df250c33 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -187,7 +187,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct platform_device *ofdev) +static void fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = platform_get_drvdata(ofdev); struct fec_info *fec = bus->priv; @@ -196,8 +196,6 @@ static int fs_enet_mdio_remove(struct platform_device *ofdev) iounmap(fec->fecp); kfree(fec); mdiobus_free(bus); - - return 0; } static const struct of_device_id fs_enet_mdio_fec_match[] = { @@ -220,7 +218,7 @@ static struct platform_driver fs_enet_fec_mdio_driver = { .of_match_table = fs_enet_mdio_fec_match, }, .probe = fs_enet_mdio_probe, - .remove = fs_enet_mdio_remove, + .remove_new = fs_enet_mdio_remove, }; module_platform_driver(fs_enet_fec_mdio_driver); -- cgit From f833635589aefc713582ae763aed8ef997b39f91 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:44 +0200 Subject: net: fsl_pq_mdio: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Michal Kubiak Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-7-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 9d58d8334467..01d594886f52 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -511,7 +511,7 @@ error: } -static int fsl_pq_mdio_remove(struct platform_device *pdev) +static void fsl_pq_mdio_remove(struct platform_device *pdev) { struct device *device = &pdev->dev; struct mii_bus *bus = dev_get_drvdata(device); @@ -521,8 +521,6 @@ static int fsl_pq_mdio_remove(struct platform_device *pdev) iounmap(priv->map); mdiobus_free(bus); - - return 0; } static struct platform_driver fsl_pq_mdio_driver = { @@ -531,7 +529,7 @@ static struct platform_driver fsl_pq_mdio_driver = { .of_match_table = fsl_pq_mdio_match, }, .probe = fsl_pq_mdio_probe, - .remove = fsl_pq_mdio_remove, + .remove_new = fsl_pq_mdio_remove, }; module_platform_driver(fsl_pq_mdio_driver); -- cgit From 4be0ebc33f39f22f5568eac9d23715d79f1d110f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:45 +0200 Subject: net: gianfar: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Michal Kubiak Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-8-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/gianfar.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 38d5013c6fed..0c898f9ee358 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -3364,7 +3364,7 @@ register_fail: return err; } -static int gfar_remove(struct platform_device *ofdev) +static void gfar_remove(struct platform_device *ofdev) { struct gfar_private *priv = platform_get_drvdata(ofdev); struct device_node *np = ofdev->dev.of_node; @@ -3381,8 +3381,6 @@ static int gfar_remove(struct platform_device *ofdev) gfar_free_rx_queues(priv); gfar_free_tx_queues(priv); free_gfar_dev(priv); - - return 0; } #ifdef CONFIG_PM @@ -3642,7 +3640,7 @@ static struct platform_driver gfar_driver = { .of_match_table = gfar_match, }, .probe = gfar_probe, - .remove = gfar_remove, + .remove_new = gfar_remove, }; module_platform_driver(gfar_driver); -- cgit From ae18facf566c94ba78b2acbe26feae5b5596cbea Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 10 Jul 2023 09:19:46 +0200 Subject: net: ucc_geth: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Michal Kubiak Reviewed-by: Simon Horman Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230710071946.3470249-9-u.kleine-koenig@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/ucc_geth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 7a4cb4f07c32..2b3a15f24e7c 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3753,7 +3753,7 @@ err_free_info: return err; } -static int ucc_geth_remove(struct platform_device* ofdev) +static void ucc_geth_remove(struct platform_device* ofdev) { struct net_device *dev = platform_get_drvdata(ofdev); struct ucc_geth_private *ugeth = netdev_priv(dev); @@ -3767,8 +3767,6 @@ static int ucc_geth_remove(struct platform_device* ofdev) of_node_put(ugeth->ug_info->phy_node); kfree(ugeth->ug_info); free_netdev(dev); - - return 0; } static const struct of_device_id ucc_geth_match[] = { @@ -3787,7 +3785,7 @@ static struct platform_driver ucc_geth_driver = { .of_match_table = ucc_geth_match, }, .probe = ucc_geth_probe, - .remove = ucc_geth_remove, + .remove_new = ucc_geth_remove, .suspend = ucc_geth_suspend, .resume = ucc_geth_resume, }; -- cgit From 47b7acfb016b9fdc950cb501c351faf5723b1868 Mon Sep 17 00:00:00 2001 From: Menglong Dong Date: Mon, 10 Jul 2023 17:47:47 +0800 Subject: bnxt_en: use dev_consume_skb_any() in bnxt_tx_int Replace dev_kfree_skb_any() with dev_consume_skb_any() in bnxt_tx_int() to clear the unnecessary noise of "kfree_skb" event. Signed-off-by: Menglong Dong Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230710094747.943782-1-imagedong@tencent.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index e5b54e6025be..d84ded8db93d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -685,7 +685,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) next_tx_int: cons = NEXT_TX(cons); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); } WRITE_ONCE(txr->tx_cons, cons); -- cgit From a8aa20a64ef2bdbad7421acf9c7217c2c0e4ac75 Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Mon, 10 Jul 2023 15:06:37 -0500 Subject: net: stmmac: dwmac-qcom-ethqos: Use of_get_phy_mode() over device_get_phy_mode() Since this driver only uses devicetree, let's move over to of_get_phy_mode(). That API has an explicit error return and produces a phy_interface_t directly instead of an int when representing the phy mode. Signed-off-by: Andrew Halaney Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index e62940414e54..ebafdadb28d5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -4,10 +4,10 @@ #include #include #include +#include #include #include #include -#include #include "stmmac.h" #include "stmmac_platform.h" @@ -104,7 +104,7 @@ struct qcom_ethqos { struct clk *link_clk; struct phy *serdes_phy; unsigned int speed; - int phy_mode; + phy_interface_t phy_mode; const struct ethqos_emac_por *por; unsigned int num_por; @@ -720,7 +720,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (!ethqos) return -ENOMEM; - ethqos->phy_mode = device_get_phy_mode(dev); + ret = of_get_phy_mode(np, ðqos->phy_mode); + if (ret) + return dev_err_probe(dev, ret, "Failed to get phy mode\n"); switch (ethqos->phy_mode) { case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: @@ -731,8 +733,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_SGMII: ethqos->configure_func = ethqos_configure_sgmii; break; - case -ENODEV: - return -ENODEV; default: return -EINVAL; } -- cgit From b2f3d915b4fe203b725da8b5a88bc9d42a1ffc50 Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Mon, 10 Jul 2023 15:06:38 -0500 Subject: net: stmmac: dwmac-qcom-ethqos: Use dev_err_probe() Using dev_err_probe() logs to devices_deferred which is helpful when debugging. Reviewed-by: Andrew Lunn Signed-off-by: Andrew Halaney Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ebafdadb28d5..1e103fd356b7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -710,8 +710,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); if (IS_ERR(plat_dat)) { - dev_err(dev, "dt configuration failed\n"); - return PTR_ERR(plat_dat); + return dev_err_probe(dev, PTR_ERR(plat_dat), + "dt configuration failed\n"); } plat_dat->clks_config = ethqos_clks_config; -- cgit From 27381e72a2db75a8d82b4baed705b9cc4e5d278d Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Mon, 10 Jul 2023 15:06:39 -0500 Subject: net: stmmac: dwmac-qcom-ethqos: Log more errors in probe These are useful to see when debugging a probe failure. Signed-off-by: Andrew Halaney Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 1e103fd356b7..757504ebb676 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -706,7 +706,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ret = stmmac_get_platform_resources(pdev, &stmmac_res); if (ret) - return ret; + return dev_err_probe(dev, ret, + "Failed to get platform resources\n"); plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); if (IS_ERR(plat_dat)) { @@ -734,13 +735,16 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->configure_func = ethqos_configure_sgmii; break; default: + dev_err(dev, "Unsupported phy mode %s\n", + phy_modes(ethqos->phy_mode)); return -EINVAL; } ethqos->pdev = pdev; ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii"); if (IS_ERR(ethqos->rgmii_base)) - return PTR_ERR(ethqos->rgmii_base); + return dev_err_probe(dev, PTR_ERR(ethqos->rgmii_base), + "Failed to map rgmii resource\n"); ethqos->mac_base = stmmac_res.addr; @@ -752,7 +756,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); if (IS_ERR(ethqos->link_clk)) - return PTR_ERR(ethqos->link_clk); + return dev_err_probe(dev, PTR_ERR(ethqos->link_clk), + "Failed to get link_clk\n"); ret = ethqos_clks_config(ethqos, true); if (ret) @@ -764,7 +769,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes"); if (IS_ERR(ethqos->serdes_phy)) - return PTR_ERR(ethqos->serdes_phy); + return dev_err_probe(dev, PTR_ERR(ethqos->serdes_phy), + "Failed to get serdes phy\n"); ethqos->speed = SPEED_1000; ethqos_update_link_clk(ethqos, SPEED_1000); -- cgit From f3b8bec7d29e1f330287b4df9f58b01e8b8ca010 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:54 +0200 Subject: mlxsw: reg: Add Policy-Engine Port Range Register Add the Policy-Engine Port Range Register that is used for configuring port range identification. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/d1a1f53d758f7452cf5abfe006b23496076ec3e6.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 8165bf31a99a..df63f3923372 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2799,6 +2799,78 @@ static inline void mlxsw_reg_ptar_unpack(char *payload, char *tcam_region_info) mlxsw_reg_ptar_tcam_region_info_memcpy_from(payload, tcam_region_info); } +/* PPRR - Policy-Engine Port Range Register + * ---------------------------------------- + * This register is used for configuring port range identification. + */ +#define MLXSW_REG_PPRR_ID 0x3008 +#define MLXSW_REG_PPRR_LEN 0x14 + +MLXSW_REG_DEFINE(pprr, MLXSW_REG_PPRR_ID, MLXSW_REG_PPRR_LEN); + +/* reg_pprr_ipv4 + * Apply port range register to IPv4 packets. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, ipv4, 0x00, 31, 1); + +/* reg_pprr_ipv6 + * Apply port range register to IPv6 packets. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, ipv6, 0x00, 30, 1); + +/* reg_pprr_src + * Apply port range register to source L4 ports. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, src, 0x00, 29, 1); + +/* reg_pprr_dst + * Apply port range register to destination L4 ports. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, dst, 0x00, 28, 1); + +/* reg_pprr_tcp + * Apply port range register to TCP packets. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, tcp, 0x00, 27, 1); + +/* reg_pprr_udp + * Apply port range register to UDP packets. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, udp, 0x00, 26, 1); + +/* reg_pprr_register_index + * Index of Port Range Register being accessed. + * Range is 0..cap_max_acl_l4_port_range-1. + * Access: Index + */ +MLXSW_ITEM32(reg, pprr, register_index, 0x00, 0, 8); + +/* reg_prrr_port_range_min + * Minimum port range for comparison. + * Match is defined as: + * port_range_min <= packet_port <= port_range_max. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, port_range_min, 0x04, 16, 16); + +/* reg_prrr_port_range_max + * Maximum port range for comparison. + * Access: RW + */ +MLXSW_ITEM32(reg, pprr, port_range_max, 0x04, 0, 16); + +static inline void mlxsw_reg_pprr_pack(char *payload, u8 register_index) +{ + MLXSW_REG_ZERO(pprr, payload); + mlxsw_reg_pprr_register_index_set(payload, register_index); +} + /* PPBS - Policy-Engine Policy Based Switching Register * ---------------------------------------------------- * This register retrieves and sets Policy Based Switching Table entries. @@ -12819,6 +12891,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(pacl), MLXSW_REG(pagt), MLXSW_REG(ptar), + MLXSW_REG(pprr), MLXSW_REG(ppbs), MLXSW_REG(prcr), MLXSW_REG(pefa), -- cgit From 9f53a7602ac6970cadeeead0e4352818ad000dcc Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:55 +0200 Subject: mlxsw: resource: Add resource identifier for port range registers Add a resource identifier for maximum number of layer 4 port range register so that it could be later used to query the information from firmware. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/59a8fec353d5ad9fbfb7612e4a7ff61eaedad445.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index 19ae0d1c74a8..89dd2777ec4d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -39,6 +39,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_ACL_FLEX_KEYS, MLXSW_RES_ID_ACL_MAX_ACTION_PER_RULE, MLXSW_RES_ID_ACL_ACTIONS_PER_SET, + MLXSW_RES_ID_ACL_MAX_L4_PORT_RANGE, MLXSW_RES_ID_ACL_MAX_ERPT_BANKS, MLXSW_RES_ID_ACL_MAX_ERPT_BANK_SIZE, MLXSW_RES_ID_ACL_MAX_LARGE_KEY_ID, @@ -99,6 +100,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_ACL_FLEX_KEYS] = 0x2910, [MLXSW_RES_ID_ACL_MAX_ACTION_PER_RULE] = 0x2911, [MLXSW_RES_ID_ACL_ACTIONS_PER_SET] = 0x2912, + [MLXSW_RES_ID_ACL_MAX_L4_PORT_RANGE] = 0x2920, [MLXSW_RES_ID_ACL_MAX_ERPT_BANKS] = 0x2940, [MLXSW_RES_ID_ACL_MAX_ERPT_BANK_SIZE] = 0x2941, [MLXSW_RES_ID_ACL_MAX_LARGE_KEY_ID] = 0x2942, -- cgit From b3eb04be729982ae7e311afcc9c031eca4718a46 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:56 +0200 Subject: mlxsw: spectrum_port_range: Add port range core The Spectrum ASICs have a fixed number of port range registers, each of which maintains the following parameters: * Minimum and maximum port. * Apply port range for source port, destination port or both. * Apply port range for TCP, UDP or both. * Apply port range for IPv4, IPv6 or both. Implement a port range core which takes care of the allocation and configuration of these registers and exposes an API that allows in-driver consumers (e.g., the ACL code) to request matching on a range of either source or destination port. These registers are going to be used for port range matching in the flower classifier that already matches on EtherType being IPv4 / IPv6 and IP protocol being TCP / UDP. As such, there is no need to limit these registers to a specific EtherType or IP protocol, which will increase the likelihood of a register being shared by multiple flower filters. It is unlikely that a filter will match on the same range of both source and destination ports, which is why each register is only configured to match on either source or destination port. If a filter requires matching on a range of both source and destination ports, it will utilize two port range registers and match on the output of both. For efficient lookup and traversal, use XArray to store the allocated port range registers. The XArray uses RCU and an internal spinlock to synchronise access, so there is no need for a dedicate lock. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/674f00539a0072d455847663b5feb504db51a259.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/Makefile | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 9 + drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 15 ++ .../ethernet/mellanox/mlxsw/spectrum_port_range.c | 181 +++++++++++++++++++++ 4 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 3ca9fce759ea..71cad6bb6e62 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -29,7 +29,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_nve.o spectrum_nve_vxlan.o \ spectrum_dpipe.o spectrum_trap.o \ spectrum_ethtool.o spectrum_policer.o \ - spectrum_pgt.o + spectrum_pgt.o spectrum_port_range.o mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o mlxsw_spectrum-$(CONFIG_PTP_1588_CLOCK) += spectrum_ptp.o obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 25a01dafde1b..c0edcc91f178 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3188,6 +3188,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, goto err_nve_init; } + err = mlxsw_sp_port_range_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize port ranges\n"); + goto err_port_range_init; + } + err = mlxsw_sp_acl_init(mlxsw_sp); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n"); @@ -3280,6 +3286,8 @@ err_ptp_clock_init: err_router_init: mlxsw_sp_acl_fini(mlxsw_sp); err_acl_init: + mlxsw_sp_port_range_fini(mlxsw_sp); +err_port_range_init: mlxsw_sp_nve_fini(mlxsw_sp); err_nve_init: mlxsw_sp_ipv6_addr_ht_fini(mlxsw_sp); @@ -3462,6 +3470,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) } mlxsw_sp_router_fini(mlxsw_sp); mlxsw_sp_acl_fini(mlxsw_sp); + mlxsw_sp_port_range_fini(mlxsw_sp); mlxsw_sp_nve_fini(mlxsw_sp); mlxsw_sp_ipv6_addr_ht_fini(mlxsw_sp); mlxsw_sp_afa_fini(mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 231e364cbb7c..fe6c6e02a484 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -175,6 +175,7 @@ struct mlxsw_sp { struct mlxsw_sp_acl *acl; struct mlxsw_sp_fid_core *fid_core; struct mlxsw_sp_policer_core *policer_core; + struct mlxsw_sp_port_range_core *pr_core; struct mlxsw_sp_kvdl *kvdl; struct mlxsw_sp_nve *nve; struct notifier_block netdevice_nb; @@ -1484,4 +1485,18 @@ int mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid, int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp); +/* spectrum_port_range.c */ +struct mlxsw_sp_port_range { + u16 min; + u16 max; + u8 source:1; /* Source or destination */ +}; + +int mlxsw_sp_port_range_reg_get(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_port_range *range, + struct netlink_ext_ack *extack, + u8 *p_prr_index); +void mlxsw_sp_port_range_reg_put(struct mlxsw_sp *mlxsw_sp, u8 prr_index); +int mlxsw_sp_port_range_init(struct mlxsw_sp *mlxsw_sp); +void mlxsw_sp_port_range_fini(struct mlxsw_sp *mlxsw_sp); #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c new file mode 100644 index 000000000000..a12a62632721 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#include +#include +#include +#include + +#include "spectrum.h" + +struct mlxsw_sp_port_range_reg { + struct mlxsw_sp_port_range range; + refcount_t refcount; + u32 index; +}; + +struct mlxsw_sp_port_range_core { + struct xarray prr_xa; + struct xa_limit prr_ids; +}; + +static int +mlxsw_sp_port_range_reg_configure(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_port_range_reg *prr) +{ + char pprr_pl[MLXSW_REG_PPRR_LEN]; + + /* We do not care if packet is IPv4/IPv6 and TCP/UDP, so set all four + * fields. + */ + mlxsw_reg_pprr_pack(pprr_pl, prr->index); + mlxsw_reg_pprr_ipv4_set(pprr_pl, true); + mlxsw_reg_pprr_ipv6_set(pprr_pl, true); + mlxsw_reg_pprr_src_set(pprr_pl, prr->range.source); + mlxsw_reg_pprr_dst_set(pprr_pl, !prr->range.source); + mlxsw_reg_pprr_tcp_set(pprr_pl, true); + mlxsw_reg_pprr_udp_set(pprr_pl, true); + mlxsw_reg_pprr_port_range_min_set(pprr_pl, prr->range.min); + mlxsw_reg_pprr_port_range_max_set(pprr_pl, prr->range.max); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pprr), pprr_pl); +} + +static struct mlxsw_sp_port_range_reg * +mlxsw_sp_port_range_reg_create(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_port_range *range, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + struct mlxsw_sp_port_range_reg *prr; + int err; + + prr = kzalloc(sizeof(*prr), GFP_KERNEL); + if (!prr) + return ERR_PTR(-ENOMEM); + + prr->range = *range; + refcount_set(&prr->refcount, 1); + + err = xa_alloc(&pr_core->prr_xa, &prr->index, prr, pr_core->prr_ids, + GFP_KERNEL); + if (err) { + if (err == -EBUSY) + NL_SET_ERR_MSG_MOD(extack, "Exceeded number of port range registers"); + goto err_xa_alloc; + } + + err = mlxsw_sp_port_range_reg_configure(mlxsw_sp, prr); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to configure port range register"); + goto err_reg_configure; + } + + return prr; + +err_reg_configure: + xa_erase(&pr_core->prr_xa, prr->index); +err_xa_alloc: + kfree(prr); + return ERR_PTR(err); +} + +static void mlxsw_sp_port_range_reg_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_port_range_reg *prr) +{ + struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + + xa_erase(&pr_core->prr_xa, prr->index); + kfree(prr); +} + +static struct mlxsw_sp_port_range_reg * +mlxsw_sp_port_range_reg_find(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_port_range *range) +{ + struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + struct mlxsw_sp_port_range_reg *prr; + unsigned long index; + + xa_for_each(&pr_core->prr_xa, index, prr) { + if (prr->range.min == range->min && + prr->range.max == range->max && + prr->range.source == range->source) + return prr; + } + + return NULL; +} + +int mlxsw_sp_port_range_reg_get(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_port_range *range, + struct netlink_ext_ack *extack, + u8 *p_prr_index) +{ + struct mlxsw_sp_port_range_reg *prr; + + prr = mlxsw_sp_port_range_reg_find(mlxsw_sp, range); + if (prr) { + refcount_inc(&prr->refcount); + *p_prr_index = prr->index; + return 0; + } + + prr = mlxsw_sp_port_range_reg_create(mlxsw_sp, range, extack); + if (IS_ERR(prr)) + return PTR_ERR(prr); + + *p_prr_index = prr->index; + + return 0; +} + +void mlxsw_sp_port_range_reg_put(struct mlxsw_sp *mlxsw_sp, u8 prr_index) +{ + struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + struct mlxsw_sp_port_range_reg *prr; + + prr = xa_load(&pr_core->prr_xa, prr_index); + if (WARN_ON(!prr)) + return; + + if (!refcount_dec_and_test(&prr->refcount)) + return; + + mlxsw_sp_port_range_reg_destroy(mlxsw_sp, prr); +} + +int mlxsw_sp_port_range_init(struct mlxsw_sp *mlxsw_sp) +{ + struct mlxsw_sp_port_range_core *pr_core; + struct mlxsw_core *core = mlxsw_sp->core; + u64 max; + + if (!MLXSW_CORE_RES_VALID(core, ACL_MAX_L4_PORT_RANGE)) + return -EIO; + max = MLXSW_CORE_RES_GET(core, ACL_MAX_L4_PORT_RANGE); + + /* Each port range register is represented using a single bit in the + * two bytes "l4_port_range" ACL key element. + */ + WARN_ON(max > BITS_PER_BYTE * sizeof(u16)); + + pr_core = kzalloc(sizeof(*mlxsw_sp->pr_core), GFP_KERNEL); + if (!pr_core) + return -ENOMEM; + mlxsw_sp->pr_core = pr_core; + + pr_core->prr_ids.max = max - 1; + xa_init_flags(&pr_core->prr_xa, XA_FLAGS_ALLOC); + + return 0; +} + +void mlxsw_sp_port_range_fini(struct mlxsw_sp *mlxsw_sp) +{ + struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + + WARN_ON(!xa_empty(&pr_core->prr_xa)); + xa_destroy(&pr_core->prr_xa); + kfree(pr_core); +} -- cgit From 74d6786cf2dc563bebd3bceb4fd48aadee7856b2 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:57 +0200 Subject: mlxsw: spectrum_port_range: Add devlink resource support Expose via devlink-resource the maximum number of port range registers and their current occupancy. Besides the observability benefits, this resource will be used by subsequent patches for scale and occupancy tests. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/7945e0c715dc5efb1617f45f7560c1f1bd0bcf8a.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 30 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_port_range.c | 19 ++++++++++++++ 3 files changed, 50 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index c0edcc91f178..86e2f0ed64d3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3739,6 +3739,26 @@ static int mlxsw_sp_resources_rifs_register(struct mlxsw_core *mlxsw_core) &size_params); } +static int +mlxsw_sp_resources_port_range_register(struct mlxsw_core *mlxsw_core) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + struct devlink_resource_size_params size_params; + u64 max; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, ACL_MAX_L4_PORT_RANGE)) + return -EIO; + + max = MLXSW_CORE_RES_GET(mlxsw_core, ACL_MAX_L4_PORT_RANGE); + devlink_resource_size_params_init(&size_params, max, max, 1, + DEVLINK_RESOURCE_UNIT_ENTRY); + + return devl_resource_register(devlink, "port_range_registers", max, + MLXSW_SP_RESOURCE_PORT_RANGE_REGISTERS, + DEVLINK_RESOURCE_ID_PARENT_TOP, + &size_params); +} + static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) { int err; @@ -3767,8 +3787,13 @@ static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) if (err) goto err_resources_rifs_register; + err = mlxsw_sp_resources_port_range_register(mlxsw_core); + if (err) + goto err_resources_port_range_register; + return 0; +err_resources_port_range_register: err_resources_rifs_register: err_resources_rif_mac_profile_register: err_policer_resources_register: @@ -3806,8 +3831,13 @@ static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core) if (err) goto err_resources_rifs_register; + err = mlxsw_sp_resources_port_range_register(mlxsw_core); + if (err) + goto err_resources_port_range_register; + return 0; +err_resources_port_range_register: err_resources_rifs_register: err_resources_rif_mac_profile_register: err_policer_resources_register: diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index fe6c6e02a484..a74652ea4d7c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -69,6 +69,7 @@ enum mlxsw_sp_resource_id { MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS, MLXSW_SP_RESOURCE_RIF_MAC_PROFILES, MLXSW_SP_RESOURCE_RIFS, + MLXSW_SP_RESOURCE_PORT_RANGE_REGISTERS, }; struct mlxsw_sp_port; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c index a12a62632721..2d193de12be6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_port_range.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "spectrum.h" @@ -17,6 +18,7 @@ struct mlxsw_sp_port_range_reg { struct mlxsw_sp_port_range_core { struct xarray prr_xa; struct xa_limit prr_ids; + atomic_t prr_count; }; static int @@ -71,6 +73,8 @@ mlxsw_sp_port_range_reg_create(struct mlxsw_sp *mlxsw_sp, goto err_reg_configure; } + atomic_inc(&pr_core->prr_count); + return prr; err_reg_configure: @@ -85,6 +89,7 @@ static void mlxsw_sp_port_range_reg_destroy(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + atomic_dec(&pr_core->prr_count); xa_erase(&pr_core->prr_xa, prr->index); kfree(prr); } @@ -145,6 +150,13 @@ void mlxsw_sp_port_range_reg_put(struct mlxsw_sp *mlxsw_sp, u8 prr_index) mlxsw_sp_port_range_reg_destroy(mlxsw_sp, prr); } +static u64 mlxsw_sp_port_range_reg_occ_get(void *priv) +{ + struct mlxsw_sp_port_range_core *pr_core = priv; + + return atomic_read(&pr_core->prr_count); +} + int mlxsw_sp_port_range_init(struct mlxsw_sp *mlxsw_sp) { struct mlxsw_sp_port_range_core *pr_core; @@ -168,6 +180,11 @@ int mlxsw_sp_port_range_init(struct mlxsw_sp *mlxsw_sp) pr_core->prr_ids.max = max - 1; xa_init_flags(&pr_core->prr_xa, XA_FLAGS_ALLOC); + devl_resource_occ_get_register(priv_to_devlink(core), + MLXSW_SP_RESOURCE_PORT_RANGE_REGISTERS, + mlxsw_sp_port_range_reg_occ_get, + pr_core); + return 0; } @@ -175,6 +192,8 @@ void mlxsw_sp_port_range_fini(struct mlxsw_sp *mlxsw_sp) { struct mlxsw_sp_port_range_core *pr_core = mlxsw_sp->pr_core; + devl_resource_occ_get_unregister(priv_to_devlink(mlxsw_sp->core), + MLXSW_SP_RESOURCE_PORT_RANGE_REGISTERS); WARN_ON(!xa_empty(&pr_core->prr_xa)); xa_destroy(&pr_core->prr_xa); kfree(pr_core); -- cgit From d65f24c9fa6917f1c32c52cc920f478485a0c6d6 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:58 +0200 Subject: mlxsw: spectrum_acl: Add port range key element Add the port range key element to supported key blocks so that it could be used to match on the output of the port range registers. Each bit in the element can be used to match on the output of the port range register with the corresponding index. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/f0423f6ee9e36c6b0a426bc9995f42223c48f2db.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c | 1 + drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c | 3 +++ 3 files changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c index f0b2963ebac3..7870327d921b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c @@ -43,6 +43,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4), MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1), + MLXSW_AFK_ELEMENT_INFO_U32(L4_PORT_RANGE, 0x40, 1, 16), }; struct mlxsw_afk { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h index 65a4abadc7db..2eac7582c31a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h @@ -36,6 +36,7 @@ enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB, MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB, MLXSW_AFK_ELEMENT_FDB_MISS, + MLXSW_AFK_ELEMENT_L4_PORT_RANGE, MLXSW_AFK_ELEMENT_MAX, }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c index 4dea39f2b304..b7f58605b6c7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c @@ -31,12 +31,14 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = { static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = { MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4), + MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16), MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8), MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16), }; static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = { MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4), + MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16), MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8), MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16), }; @@ -205,6 +207,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = { static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = { MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */ + MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 0, 16), }; static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = { -- cgit From 898979c7238a5b465b55c7027129fb51fab908c5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:43:59 +0200 Subject: mlxsw: spectrum_acl: Pass main driver structure to mlxsw_sp_acl_rulei_destroy() The main driver structure will be needed in this function by a subsequent patch, so pass it. No functional changes intended. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/24d96a4e21310e5de2951ace58263db35e44a0df.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index a74652ea4d7c..4a1bf2d39fa0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -994,7 +994,8 @@ void mlxsw_sp_acl_ruleset_prio_get(struct mlxsw_sp_acl_ruleset *ruleset, struct mlxsw_sp_acl_rule_info * mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl, struct mlxsw_afa_block *afa_block); -void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp_acl_rule_info *rulei); +void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei); int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei); void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei, unsigned int priority); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c index 3a636f753607..dfcdd37e797b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c @@ -90,7 +90,7 @@ mlxsw_sp1_acl_ctcam_region_catchall_add(struct mlxsw_sp *mlxsw_sp, err_entry_add: err_rulei_commit: err_rulei_act_continue: - mlxsw_sp_acl_rulei_destroy(rulei); + mlxsw_sp_acl_rulei_destroy(mlxsw_sp, rulei); err_rulei_create: mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk); return err; @@ -105,7 +105,7 @@ mlxsw_sp1_acl_ctcam_region_catchall_del(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->cregion, ®ion->catchall.cchunk, ®ion->catchall.centry); - mlxsw_sp_acl_rulei_destroy(rulei); + mlxsw_sp_acl_rulei_destroy(mlxsw_sp, rulei); mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 0423ac262d89..7240b74b4883 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -339,7 +339,8 @@ err_afa_block_create: return ERR_PTR(err); } -void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp_acl_rule_info *rulei) +void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei) { if (rulei->action_created) mlxsw_afa_block_destroy(rulei->act_block); @@ -834,7 +835,7 @@ void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; - mlxsw_sp_acl_rulei_destroy(rule->rulei); + mlxsw_sp_acl_rulei_destroy(mlxsw_sp, rule->rulei); kfree(rule); mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset); } -- cgit From fe22f7410527c2077223b5fd0fc0458db912f0db Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 11 Jul 2023 18:44:00 +0200 Subject: mlxsw: spectrum_flower: Add ability to match on port ranges Add the ability to match on port ranges by utilizing the previously added port range registers and the port range key element. Up to two port range registers can be used for each filter, one for source port and another for destination port. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/df4385a9592917e9a22ebff339e0463e4a8dfa82.1689092769.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 6 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 6 ++ .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 68 ++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4a1bf2d39fa0..c6231e62a371 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -867,9 +867,13 @@ struct mlxsw_sp_acl_rule_info { egress_bind_blocker:1, counter_valid:1, policer_index_valid:1, - ipv6_valid:1; + ipv6_valid:1, + src_port_range_reg_valid:1, + dst_port_range_reg_valid:1; unsigned int counter_index; u16 policer_index; + u8 src_port_range_reg_index; + u8 dst_port_range_reg_index; struct { u32 prev_val; enum mlxsw_sp_acl_mangle_field prev_field; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 7240b74b4883..186161a3459d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -344,6 +344,12 @@ void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, { if (rulei->action_created) mlxsw_afa_block_destroy(rulei->act_block); + if (rulei->src_port_range_reg_valid) + mlxsw_sp_port_range_reg_put(mlxsw_sp, + rulei->src_port_range_reg_index); + if (rulei->dst_port_range_reg_valid) + mlxsw_sp_port_range_reg_put(mlxsw_sp, + rulei->dst_port_range_reg_index); kfree(rulei); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 72917f09e806..8329100479b3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -418,6 +418,68 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, return 0; } +static int +mlxsw_sp_flower_parse_ports_range(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei, + struct flow_cls_offload *f, u8 ip_proto) +{ + const struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_match_ports_range match; + u32 key_mask_value = 0; + + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS_RANGE)) + return 0; + + if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) { + NL_SET_ERR_MSG_MOD(f->common.extack, "Only UDP and TCP keys are supported"); + return -EINVAL; + } + + flow_rule_match_ports_range(rule, &match); + + if (match.mask->tp_min.src) { + struct mlxsw_sp_port_range range = { + .min = ntohs(match.key->tp_min.src), + .max = ntohs(match.key->tp_max.src), + .source = true, + }; + u8 prr_index; + int err; + + err = mlxsw_sp_port_range_reg_get(mlxsw_sp, &range, + f->common.extack, &prr_index); + if (err) + return err; + + rulei->src_port_range_reg_index = prr_index; + rulei->src_port_range_reg_valid = true; + key_mask_value |= BIT(prr_index); + } + + if (match.mask->tp_min.dst) { + struct mlxsw_sp_port_range range = { + .min = ntohs(match.key->tp_min.dst), + .max = ntohs(match.key->tp_max.dst), + }; + u8 prr_index; + int err; + + err = mlxsw_sp_port_range_reg_get(mlxsw_sp, &range, + f->common.extack, &prr_index); + if (err) + return err; + + rulei->dst_port_range_reg_index = prr_index; + rulei->dst_port_range_reg_valid = true; + key_mask_value |= BIT(prr_index); + } + + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_L4_PORT_RANGE, + key_mask_value, key_mask_value); + + return 0; +} + static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, struct flow_cls_offload *f, @@ -503,6 +565,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT(FLOW_DISSECTOR_KEY_PORTS) | + BIT(FLOW_DISSECTOR_KEY_PORTS_RANGE) | BIT(FLOW_DISSECTOR_KEY_TCP) | BIT(FLOW_DISSECTOR_KEY_IP) | BIT(FLOW_DISSECTOR_KEY_VLAN))) { @@ -604,6 +667,11 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_flower_parse_ports(mlxsw_sp, rulei, f, ip_proto); if (err) return err; + + err = mlxsw_sp_flower_parse_ports_range(mlxsw_sp, rulei, f, ip_proto); + if (err) + return err; + err = mlxsw_sp_flower_parse_tcp(mlxsw_sp, rulei, f, ip_proto); if (err) return err; -- cgit From ba2274dcfda859b8a27193e68ad37bfe4da28ddc Mon Sep 17 00:00:00 2001 From: Jose Ignacio Tornos Martinez Date: Tue, 11 Jul 2023 08:28:13 +0200 Subject: net: wwan: t7xx: Add AP CLDMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At this moment with the current status, t7xx is not functional due to problems like this after connection, if there is no activity: [ 57.370534] mtk_t7xx 0000:72:00.0: [PM] SAP suspend error: -110 [ 57.370581] mtk_t7xx 0000:72:00.0: can't suspend (t7xx_pci_pm_runtime_suspend [mtk_t7xx] returned -110) because after this, the traffic no longer works. The complete series 'net: wwan: t7xx: fw flashing & coredump support' was reverted because of issues with the pci implementation. In order to have at least the modem working, it would be enough if just the first commit of the series is re-applied: d20ef656f994 net: wwan: t7xx: Add AP CLDMA With that, the Application Processor would be controlled, correctly suspended and the commented problems would be fixed (I am testing here like this with no related issue). This commit is independent of the others and not related to the commented pci implementation for the new features: fw flashing and coredump collection. Use v2 patch version of d20ef656f994 as JinJian Song suggests (https://patchwork.kernel.org/project/netdevbpf/patch/20230105154215.198828-1-m.chetan.kumar@linux.intel.com/). Original text from the commit that would be re-applied: d20ef656f994 net: wwan: t7xx: Add AP CLDMA Author: Haijun Liu Date: Tue Aug 16 09:53:28 2022 +0530 The t7xx device contains two Cross Layer DMA (CLDMA) interfaces to communicate with AP and Modem processors respectively. So far only MD-CLDMA was being used, this patch enables AP-CLDMA. Rename small Application Processor (sAP) to AP. Signed-off-by: Haijun Liu Co-developed-by: Madhusmita Sahu Signed-off-by: Madhusmita Sahu Signed-off-by: Moises Veleta Signed-off-by: Devegowda Chandrashekar Signed-off-by: M Chetan Kumar Reviewed-by: Ilpo Järvinen Reviewed-by: Sergey Ryazanov Reviewed-by: Jesse Brandeburg Signed-off-by: Jose Ignacio Tornos Martinez Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230711062817.6108-1-jtornosm@redhat.com Signed-off-by: Jakub Kicinski --- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 17 ++++--- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 2 +- drivers/net/wwan/t7xx/t7xx_mhccif.h | 1 + drivers/net/wwan/t7xx/t7xx_modem_ops.c | 76 ++++++++++++++++++++++++------ drivers/net/wwan/t7xx/t7xx_modem_ops.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 6 ++- drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c | 8 +++- drivers/net/wwan/t7xx/t7xx_port_proxy.c | 18 +++++-- drivers/net/wwan/t7xx/t7xx_reg.h | 2 +- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 13 ++++- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 2 + 11 files changed, 116 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c index 7162bf38a8c9..cc70360364b7 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c @@ -1066,13 +1066,18 @@ static void t7xx_hw_info_init(struct cldma_ctrl *md_ctrl) struct t7xx_cldma_hw *hw_info = &md_ctrl->hw_info; u32 phy_ao_base, phy_pd_base; - if (md_ctrl->hif_id != CLDMA_ID_MD) - return; - - phy_ao_base = CLDMA1_AO_BASE; - phy_pd_base = CLDMA1_PD_BASE; - hw_info->phy_interrupt_id = CLDMA1_INT; hw_info->hw_mode = MODE_BIT_64; + + if (md_ctrl->hif_id == CLDMA_ID_MD) { + phy_ao_base = CLDMA1_AO_BASE; + phy_pd_base = CLDMA1_PD_BASE; + hw_info->phy_interrupt_id = CLDMA1_INT; + } else { + phy_ao_base = CLDMA0_AO_BASE; + phy_pd_base = CLDMA0_PD_BASE; + hw_info->phy_interrupt_id = CLDMA0_INT; + } + hw_info->ap_ao_base = t7xx_pcie_addr_transfer(pbase->pcie_ext_reg_base, pbase->pcie_dev_reg_trsl_addr, phy_ao_base); hw_info->ap_pdn_base = t7xx_pcie_addr_transfer(pbase->pcie_ext_reg_base, diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.h b/drivers/net/wwan/t7xx/t7xx_hif_cldma.h index 47a35e552da7..4410bac6993a 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.h +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.h @@ -34,7 +34,7 @@ /** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel. - * @CLDMA_ID_AP: Application Processor control channel (not used at the moment). + * @CLDMA_ID_AP: Application Processor control channel. * @CLDMA_NUM: Number of CLDMA HW units available. */ enum cldma_id { diff --git a/drivers/net/wwan/t7xx/t7xx_mhccif.h b/drivers/net/wwan/t7xx/t7xx_mhccif.h index 209b386bc088..20c50dce9fc3 100644 --- a/drivers/net/wwan/t7xx/t7xx_mhccif.h +++ b/drivers/net/wwan/t7xx/t7xx_mhccif.h @@ -25,6 +25,7 @@ D2H_INT_EXCEPTION_CLEARQ_DONE | \ D2H_INT_EXCEPTION_ALLQ_RESET | \ D2H_INT_PORT_ENUM | \ + D2H_INT_ASYNC_AP_HK | \ D2H_INT_ASYNC_MD_HK) void t7xx_mhccif_mask_set(struct t7xx_pci_dev *t7xx_dev, u32 val); diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c index 7d0f5e4f0a78..24e7d491468e 100644 --- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c +++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c @@ -44,6 +44,7 @@ #include "t7xx_state_monitor.h" #define RT_ID_MD_PORT_ENUM 0 +#define RT_ID_AP_PORT_ENUM 1 /* Modem feature query identification code - "ICCC" */ #define MD_FEATURE_QUERY_ID 0x49434343 @@ -298,6 +299,7 @@ static void t7xx_md_exception(struct t7xx_modem *md, enum hif_ex_stage stage) } t7xx_cldma_exception(md->md_ctrl[CLDMA_ID_MD], stage); + t7xx_cldma_exception(md->md_ctrl[CLDMA_ID_AP], stage); if (stage == HIF_EX_INIT) t7xx_mhccif_h2d_swint_trigger(t7xx_dev, H2D_CH_EXCEPTION_ACK); @@ -426,7 +428,7 @@ static int t7xx_parse_host_rt_data(struct t7xx_fsm_ctl *ctl, struct t7xx_sys_inf if (ft_spt_st != MTK_FEATURE_MUST_BE_SUPPORTED) return -EINVAL; - if (i == RT_ID_MD_PORT_ENUM) + if (i == RT_ID_MD_PORT_ENUM || i == RT_ID_AP_PORT_ENUM) t7xx_port_enum_msg_handler(ctl->md, rt_feature->data); } @@ -456,12 +458,12 @@ static int t7xx_core_reset(struct t7xx_modem *md) return 0; } -static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_fsm_ctl *ctl, +static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_sys_info *core_info, + struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_event_state event_id, enum t7xx_fsm_event_state err_detect) { struct t7xx_fsm_event *event = NULL, *event_next; - struct t7xx_sys_info *core_info = &md->core_md; struct device *dev = &md->t7xx_dev->pdev->dev; unsigned long flags; int ret; @@ -531,19 +533,33 @@ static void t7xx_md_hk_wq(struct work_struct *work) t7xx_cldma_start(md->md_ctrl[CLDMA_ID_MD]); t7xx_fsm_broadcast_state(ctl, MD_STATE_WAITING_FOR_HS2); md->core_md.handshake_ongoing = true; - t7xx_core_hk_handler(md, ctl, FSM_EVENT_MD_HS2, FSM_EVENT_MD_HS2_EXIT); + t7xx_core_hk_handler(md, &md->core_md, ctl, FSM_EVENT_MD_HS2, FSM_EVENT_MD_HS2_EXIT); +} + +static void t7xx_ap_hk_wq(struct work_struct *work) +{ + struct t7xx_modem *md = container_of(work, struct t7xx_modem, ap_handshake_work); + struct t7xx_fsm_ctl *ctl = md->fsm_ctl; + + /* Clear the HS2 EXIT event appended in t7xx_core_reset(). */ + t7xx_fsm_clr_event(ctl, FSM_EVENT_AP_HS2_EXIT); + t7xx_cldma_stop(md->md_ctrl[CLDMA_ID_AP]); + t7xx_cldma_switch_cfg(md->md_ctrl[CLDMA_ID_AP]); + t7xx_cldma_start(md->md_ctrl[CLDMA_ID_AP]); + md->core_ap.handshake_ongoing = true; + t7xx_core_hk_handler(md, &md->core_ap, ctl, FSM_EVENT_AP_HS2, FSM_EVENT_AP_HS2_EXIT); } void t7xx_md_event_notify(struct t7xx_modem *md, enum md_event_id evt_id) { struct t7xx_fsm_ctl *ctl = md->fsm_ctl; - void __iomem *mhccif_base; unsigned int int_sta; unsigned long flags; switch (evt_id) { case FSM_PRE_START: - t7xx_mhccif_mask_clr(md->t7xx_dev, D2H_INT_PORT_ENUM); + t7xx_mhccif_mask_clr(md->t7xx_dev, D2H_INT_PORT_ENUM | D2H_INT_ASYNC_MD_HK | + D2H_INT_ASYNC_AP_HK); break; case FSM_START: @@ -556,16 +572,26 @@ void t7xx_md_event_notify(struct t7xx_modem *md, enum md_event_id evt_id) ctl->exp_flg = true; md->exp_id &= ~D2H_INT_EXCEPTION_INIT; md->exp_id &= ~D2H_INT_ASYNC_MD_HK; + md->exp_id &= ~D2H_INT_ASYNC_AP_HK; } else if (ctl->exp_flg) { md->exp_id &= ~D2H_INT_ASYNC_MD_HK; - } else if (md->exp_id & D2H_INT_ASYNC_MD_HK) { - queue_work(md->handshake_wq, &md->handshake_work); - md->exp_id &= ~D2H_INT_ASYNC_MD_HK; - mhccif_base = md->t7xx_dev->base_addr.mhccif_rc_base; - iowrite32(D2H_INT_ASYNC_MD_HK, mhccif_base + REG_EP2RC_SW_INT_ACK); - t7xx_mhccif_mask_set(md->t7xx_dev, D2H_INT_ASYNC_MD_HK); + md->exp_id &= ~D2H_INT_ASYNC_AP_HK; } else { - t7xx_mhccif_mask_clr(md->t7xx_dev, D2H_INT_ASYNC_MD_HK); + void __iomem *mhccif_base = md->t7xx_dev->base_addr.mhccif_rc_base; + + if (md->exp_id & D2H_INT_ASYNC_MD_HK) { + queue_work(md->handshake_wq, &md->handshake_work); + md->exp_id &= ~D2H_INT_ASYNC_MD_HK; + iowrite32(D2H_INT_ASYNC_MD_HK, mhccif_base + REG_EP2RC_SW_INT_ACK); + t7xx_mhccif_mask_set(md->t7xx_dev, D2H_INT_ASYNC_MD_HK); + } + + if (md->exp_id & D2H_INT_ASYNC_AP_HK) { + queue_work(md->handshake_wq, &md->ap_handshake_work); + md->exp_id &= ~D2H_INT_ASYNC_AP_HK; + iowrite32(D2H_INT_ASYNC_AP_HK, mhccif_base + REG_EP2RC_SW_INT_ACK); + t7xx_mhccif_mask_set(md->t7xx_dev, D2H_INT_ASYNC_AP_HK); + } } spin_unlock_irqrestore(&md->exp_lock, flags); @@ -578,6 +604,7 @@ void t7xx_md_event_notify(struct t7xx_modem *md, enum md_event_id evt_id) case FSM_READY: t7xx_mhccif_mask_set(md->t7xx_dev, D2H_INT_ASYNC_MD_HK); + t7xx_mhccif_mask_set(md->t7xx_dev, D2H_INT_ASYNC_AP_HK); break; default: @@ -629,6 +656,12 @@ static struct t7xx_modem *t7xx_md_alloc(struct t7xx_pci_dev *t7xx_dev) md->core_md.feature_set[RT_ID_MD_PORT_ENUM] &= ~FEATURE_MSK; md->core_md.feature_set[RT_ID_MD_PORT_ENUM] |= FIELD_PREP(FEATURE_MSK, MTK_FEATURE_MUST_BE_SUPPORTED); + + INIT_WORK(&md->ap_handshake_work, t7xx_ap_hk_wq); + md->core_ap.feature_set[RT_ID_AP_PORT_ENUM] &= ~FEATURE_MSK; + md->core_ap.feature_set[RT_ID_AP_PORT_ENUM] |= + FIELD_PREP(FEATURE_MSK, MTK_FEATURE_MUST_BE_SUPPORTED); + return md; } @@ -640,6 +673,7 @@ int t7xx_md_reset(struct t7xx_pci_dev *t7xx_dev) md->exp_id = 0; t7xx_fsm_reset(md); t7xx_cldma_reset(md->md_ctrl[CLDMA_ID_MD]); + t7xx_cldma_reset(md->md_ctrl[CLDMA_ID_AP]); t7xx_port_proxy_reset(md->port_prox); md->md_init_finish = true; return t7xx_core_reset(md); @@ -669,6 +703,10 @@ int t7xx_md_init(struct t7xx_pci_dev *t7xx_dev) if (ret) goto err_destroy_hswq; + ret = t7xx_cldma_alloc(CLDMA_ID_AP, t7xx_dev); + if (ret) + goto err_destroy_hswq; + ret = t7xx_fsm_init(md); if (ret) goto err_destroy_hswq; @@ -681,12 +719,16 @@ int t7xx_md_init(struct t7xx_pci_dev *t7xx_dev) if (ret) goto err_uninit_ccmni; - ret = t7xx_port_proxy_init(md); + ret = t7xx_cldma_init(md->md_ctrl[CLDMA_ID_AP]); if (ret) goto err_uninit_md_cldma; + ret = t7xx_port_proxy_init(md); + if (ret) + goto err_uninit_ap_cldma; + ret = t7xx_fsm_append_cmd(md->fsm_ctl, FSM_CMD_START, 0); - if (ret) /* fsm_uninit flushes cmd queue */ + if (ret) /* t7xx_fsm_uninit() flushes cmd queue */ goto err_uninit_proxy; t7xx_md_sys_sw_init(t7xx_dev); @@ -696,6 +738,9 @@ int t7xx_md_init(struct t7xx_pci_dev *t7xx_dev) err_uninit_proxy: t7xx_port_proxy_uninit(md->port_prox); +err_uninit_ap_cldma: + t7xx_cldma_exit(md->md_ctrl[CLDMA_ID_AP]); + err_uninit_md_cldma: t7xx_cldma_exit(md->md_ctrl[CLDMA_ID_MD]); @@ -722,6 +767,7 @@ void t7xx_md_exit(struct t7xx_pci_dev *t7xx_dev) t7xx_fsm_append_cmd(md->fsm_ctl, FSM_CMD_PRE_STOP, FSM_CMD_FLAG_WAIT_FOR_COMPLETION); t7xx_port_proxy_uninit(md->port_prox); + t7xx_cldma_exit(md->md_ctrl[CLDMA_ID_AP]); t7xx_cldma_exit(md->md_ctrl[CLDMA_ID_MD]); t7xx_ccmni_exit(t7xx_dev); t7xx_fsm_uninit(md); diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.h b/drivers/net/wwan/t7xx/t7xx_modem_ops.h index 7469ed636ae8..abe633cf7adc 100644 --- a/drivers/net/wwan/t7xx/t7xx_modem_ops.h +++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.h @@ -66,10 +66,12 @@ struct t7xx_modem { struct cldma_ctrl *md_ctrl[CLDMA_NUM]; struct t7xx_pci_dev *t7xx_dev; struct t7xx_sys_info core_md; + struct t7xx_sys_info core_ap; bool md_init_finish; bool rgu_irq_asserted; struct workqueue_struct *handshake_wq; struct work_struct handshake_work; + struct work_struct ap_handshake_work; struct t7xx_fsm_ctl *fsm_ctl; struct port_proxy *port_prox; unsigned int exp_id; diff --git a/drivers/net/wwan/t7xx/t7xx_port.h b/drivers/net/wwan/t7xx/t7xx_port.h index 8ea9079af997..4ae8a00a8532 100644 --- a/drivers/net/wwan/t7xx/t7xx_port.h +++ b/drivers/net/wwan/t7xx/t7xx_port.h @@ -36,9 +36,13 @@ /* Channel ID and Message ID definitions. * The channel number consists of peer_id(15:12) , channel_id(11:0) * peer_id: - * 0:reserved, 1: to sAP, 2: to MD + * 0:reserved, 1: to AP, 2: to MD */ enum port_ch { + /* to AP */ + PORT_CH_AP_CONTROL_RX = 0x1000, + PORT_CH_AP_CONTROL_TX = 0x1001, + /* to MD */ PORT_CH_CONTROL_RX = 0x2000, PORT_CH_CONTROL_TX = 0x2001, diff --git a/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c b/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c index 68430b130a67..ae632ef96698 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c +++ b/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c @@ -167,8 +167,12 @@ static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb) case CTL_ID_HS2_MSG: skb_pull(skb, sizeof(*ctrl_msg_h)); - if (port_conf->rx_ch == PORT_CH_CONTROL_RX) { - ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_HS2, skb->data, + if (port_conf->rx_ch == PORT_CH_CONTROL_RX || + port_conf->rx_ch == PORT_CH_AP_CONTROL_RX) { + int event = port_conf->rx_ch == PORT_CH_CONTROL_RX ? + FSM_EVENT_MD_HS2 : FSM_EVENT_AP_HS2; + + ret = t7xx_fsm_append_event(ctl, event, skb->data, le32_to_cpu(ctrl_msg_h->data_length)); if (ret) dev_err(port->dev, "Failed to append Handshake 2 event"); diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c index 894b1d11b2c9..274846d39fbf 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c +++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c @@ -48,7 +48,7 @@ i < (proxy)->port_count; \ i++, (p) = &(proxy)->ports[i]) -static const struct t7xx_port_conf t7xx_md_port_conf[] = { +static const struct t7xx_port_conf t7xx_port_conf[] = { { .tx_ch = PORT_CH_UART2_TX, .rx_ch = PORT_CH_UART2_RX, @@ -89,6 +89,14 @@ static const struct t7xx_port_conf t7xx_md_port_conf[] = { .path_id = CLDMA_ID_MD, .ops = &ctl_port_ops, .name = "t7xx_ctrl", + }, { + .tx_ch = PORT_CH_AP_CONTROL_TX, + .rx_ch = PORT_CH_AP_CONTROL_RX, + .txq_index = Q_IDX_CTRL, + .rxq_index = Q_IDX_CTRL, + .path_id = CLDMA_ID_AP, + .ops = &ctl_port_ops, + .name = "t7xx_ap_ctrl", }, }; @@ -428,6 +436,9 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) if (port_conf->tx_ch == PORT_CH_CONTROL_TX) md->core_md.ctl_port = port; + if (port_conf->tx_ch == PORT_CH_AP_CONTROL_TX) + md->core_ap.ctl_port = port; + port->t7xx_dev = md->t7xx_dev; port->dev = &md->t7xx_dev->pdev->dev; spin_lock_init(&port->port_update_lock); @@ -442,7 +453,7 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) static int t7xx_proxy_alloc(struct t7xx_modem *md) { - unsigned int port_count = ARRAY_SIZE(t7xx_md_port_conf); + unsigned int port_count = ARRAY_SIZE(t7xx_port_conf); struct device *dev = &md->t7xx_dev->pdev->dev; struct port_proxy *port_prox; int i; @@ -456,7 +467,7 @@ static int t7xx_proxy_alloc(struct t7xx_modem *md) port_prox->dev = dev; for (i = 0; i < port_count; i++) - port_prox->ports[i].port_conf = &t7xx_md_port_conf[i]; + port_prox->ports[i].port_conf = &t7xx_port_conf[i]; port_prox->port_count = port_count; t7xx_proxy_init_all_ports(md); @@ -481,6 +492,7 @@ int t7xx_port_proxy_init(struct t7xx_modem *md) if (ret) return ret; + t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_AP], t7xx_port_proxy_recv_skb); t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_MD], t7xx_port_proxy_recv_skb); return 0; } diff --git a/drivers/net/wwan/t7xx/t7xx_reg.h b/drivers/net/wwan/t7xx/t7xx_reg.h index 7c1b81091a0f..c41d7d094c08 100644 --- a/drivers/net/wwan/t7xx/t7xx_reg.h +++ b/drivers/net/wwan/t7xx/t7xx_reg.h @@ -56,7 +56,7 @@ #define D2H_INT_RESUME_ACK BIT(12) #define D2H_INT_SUSPEND_ACK_AP BIT(13) #define D2H_INT_RESUME_ACK_AP BIT(14) -#define D2H_INT_ASYNC_SAP_HK BIT(15) +#define D2H_INT_ASYNC_AP_HK BIT(15) #define D2H_INT_ASYNC_MD_HK BIT(16) /* Register base */ diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 0bcca08ff2bd..80edb8e75a6a 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -285,8 +285,9 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl) t7xx_fsm_broadcast_state(ctl, MD_STATE_WAITING_FOR_HS1); t7xx_md_event_notify(md, FSM_START); - wait_event_interruptible_timeout(ctl->async_hk_wq, md->core_md.ready || ctl->exp_flg, - HZ * 60); + wait_event_interruptible_timeout(ctl->async_hk_wq, + (md->core_md.ready && md->core_ap.ready) || + ctl->exp_flg, HZ * 60); dev = &md->t7xx_dev->pdev->dev; if (ctl->exp_flg) @@ -297,6 +298,13 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl) if (md->core_md.handshake_ongoing) t7xx_fsm_append_event(ctl, FSM_EVENT_MD_HS2_EXIT, NULL, 0); + fsm_routine_exception(ctl, NULL, EXCEPTION_HS_TIMEOUT); + return -ETIMEDOUT; + } else if (!md->core_ap.ready) { + dev_err(dev, "AP handshake timeout\n"); + if (md->core_ap.handshake_ongoing) + t7xx_fsm_append_event(ctl, FSM_EVENT_AP_HS2_EXIT, NULL, 0); + fsm_routine_exception(ctl, NULL, EXCEPTION_HS_TIMEOUT); return -ETIMEDOUT; } @@ -335,6 +343,7 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command return; } + t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_AP]); t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_MD]); fsm_finish_command(ctl, cmd, fsm_routine_starting(ctl)); } diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h index b1af0259d4c5..b6e76f3903c8 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h @@ -38,10 +38,12 @@ enum t7xx_fsm_state { enum t7xx_fsm_event_state { FSM_EVENT_INVALID, FSM_EVENT_MD_HS2, + FSM_EVENT_AP_HS2, FSM_EVENT_MD_EX, FSM_EVENT_MD_EX_REC_OK, FSM_EVENT_MD_EX_PASS, FSM_EVENT_MD_HS2_EXIT, + FSM_EVENT_AP_HS2_EXIT, FSM_EVENT_MAX }; -- cgit From bec9ce34075e4b1c4a36d9eb7a40e84929d12aa8 Mon Sep 17 00:00:00 2001 From: Ziyang Chen Date: Wed, 12 Jul 2023 14:35:51 +0200 Subject: nfp: prevent dropped counter increment during probe The dev_rx_discards counter will increment by one when an interface is toggled up and down. The main reason is that the driver first sends a `NFP_NET_CFG_CTRL_ENABLE` configuration packet to the NIC to perform port initialisation when an interface is set up. But there is a race between physical link up and free list queue initialization which may lead to the configuration packet being discarded. To address this problem a new bit NFP_NET_CFG_CTRL_FREELIST_EN is added to perform free list initialisation on the NIC. The FREELIST_EN should be sent in advance to initialize free list queue. When a port is set to down, FREELIST_EN should be sent after CTRL_ENABLE to avoid packet discards. Signed-off-by: Ziyang Chen Acked-by: Simon Horman Signed-off-by: Louis Peens Link: https://lore.kernel.org/r/20230712123551.13858-1-louis.peens@corigine.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/netronome/nfp/nfp_net_common.c | 54 +++++++++++++++++++--- drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 1 + 2 files changed, 48 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 6b1fb5708434..f18c791cf698 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -924,7 +924,7 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn, const u8 *addr) */ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) { - u32 new_ctrl, update; + u32 new_ctrl, new_ctrl_w1, update; unsigned int r; int err; @@ -937,14 +937,29 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG) new_ctrl &= ~NFP_NET_CFG_CTRL_RINGCFG; - nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, 0); - nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, 0); + if (!(nn->cap_w1 & NFP_NET_CFG_CTRL_FREELIST_EN)) { + nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, 0); + nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, 0); + } nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); err = nfp_net_reconfig(nn, update); if (err) nn_err(nn, "Could not disable device: %d\n", err); + if (nn->cap_w1 & NFP_NET_CFG_CTRL_FREELIST_EN) { + new_ctrl_w1 = nn->dp.ctrl_w1; + new_ctrl_w1 &= ~NFP_NET_CFG_CTRL_FREELIST_EN; + nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, 0); + nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, 0); + + nn_writel(nn, NFP_NET_CFG_CTRL_WORD1, new_ctrl_w1); + err = nfp_net_reconfig(nn, update); + if (err) + nn_err(nn, "Could not disable FREELIST_EN: %d\n", err); + nn->dp.ctrl_w1 = new_ctrl_w1; + } + for (r = 0; r < nn->dp.num_rx_rings; r++) { nfp_net_rx_ring_reset(&nn->dp.rx_rings[r]); if (nfp_net_has_xsk_pool_slow(&nn->dp, nn->dp.rx_rings[r].idx)) @@ -964,11 +979,12 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) */ static int nfp_net_set_config_and_enable(struct nfp_net *nn) { - u32 bufsz, new_ctrl, update = 0; + u32 bufsz, new_ctrl, new_ctrl_w1, update = 0; unsigned int r; int err; new_ctrl = nn->dp.ctrl; + new_ctrl_w1 = nn->dp.ctrl_w1; if (nn->dp.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) { nfp_net_rss_write_key(nn); @@ -1001,16 +1017,25 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn) bufsz = nn->dp.fl_bufsz - nn->dp.rx_dma_off - NFP_NET_RX_BUF_NON_DATA; nn_writel(nn, NFP_NET_CFG_FLBUFSZ, bufsz); - /* Enable device */ - new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; + /* Enable device + * Step 1: Replace the CTRL_ENABLE by NFP_NET_CFG_CTRL_FREELIST_EN if + * FREELIST_EN exits. + */ + if (nn->cap_w1 & NFP_NET_CFG_CTRL_FREELIST_EN) + new_ctrl_w1 |= NFP_NET_CFG_CTRL_FREELIST_EN; + else + new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; update |= NFP_NET_CFG_UPDATE_GEN; update |= NFP_NET_CFG_UPDATE_MSIX; update |= NFP_NET_CFG_UPDATE_RING; if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG) new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG; + /* Step 2: Send the configuration and write the freelist. + * - The freelist only need to be written once. + */ nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); - nn_writel(nn, NFP_NET_CFG_CTRL_WORD1, nn->dp.ctrl_w1); + nn_writel(nn, NFP_NET_CFG_CTRL_WORD1, new_ctrl_w1); err = nfp_net_reconfig(nn, update); if (err) { nfp_net_clear_config_and_disable(nn); @@ -1018,10 +1043,25 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn) } nn->dp.ctrl = new_ctrl; + nn->dp.ctrl_w1 = new_ctrl_w1; for (r = 0; r < nn->dp.num_rx_rings; r++) nfp_net_rx_ring_fill_freelist(&nn->dp, &nn->dp.rx_rings[r]); + /* Step 3: Do the NFP_NET_CFG_CTRL_ENABLE. Send the configuration. + */ + if (nn->cap_w1 & NFP_NET_CFG_CTRL_FREELIST_EN) { + new_ctrl |= NFP_NET_CFG_CTRL_ENABLE; + nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); + + err = nfp_net_reconfig(nn, update); + if (err) { + nfp_net_clear_config_and_disable(nn); + return err; + } + nn->dp.ctrl = new_ctrl; + } + return 0; } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h index 669b9dccb6a9..3e63f6d6a563 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h @@ -268,6 +268,7 @@ #define NFP_NET_CFG_CTRL_PKT_TYPE (0x1 << 0) /* Pkttype offload */ #define NFP_NET_CFG_CTRL_IPSEC (0x1 << 1) /* IPsec offload */ #define NFP_NET_CFG_CTRL_MCAST_FILTER (0x1 << 2) /* Multicast Filter */ +#define NFP_NET_CFG_CTRL_FREELIST_EN (0x1 << 6) /* Freelist enable flag bit */ #define NFP_NET_CFG_CAP_WORD1 0x00a4 -- cgit From d26979f1cef71d6fa036f6cedfa0059715092503 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:50 +0200 Subject: net: stmmac: replace the has_integrated_pcs field with a flag struct plat_stmmacenet_data contains several boolean fields that could be easily replaced with a common integer 'flags' bitfield and bit defines. Start the process with the has_integrated_pcs field. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-2-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 757504ebb676..3cfa4d2e1929 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -786,7 +786,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) plat_dat->rx_clk_runs_in_lpi = 1; - plat_dat->has_integrated_pcs = data->has_integrated_pcs; + if (data->has_integrated_pcs) + plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS; if (ethqos->serdes_phy) { plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4727f7be4f86..38b6cbd8a133 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -5798,7 +5798,8 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv) } /* PCS link status */ - if (priv->hw->pcs && !priv->plat->has_integrated_pcs) { + if (priv->hw->pcs && + !(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS)) { if (priv->xstats.pcs_link) netif_carrier_on(priv->dev); else -- cgit From 309efe6eb499d04b7c09e57298c453b602efe3fd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:51 +0200 Subject: net: stmmac: replace the sph_disable field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-3-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 9f88530c5e8c..0c12ab67c27b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -359,7 +359,7 @@ bypass_clk_reset_gpio: data->fix_mac_speed = tegra_eqos_fix_speed; data->init = tegra_eqos_init; data->bsp_priv = eqos; - data->sph_disable = 1; + data->flags |= STMMAC_FLAG_SPH_DISABLE; err = tegra_eqos_init(pdev, eqos); if (err < 0) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index ab9f876b6df7..ae5db39a3f1b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -459,7 +459,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->has_gmac4 = 1; plat->force_sf_dma_mode = 0; plat->tso_en = 1; - plat->sph_disable = 1; + plat->flags |= STMMAC_FLAG_SPH_DISABLE; /* Multiplying factor to the clk_eee_i clock time * period to make it closer to 100 ns. This value diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 38b6cbd8a133..18e56299363d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7258,7 +7258,8 @@ int stmmac_dvr_probe(struct device *device, dev_info(priv->device, "TSO feature enabled\n"); } - if (priv->dma_cap.sphen && !priv->plat->sph_disable) { + if (priv->dma_cap.sphen && + !(priv->plat->flags & STMMAC_FLAG_SPH_DISABLE)) { ndev->hw_features |= NETIF_F_GRO; priv->sph_cap = true; priv->sph = priv->sph_cap; -- cgit From fd1d62d80ebc1a68ba700e92c9da9d443c08f371 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:52 +0200 Subject: net: stmmac: replace the use_phy_wol field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-4-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 5 ++++- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index ae5db39a3f1b..c690ec1b9bab 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -628,7 +628,7 @@ static int ehl_common_data(struct pci_dev *pdev, { plat->rx_queues_to_use = 8; plat->tx_queues_to_use = 8; - plat->use_phy_wol = 1; + plat->flags |= STMMAC_FLAG_USE_PHY_WOL; plat->safety_feat_cfg->tsoee = 1; plat->safety_feat_cfg->mrxpee = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 73c1dfa7ecb1..4d877d75642d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -588,7 +588,10 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev, int i; plat->interface = priv_plat->phy_mode; - plat->use_phy_wol = priv_plat->mac_wol ? 0 : 1; + if (priv_plat->mac_wol) + plat->flags |= STMMAC_FLAG_USE_PHY_WOL; + else + plat->flags &= ~STMMAC_FLAG_USE_PHY_WOL; plat->riwt_off = 1; plat->maxmtu = ETH_DATA_LEN; plat->host_dma_width = priv_plat->variant->dma_bit_mask; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 18e56299363d..a1a59af3961d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6877,7 +6877,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) */ priv->plat->enh_desc = priv->dma_cap.enh_desc; priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up && - !priv->plat->use_phy_wol; + !(priv->plat->flags & STMMAC_FLAG_USE_PHY_WOL); priv->hw->pmt = priv->plat->pmt; if (priv->dma_cap.hash_tb_sz) { priv->hw->multicast_filter_bins = -- cgit From d8daff284e305409fd640feda7345d0221d782ce Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:53 +0200 Subject: net: stmmac: replace the has_sun8i field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-5-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 1e714380d125..2b5ebb15bfda 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1227,7 +1227,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) plat_dat->interface = interface; plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; plat_dat->tx_coe = 1; - plat_dat->has_sun8i = true; + plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I; plat_dat->bsp_priv = gmac; plat_dat->init = sun8i_dwmac_init; plat_dat->exit = sun8i_dwmac_exit; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a1a59af3961d..3df32658b5bb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -325,7 +325,7 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv) priv->clk_csr = STMMAC_CSR_250_300M; } - if (priv->plat->has_sun8i) { + if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { if (clk_rate > 160000000) priv->clk_csr = 0x03; else if (clk_rate > 80000000) @@ -6856,7 +6856,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) int ret; /* dwmac-sun8i only work in chain mode */ - if (priv->plat->has_sun8i) + if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) chain_mode = 1; priv->chain_mode = chain_mode; -- cgit From 68861a3bcc1caf5c15a56e02090310271fd085e1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:54 +0200 Subject: net: stmmac: replace the tso_en field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-6-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 3 +-- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 ++++-- 7 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 0c12ab67c27b..b5efd9c2eac7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -113,7 +113,7 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, /* dwc-qos needs GMAC4, AAL, TSO and PMT */ plat_dat->has_gmac4 = 1; plat_dat->dma_cfg->aal = 1; - plat_dat->tso_en = 1; + plat_dat->flags |= STMMAC_FLAG_TSO_EN; plat_dat->pmt = 1; return 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index c690ec1b9bab..faa6f4ec6838 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -458,8 +458,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->has_gmac = 0; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 0; - plat->tso_en = 1; - plat->flags |= STMMAC_FLAG_SPH_DISABLE; + plat->flags |= (STMMAC_FLAG_TSO_EN | STMMAC_FLAG_SPH_DISABLE); /* Multiplying factor to the clk_eee_i clock time * period to make it closer to 100 ns. This value diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 3cfa4d2e1929..4b58904ee132 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -783,7 +783,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ethqos->has_emac_ge_3) plat_dat->dwmac4_addrs = &data->dwmac4_addrs; plat_dat->pmt = 1; - plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); + if (of_property_read_bool(np, "snps,tso")) + plat_dat->flags |= STMMAC_FLAG_TSO_EN; if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) plat_dat->rx_clk_runs_in_lpi = 1; if (data->has_integrated_pcs) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c index f8367c5b490b..5e8aa03cffae 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c @@ -290,7 +290,7 @@ static int tegra_mgbe_probe(struct platform_device *pdev) } plat->has_xgmac = 1; - plat->tso_en = 1; + plat->flags |= STMMAC_FLAG_TSO_EN; plat->pmt = 1; plat->bsp_priv = mgbe; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3df32658b5bb..73002ed923aa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -5677,7 +5677,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev, features &= ~NETIF_F_CSUM_MASK; /* Disable tso if asked by ethtool */ - if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { + if ((priv->plat->flags & STMMAC_FLAG_TSO_EN) && (priv->dma_cap.tsoen)) { if (features & NETIF_F_TSO) priv->tso = true; else @@ -7250,7 +7250,7 @@ int stmmac_dvr_probe(struct device *device, ndev->hw_features |= NETIF_F_HW_TC; } - if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { + if ((priv->plat->flags & STMMAC_FLAG_TSO_EN) && (priv->dma_cap.tsoen)) { ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; if (priv->plat->has_gmac4) ndev->hw_features |= NETIF_F_GSO_UDP_L4; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 644bb54f5f02..352b01678c22 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -77,7 +77,7 @@ static int snps_gmac5_default_data(struct pci_dev *pdev, plat->clk_csr = 5; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 1; - plat->tso_en = 1; + plat->flags |= STMMAC_FLAG_TSO_EN; plat->pmt = 1; /* Set default value for multicast hash bins */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 231152ee5a32..f51522cb0061 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -525,7 +525,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->has_gmac4 = 1; plat->has_gmac = 0; plat->pmt = 1; - plat->tso_en = of_property_read_bool(np, "snps,tso"); + if (of_property_read_bool(np, "snps,tso")) + plat->flags |= STMMAC_FLAG_TSO_EN; } if (of_device_is_compatible(np, "snps,dwmac-3.610") || @@ -538,7 +539,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) if (of_device_is_compatible(np, "snps,dwxgmac")) { plat->has_xgmac = 1; plat->pmt = 1; - plat->tso_en = of_property_read_bool(np, "snps,tso"); + if (of_property_read_bool(np, "snps,tso")) + plat->flags |= STMMAC_FLAG_TSO_EN; } dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), -- cgit From efe92571bfc30f251f6f2fa7828aa5f239736abf Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:55 +0200 Subject: net: stmmac: replace the serdes_up_after_phy_linkup field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-7-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c index 5e8aa03cffae..99e2e5a5cd60 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c @@ -337,7 +337,7 @@ static int tegra_mgbe_probe(struct platform_device *pdev) /* Program SID */ writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); - plat->serdes_up_after_phy_linkup = 1; + plat->flags |= STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP; err = stmmac_dvr_probe(&pdev->dev, plat, &res); if (err < 0) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 73002ed923aa..d444514db07e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -991,7 +991,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); u32 old_ctrl, ctrl; - if (priv->plat->serdes_up_after_phy_linkup && priv->plat->serdes_powerup) + if ((priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && + priv->plat->serdes_powerup) priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv); old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); @@ -3838,7 +3839,8 @@ static int __stmmac_open(struct net_device *dev, stmmac_reset_queues_param(priv); - if (!priv->plat->serdes_up_after_phy_linkup && priv->plat->serdes_powerup) { + if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && + priv->plat->serdes_powerup) { ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv); if (ret < 0) { netdev_err(priv->dev, "%s: Serdes powerup failed\n", @@ -7623,7 +7625,8 @@ int stmmac_resume(struct device *dev) stmmac_mdio_reset(priv->mii); } - if (!priv->plat->serdes_up_after_phy_linkup && priv->plat->serdes_powerup) { + if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && + priv->plat->serdes_powerup) { ret = priv->plat->serdes_powerup(ndev, priv->plat->bsp_priv); -- cgit From fc02152bdbb28bd46df66ddcf4f469760c1b8df8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:56 +0200 Subject: net: stmmac: replace the vlan_fail_q_en field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-8-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index faa6f4ec6838..1f1bc99571a5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -560,7 +560,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, /* Set the maxmtu to a default of JUMBO_LEN */ plat->maxmtu = JUMBO_LEN; - plat->vlan_fail_q_en = true; + plat->flags |= STMMAC_FLAG_VLAN_FAIL_Q_EN; /* Use the last Rx queue */ plat->vlan_fail_q = plat->rx_queues_to_use - 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d444514db07e..c5763f60c6ef 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6923,7 +6923,8 @@ static int stmmac_hw_init(struct stmmac_priv *priv) if (priv->dma_cap.tsoen) dev_info(priv->device, "TSO supported\n"); - priv->hw->vlan_fail_q_en = priv->plat->vlan_fail_q_en; + priv->hw->vlan_fail_q_en = + (priv->plat->flags & STMMAC_FLAG_VLAN_FAIL_Q_EN); priv->hw->vlan_fail_q = priv->plat->vlan_fail_q; /* Run HW quirks, if any */ -- cgit From 956c3f09b9c4cc9567ca11c84007545b939e61aa Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:57 +0200 Subject: net: stmmac: replace the multi_msi_en field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-9-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 1f1bc99571a5..d8bcf9452197 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -953,7 +953,7 @@ static int stmmac_config_single_msi(struct pci_dev *pdev, res->irq = pci_irq_vector(pdev, 0); res->wol_irq = res->irq; - plat->multi_msi_en = 0; + plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN; dev_info(&pdev->dev, "%s: Single IRQ enablement successful\n", __func__); @@ -1005,7 +1005,7 @@ static int stmmac_config_multi_msi(struct pci_dev *pdev, if (plat->msi_sfty_ue_vec < STMMAC_MSI_VEC_MAX) res->sfty_ue_irq = pci_irq_vector(pdev, plat->msi_sfty_ue_vec); - plat->multi_msi_en = 1; + plat->flags |= STMMAC_FLAG_MULTI_MSI_EN; dev_info(&pdev->dev, "%s: multi MSI enablement successful\n", __func__); return 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c5763f60c6ef..ebe82e7b50fc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3711,7 +3711,7 @@ static int stmmac_request_irq(struct net_device *dev) int ret; /* Request the IRQ lines */ - if (priv->plat->multi_msi_en) + if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) ret = stmmac_request_irq_multi_msi(dev); else ret = stmmac_request_irq_single(dev); @@ -5954,7 +5954,7 @@ static void stmmac_poll_controller(struct net_device *dev) if (test_bit(STMMAC_DOWN, &priv->state)) return; - if (priv->plat->multi_msi_en) { + if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) { for (i = 0; i < priv->plat->rx_queues_to_use; i++) stmmac_msi_intr_rx(0, &priv->dma_conf.rx_queue[i]); @@ -7169,7 +7169,8 @@ int stmmac_dvr_probe(struct device *device, priv->plat = plat_dat; priv->ioaddr = res->addr; priv->dev->base_addr = (unsigned long)res->addr; - priv->plat->dma_cfg->multi_msi_en = priv->plat->multi_msi_en; + priv->plat->dma_cfg->multi_msi_en = + (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN); priv->dev->irq = res->irq; priv->wol_irq = res->wol_irq; -- cgit From aa5513f5d95f6b5311de859f8f466a09863bedf6 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:58 +0200 Subject: net: stmmac: replace the ext_snapshot_en field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-10-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index d8bcf9452197..a3d0da4e9e91 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -326,7 +326,7 @@ static int intel_crosststamp(ktime_t *device, /* Both internal crosstimestamping and external triggered event * timestamping cannot be run concurrently. */ - if (priv->plat->ext_snapshot_en) + if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN) return -EBUSY; priv->plat->int_snapshot_en = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index 8b50f03056b7..afd81aac6644 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -195,7 +195,7 @@ static void timestamp_interrupt(struct stmmac_priv *priv) */ ts_status = readl(priv->ioaddr + GMAC_TIMESTAMP_STATUS); - if (!priv->plat->ext_snapshot_en) + if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN) return; num_snapshot = (ts_status & GMAC_TIMESTAMP_ATSNS_MASK) >> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index b4388ca8d211..3d7825cb30bb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -192,7 +192,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp, write_unlock_irqrestore(&priv->ptp_lock, flags); break; case PTP_CLK_REQ_EXTTS: - priv->plat->ext_snapshot_en = on; + if (on) + priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN; + else + priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN; mutex_lock(&priv->aux_ts_lock); acr_value = readl(ptpaddr + PTP_ACR); acr_value &= ~PTP_ACR_MASK; -- cgit From 621ba7ad7891b381baf9ebf3da4ec4e95c86ea4e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 10:59:59 +0200 Subject: net: stmmac: replace the int_snapshot_en field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-11-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 10 +++++----- drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index a3d0da4e9e91..0ffae785d8bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -329,7 +329,7 @@ static int intel_crosststamp(ktime_t *device, if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN) return -EBUSY; - priv->plat->int_snapshot_en = 1; + priv->plat->flags |= STMMAC_FLAG_INT_SNAPSHOT_EN; mutex_lock(&priv->aux_ts_lock); /* Enable Internal snapshot trigger */ @@ -350,7 +350,7 @@ static int intel_crosststamp(ktime_t *device, break; default: mutex_unlock(&priv->aux_ts_lock); - priv->plat->int_snapshot_en = 0; + priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; return -EINVAL; } writel(acr_value, ptpaddr + PTP_ACR); @@ -376,7 +376,7 @@ static int intel_crosststamp(ktime_t *device, if (!wait_event_interruptible_timeout(priv->tstamp_busy_wait, stmmac_cross_ts_isr(priv), HZ / 100)) { - priv->plat->int_snapshot_en = 0; + priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; return -ETIMEDOUT; } @@ -395,7 +395,7 @@ static int intel_crosststamp(ktime_t *device, } system->cycles *= intel_priv->crossts_adj; - priv->plat->int_snapshot_en = 0; + priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; return 0; } @@ -609,7 +609,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->ext_snapshot_num = AUX_SNAPSHOT0; plat->crosststamp = intel_crosststamp; - plat->int_snapshot_en = 0; + plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; /* Setup MSI vector offset specific to Intel mGbE controller */ plat->msi_mac_vec = 29; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index afd81aac6644..fa2c3ba7e9fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -180,7 +180,7 @@ static void timestamp_interrupt(struct stmmac_priv *priv) u64 ptp_time; int i; - if (priv->plat->int_snapshot_en) { + if (priv->plat->flags & STMMAC_FLAG_INT_SNAPSHOT_EN) { wake_up(&priv->tstamp_busy_wait); return; } -- cgit From 743dd1db85f40be1e2c7416c83f0289aaa260ceb Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 11:00:00 +0200 Subject: net: stmmac: replace the rx_clk_runs_in_lpi field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-12-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 4b58904ee132..735525ba8b93 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -786,7 +786,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (of_property_read_bool(np, "snps,tso")) plat_dat->flags |= STMMAC_FLAG_TSO_EN; if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) - plat_dat->rx_clk_runs_in_lpi = 1; + plat_dat->flags |= STMMAC_FLAG_RX_CLK_RUNS_IN_LPI; if (data->has_integrated_pcs) plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ebe82e7b50fc..2d68a6e84b0e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1085,7 +1085,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, stmmac_mac_set(priv, priv->ioaddr, true); if (phy && priv->dma_cap.eee) { priv->eee_active = - phy_init_eee(phy, !priv->plat->rx_clk_runs_in_lpi) >= 0; + phy_init_eee(phy, !(priv->plat->flags & + STMMAC_FLAG_RX_CLK_RUNS_IN_LPI)) >= 0; priv->eee_enabled = stmmac_eee_init(priv); priv->tx_lpi_enabled = priv->eee_enabled; stmmac_set_eee_pls(priv, priv->hw, true); -- cgit From 9d0c0d5ebd635f914ab2ab691b68e8754fbe0a57 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Jul 2023 11:00:01 +0200 Subject: net: stmmac: replace the en_tx_lpi_clockgating field with a flag Drop the boolean field of the plat_stmmacenet_data structure in favor of a simple bitfield flag. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Link: https://lore.kernel.org/r/20230710090001.303225-13-brgl@bgdev.pl Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2d68a6e84b0e..efe85b086abe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -421,7 +421,7 @@ static int stmmac_enable_eee_mode(struct stmmac_priv *priv) /* Check and enter in LPI mode */ if (!priv->tx_path_in_lpi_mode) stmmac_set_eee_mode(priv, priv->hw, - priv->plat->en_tx_lpi_clockgating); + priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index f51522cb0061..23d53ea04b24 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -466,8 +466,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode"); - plat->en_tx_lpi_clockgating = - of_property_read_bool(np, "snps,en-tx-lpi-clockgating"); + if (of_property_read_bool(np, "snps,en-tx-lpi-clockgating")) + plat->flags |= STMMAC_FLAG_EN_TX_LPI_CLOCKGATING; /* Set the maxmtu to a default of JUMBO_LEN in case the * parameter is not present in the device tree. -- cgit From dc4c399d215d76689ebadec7ed3184bcf213e2ee Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Tue, 11 Jul 2023 15:06:26 +0200 Subject: pptp: Constify the po parameter of pptp_route_output(). Make it explicit that this function doesn't modify the socket passed as parameter. Signed-off-by: Guillaume Nault Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ppp/pptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 32183f24e63f..57d38b27812d 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -129,10 +129,10 @@ static void del_chan(struct pppox_sock *sock) spin_unlock(&chan_lock); } -static struct rtable *pptp_route_output(struct pppox_sock *po, +static struct rtable *pptp_route_output(const struct pppox_sock *po, struct flowi4 *fl4) { - struct sock *sk = &po->sk; + const struct sock *sk = &po->sk; struct net *net; net = sock_net(sk); -- cgit From 88085b3b83f55eab1be57f4eb0f69446717f23fb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Jul 2023 00:45:58 +0100 Subject: net: dsa: ar9331: Use maple tree register cache We now have a regmap cache which uses a maple tree to store the register state, this is a more modern data structure and the regmap level code using it makes a number of assumptions better tuned for modern hardware than those made by the rbtree cache type that the at9331 driver uses. Switch the ar9331 driver to use the more modern data structure. This should have minimal practical impact, it's mainly code modernisation. Signed-off-by: Mark Brown Signed-off-by: David S. Miller --- drivers/net/dsa/qca/ar9331.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index b2bf78ac485e..72730dcc9ca9 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -1010,7 +1010,7 @@ static const struct regmap_config ar9331_mdio_regmap_config = { .wr_table = &ar9331_register_set, .rd_table = &ar9331_register_set, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static struct regmap_bus ar9331_sw_bus = { -- cgit From 6963e463256e4a5fa1635b3636aa38b058668122 Mon Sep 17 00:00:00 2001 From: Mengyuan Lou Date: Thu, 13 Jul 2023 14:09:11 +0800 Subject: net: ngbe: add Wake on Lan support Implement ethtool_ops get_wol and set_wol. Implement Wake-on-LAN support. Wol requires hardware board support which use sub id to identify. Magic packets are checked by fw, for now just support WAKE_MAGIC. Signed-off-by: Mengyuan Lou Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 3 +- drivers/net/ethernet/wangxun/libwx/wx_hw.h | 1 + drivers/net/ethernet/wangxun/libwx/wx_type.h | 6 ++- drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 35 +++++++++++++ drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 64 +++++++++++++++++++++--- drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c | 1 + 6 files changed, 102 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 39a9aeee7aab..ad09ab1d1209 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1501,7 +1501,7 @@ static void wx_restore_vlan(struct wx *wx) * * Configure the Rx unit of the MAC after a reset. **/ -static void wx_configure_rx(struct wx *wx) +void wx_configure_rx(struct wx *wx) { u32 psrtype, i; int ret; @@ -1545,6 +1545,7 @@ static void wx_configure_rx(struct wx *wx) wx_enable_rx(wx); wx_enable_sec_rx_path(wx); } +EXPORT_SYMBOL(wx_configure_rx); static void wx_configure_isb(struct wx *wx) { diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h index 1f93ca32c921..b95090e973ae 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h @@ -25,6 +25,7 @@ void wx_disable_rx(struct wx *wx); void wx_set_rx_mode(struct net_device *netdev); int wx_change_mtu(struct net_device *netdev, int new_mtu); void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring); +void wx_configure_rx(struct wx *wx); void wx_configure(struct wx *wx); void wx_start_hw(struct wx *wx); int wx_disable_pcie_master(struct wx *wx); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 29dfb561887d..1de88a33a698 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -160,6 +160,10 @@ #define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16)) #define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16)) +#define WX_PSR_WKUP_CTL 0x15B80 +/* Wake Up Filter Control Bit */ +#define WX_PSR_WKUP_CTL_MAG BIT(1) /* Magic Packet Wakeup Enable */ + /* vlan tbl */ #define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4)) @@ -846,7 +850,7 @@ struct wx { int duplex; struct phy_device *phydev; - bool wol_enabled; + bool wol_hw_supported; bool ncsi_enabled; bool gpio_ctrl; raw_spinlock_t gpio_lock; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c index 5b25834baf38..ec0e869e9aac 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c @@ -6,14 +6,49 @@ #include #include "../libwx/wx_ethtool.h" +#include "../libwx/wx_type.h" #include "ngbe_ethtool.h" +static void ngbe_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct wx *wx = netdev_priv(netdev); + + if (!wx->wol_hw_supported) + return; + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + if (wx->wol & WX_PSR_WKUP_CTL_MAG) + wol->wolopts |= WAKE_MAGIC; +} + +static int ngbe_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct wx *wx = netdev_priv(netdev); + struct pci_dev *pdev = wx->pdev; + + if (!wx->wol_hw_supported) + return -EOPNOTSUPP; + + wx->wol = 0; + if (wol->wolopts & WAKE_MAGIC) + wx->wol = WX_PSR_WKUP_CTL_MAG; + netdev->wol_enabled = !!(wx->wol); + wr32(wx, WX_PSR_WKUP_CTL, wx->wol); + device_set_wakeup_enable(&pdev->dev, netdev->wol_enabled); + + return 0; +} + static const struct ethtool_ops ngbe_ethtool_ops = { .get_drvinfo = wx_get_drvinfo, .get_link = ethtool_op_get_link, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, .nway_reset = phy_ethtool_nway_reset, + .get_wol = ngbe_get_wol, + .set_wol = ngbe_set_wol, }; void ngbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index c99a5d3de72e..2b431db6085a 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -62,7 +62,7 @@ static void ngbe_init_type_code(struct wx *wx) em_mac_type_rgmii : em_mac_type_mdi; - wx->wol_enabled = (wol_mask == NGBE_WOL_SUP) ? 1 : 0; + wx->wol_hw_supported = (wol_mask == NGBE_WOL_SUP) ? 1 : 0; wx->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK || type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0; @@ -440,14 +440,26 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) { struct wx *wx = pci_get_drvdata(pdev); struct net_device *netdev; + u32 wufc = wx->wol; netdev = wx->netdev; + rtnl_lock(); netif_device_detach(netdev); - rtnl_lock(); if (netif_running(netdev)) - ngbe_down(wx); + ngbe_close(netdev); + wx_clear_interrupt_scheme(wx); rtnl_unlock(); + + if (wufc) { + wx_set_rx_mode(netdev); + wx_configure_rx(wx); + wr32(wx, NGBE_PSR_WKUP_CTL, wufc); + } else { + wr32(wx, NGBE_PSR_WKUP_CTL, 0); + } + pci_wake_from_d3(pdev, !!wufc); + *enable_wake = !!wufc; wx_control_hw(wx, false); pci_disable_device(pdev); @@ -621,12 +633,11 @@ static int ngbe_probe(struct pci_dev *pdev, } wx->wol = 0; - if (wx->wol_enabled) + if (wx->wol_hw_supported) wx->wol = NGBE_PSR_WKUP_CTL_MAG; - wx->wol_enabled = !!(wx->wol); + netdev->wol_enabled = !!(wx->wol); wr32(wx, NGBE_PSR_WKUP_CTL, wx->wol); - device_set_wakeup_enable(&pdev->dev, wx->wol); /* Save off EEPROM version number and Option Rom version which @@ -712,11 +723,52 @@ static void ngbe_remove(struct pci_dev *pdev) pci_disable_device(pdev); } +static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state) +{ + bool wake; + + ngbe_dev_shutdown(pdev, &wake); + device_set_wakeup_enable(&pdev->dev, wake); + + return 0; +} + +static int ngbe_resume(struct pci_dev *pdev) +{ + struct net_device *netdev; + struct wx *wx; + u32 err; + + wx = pci_get_drvdata(pdev); + netdev = wx->netdev; + + err = pci_enable_device_mem(pdev); + if (err) { + wx_err(wx, "Cannot enable PCI device from suspend\n"); + return err; + } + pci_set_master(pdev); + device_wakeup_disable(&pdev->dev); + + ngbe_reset_hw(wx); + rtnl_lock(); + err = wx_init_interrupt_scheme(wx); + if (!err && netif_running(netdev)) + err = ngbe_open(netdev); + if (!err) + netif_device_attach(netdev); + rtnl_unlock(); + + return 0; +} + static struct pci_driver ngbe_driver = { .name = ngbe_driver_name, .id_table = ngbe_pci_tbl, .probe = ngbe_probe, .remove = ngbe_remove, + .suspend = ngbe_suspend, + .resume = ngbe_resume, .shutdown = ngbe_shutdown, }; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c index c9ddbbc3fa4f..cc2f325a52f7 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c @@ -236,6 +236,7 @@ static void ngbe_phy_fixup(struct wx *wx) phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + phydev->mac_managed_pm = true; if (wx->mac_type != em_mac_type_mdi) return; /* disable EEE, internal phy does not support eee */ -- cgit From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:07 +0100 Subject: net: phylink: add pcs_enable()/pcs_disable() methods Add phylink PCS enable/disable callbacks that will allow us to place IEEE 802.3 register compliant PCS in power-down mode while not being used. Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 48 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index d0aaa5cad853..748c62efceb8 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -34,6 +34,10 @@ enum { PHYLINK_DISABLE_STOPPED, PHYLINK_DISABLE_LINK, PHYLINK_DISABLE_MAC_WOL, + + PCS_STATE_DOWN = 0, + PCS_STATE_STARTING, + PCS_STATE_STARTED, }; /** @@ -72,6 +76,7 @@ struct phylink { struct phylink_link_state phy_state; struct work_struct resolve; unsigned int pcs_neg_mode; + unsigned int pcs_state; bool mac_link_dropped; bool using_mac_select_pcs; @@ -993,6 +998,22 @@ static void phylink_resolve_an_pause(struct phylink_link_state *state) } } +static void phylink_pcs_disable(struct phylink_pcs *pcs) +{ + if (pcs && pcs->ops->pcs_disable) + pcs->ops->pcs_disable(pcs); +} + +static int phylink_pcs_enable(struct phylink_pcs *pcs) +{ + int err = 0; + + if (pcs && pcs->ops->pcs_enable) + err = pcs->ops->pcs_enable(pcs); + + return err; +} + static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, const struct phylink_link_state *state, bool permit_pause_to_mac) @@ -1095,11 +1116,17 @@ static void phylink_major_config(struct phylink *pl, bool restart, /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ - if (pcs_changed) + if (pcs_changed) { + phylink_pcs_disable(pl->pcs); + pl->pcs = pcs; + } phylink_mac_config(pl, state); + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) + phylink_pcs_enable(pl->pcs); + neg_mode = pl->cur_link_an_mode; if (pl->pcs && pl->pcs->neg_mode) neg_mode = pl->pcs_neg_mode; @@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct phylink_config *config, pl->link_config.pause = MLO_PAUSE_AN; pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; + pl->pcs_state = PCS_STATE_DOWN; pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); @@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); + pl->pcs_state = PCS_STATE_STARTING; + /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. @@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); + pl->pcs_state = PCS_STATE_STARTED; + phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { @@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl) poll = true; } - switch (pl->cfg_link_an_mode) { - case MLO_AN_FIXED: + if (pl->cfg_link_an_mode == MLO_AN_FIXED) poll |= pl->config->poll_fixed_state; - break; - case MLO_AN_INBAND: - if (pl->pcs) - poll |= pl->pcs->poll; - break; - } + if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) @@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); + + pl->pcs_state = PCS_STATE_DOWN; + + phylink_pcs_disable(pl->pcs); } EXPORT_SYMBOL_GPL(phylink_stop); -- cgit From aee6098822ed8a298ad817da8339ba4c7ea381fe Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:12 +0100 Subject: net: phylink: add pcs_pre_config()/pcs_post_config() methods Add hooks that are called before and after the mac_config() call, which will be needed to deal with errata workarounds for the Marvell 88e639x DSA switches. Reviewed-by: Andrew Lunn Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 748c62efceb8..9840a2952309 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -998,6 +998,24 @@ static void phylink_resolve_an_pause(struct phylink_link_state *state) } } +static void phylink_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + if (pcs && pcs->ops->pcs_pre_config) + pcs->ops->pcs_pre_config(pcs, interface); +} + +static int phylink_pcs_post_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + int err = 0; + + if (pcs && pcs->ops->pcs_post_config) + err = pcs->ops->pcs_post_config(pcs, interface); + + return err; +} + static void phylink_pcs_disable(struct phylink_pcs *pcs) { if (pcs && pcs->ops->pcs_disable) @@ -1122,8 +1140,14 @@ static void phylink_major_config(struct phylink *pl, bool restart, pl->pcs = pcs; } + if (pl->pcs) + phylink_pcs_pre_config(pl->pcs, state->interface); + phylink_mac_config(pl, state); + if (pl->pcs) + phylink_pcs_post_config(pl->pcs, state->interface); + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) phylink_pcs_enable(pl->pcs); -- cgit From 24699cc1ff3e633d7c3a0d3ef394243db11757ec Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:17 +0100 Subject: net: phylink: add support for PCS link change notifications Add a function, phylink_pcs_change() which can be used by PCs drivers to notify phylink about changes to the PCS link state. Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 9840a2952309..71b1012ef3be 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1137,6 +1137,11 @@ static void phylink_major_config(struct phylink *pl, bool restart, if (pcs_changed) { phylink_pcs_disable(pl->pcs); + if (pl->pcs) + pl->pcs->phylink = NULL; + + pcs->phylink = pl; + pl->pcs = pcs; } @@ -1991,6 +1996,14 @@ void phylink_disconnect_phy(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_disconnect_phy); +static void phylink_link_changed(struct phylink *pl, bool up, const char *what) +{ + if (!up) + pl->mac_link_dropped = true; + phylink_run_resolve(pl); + phylink_dbg(pl, "%s link %s\n", what, up ? "up" : "down"); +} + /** * phylink_mac_change() - notify phylink of a change in MAC state * @pl: a pointer to a &struct phylink returned from phylink_create() @@ -2001,13 +2014,30 @@ EXPORT_SYMBOL_GPL(phylink_disconnect_phy); */ void phylink_mac_change(struct phylink *pl, bool up) { - if (!up) - pl->mac_link_dropped = true; - phylink_run_resolve(pl); - phylink_dbg(pl, "mac link %s\n", up ? "up" : "down"); + phylink_link_changed(pl, up, "mac"); } EXPORT_SYMBOL_GPL(phylink_mac_change); +/** + * phylink_pcs_change() - notify phylink of a change to PCS link state + * @pcs: pointer to &struct phylink_pcs + * @up: indicates whether the link is currently up. + * + * The PCS driver should call this when the state of its link changes + * (e.g. link failure, new negotiation results, etc.) Note: it should + * not determine "up" by reading the BMSR. If in doubt about the link + * state at interrupt time, then pass true if pcs_get_state() returns + * the latched link-down state, otherwise pass false. + */ +void phylink_pcs_change(struct phylink_pcs *pcs, bool up) +{ + struct phylink *pl = pcs->phylink; + + if (pl) + phylink_link_changed(pl, up, "pcs"); +} +EXPORT_SYMBOL_GPL(phylink_pcs_change); + static irqreturn_t phylink_link_handler(int irq, void *data) { struct phylink *pl = data; -- cgit From e6a45700e7e19b1c945ee56feab429ff8489370b Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:22 +0100 Subject: net: mdio: add unlocked mdiobus and mdiodev bus accessors Add the following unlocked accessors to complete the set: __mdiobus_modify() __mdiodev_read() __mdiodev_write() __mdiodev_modify() __mdiodev_modify_changed() which we will need for Marvell DSA PCS conversion. Reviewed-by: Andrew Lunn Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 8b3618d3da4a..bc04048de2fa 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1210,6 +1210,26 @@ int mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, } EXPORT_SYMBOL(mdiobus_c45_write_nested); +/* + * __mdiobus_modify - Convenience function for modifying a given mdio device + * register + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to write + * @mask: bit mask of bits to clear + * @set: bit mask of bits to set + */ +int __mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, + u16 set) +{ + int err; + + err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); + + return err < 0 ? err : 0; +} +EXPORT_SYMBOL_GPL(__mdiobus_modify); + /** * mdiobus_modify - Convenience function for modifying a given mdio device * register @@ -1224,10 +1244,10 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set) int err; mutex_lock(&bus->mdio_lock); - err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); + err = __mdiobus_modify(bus, addr, regnum, mask, set); mutex_unlock(&bus->mdio_lock); - return err < 0 ? err : 0; + return err; } EXPORT_SYMBOL_GPL(mdiobus_modify); -- cgit From 40da0c32c3fcb5bcb79068574ae60baaea78f3c4 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:28 +0100 Subject: net: dsa: mv88e6xxx: remove handling for DSA and CPU ports As we now always use a fixed-link for DSA and CPU ports, we no longer need the hack in the Marvell code to make this work. Remove it. This is especially important with the conversion of DSA drivers to phylink_pcs, as the PCS code only gets called if we are using phylink for the port. Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 48 +++++----------------------------------- 1 file changed, 5 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8b51756bd805..42c325409ac4 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3315,56 +3315,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) { struct device_node *phy_handle = NULL; struct dsa_switch *ds = chip->ds; - phy_interface_t mode; struct dsa_port *dp; - int tx_amp, speed; + int tx_amp; int err; u16 reg; chip->ports[port].chip = chip; chip->ports[port].port = port; - dp = dsa_to_port(ds, port); - - /* MAC Forcing register: don't force link, speed, duplex or flow control - * state to any particular values on physical ports, but force the CPU - * port and all DSA ports to their maximum bandwidth and full duplex. - */ - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - struct phylink_config pl_config = {}; - unsigned long caps; - - chip->info->ops->phylink_get_caps(chip, port, &pl_config); - - caps = pl_config.mac_capabilities; - - if (chip->info->ops->port_max_speed_mode) - mode = chip->info->ops->port_max_speed_mode(chip, port); - else - mode = PHY_INTERFACE_MODE_NA; - - if (caps & MAC_10000FD) - speed = SPEED_10000; - else if (caps & MAC_5000FD) - speed = SPEED_5000; - else if (caps & MAC_2500FD) - speed = SPEED_2500; - else if (caps & MAC_1000) - speed = SPEED_1000; - else if (caps & MAC_100) - speed = SPEED_100; - else - speed = SPEED_10; - - err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP, - speed, DUPLEX_FULL, - PAUSE_OFF, mode); - } else { - err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, - SPEED_UNFORCED, DUPLEX_UNFORCED, - PAUSE_ON, - PHY_INTERFACE_MODE_NA); - } + err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, + SPEED_UNFORCED, DUPLEX_UNFORCED, + PAUSE_ON, PHY_INTERFACE_MODE_NA); if (err) return err; @@ -3541,6 +3502,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) } if (chip->info->ops->serdes_set_tx_amplitude) { + dp = dsa_to_port(ds, port); if (dp) phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0); -- cgit From b92143d4420fde0e7f2ca1637362120177e03458 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:33 +0100 Subject: net: dsa: mv88e6xxx: add infrastructure for phylink_pcs Add infrastructure for phylink_pcs to the mv88e6xxx driver. This involves adding a mac_select_pcs() hook so we can pass the PCS to phylink at the appropriate time, and a PCS initialisation function. As the various chip implementations are converted to use phylink_pcs, they are no longer reliant on the legacy phylink behaviour. We detect this by the use of this infrastructure, or the lack of any serdes. Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 48 ++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 12 ++++++++++ 2 files changed, 60 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 42c325409ac4..acbe55762f5e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -844,6 +844,31 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces); } + + /* If we have a .pcs_ops, or don't have a .serdes_pcs_get_state, + * serdes_pcs_config, serdes_pcs_an_restart, or serdes_pcs_link_up, + * we are not legacy. + */ + if (chip->info->ops->pcs_ops || + (!chip->info->ops->serdes_pcs_get_state && + !chip->info->ops->serdes_pcs_config && + !chip->info->ops->serdes_pcs_an_restart && + !chip->info->ops->serdes_pcs_link_up)) + config->legacy_pre_march2020 = false; +} + +static struct phylink_pcs *mv88e6xxx_mac_select_pcs(struct dsa_switch *ds, + int port, + phy_interface_t interface) +{ + struct mv88e6xxx_chip *chip = ds->priv; + struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP); + + if (chip->info->ops->pcs_ops) + pcs = chip->info->ops->pcs_ops->pcs_select(chip, port, + interface); + + return pcs; } static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port, @@ -3582,6 +3607,10 @@ static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port, struct mv88e6xxx_chip *chip = ds->priv; int err; + /* Do not control power or request irqs if using PCS */ + if (chip->info->ops->pcs_ops) + return 0; + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_serdes_power(chip, port, true); mv88e6xxx_reg_unlock(chip); @@ -3593,6 +3622,10 @@ static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port) { struct mv88e6xxx_chip *chip = ds->priv; + /* Do not control power or request irqs if using PCS */ + if (chip->info->ops->pcs_ops) + return; + mv88e6xxx_reg_lock(chip); if (mv88e6xxx_serdes_power(chip, port, false)) dev_err(chip->dev, "failed to power off SERDES\n"); @@ -4061,12 +4094,26 @@ out_mdios: static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) { + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + if (chip->info->ops->pcs_ops->pcs_init) { + err = chip->info->ops->pcs_ops->pcs_init(chip, port); + if (err) + return err; + } + return mv88e6xxx_setup_devlink_regions_port(ds, port); } static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) { + struct mv88e6xxx_chip *chip = ds->priv; + mv88e6xxx_teardown_devlink_regions_port(ds, port); + + if (chip->info->ops->pcs_ops->pcs_teardown) + chip->info->ops->pcs_ops->pcs_teardown(chip, port); } static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) @@ -7061,6 +7108,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .port_setup = mv88e6xxx_port_setup, .port_teardown = mv88e6xxx_port_teardown, .phylink_get_caps = mv88e6xxx_get_caps, + .phylink_mac_select_pcs = mv88e6xxx_mac_select_pcs, .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, .phylink_mac_prepare = mv88e6xxx_mac_prepare, .phylink_mac_config = mv88e6xxx_mac_config, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 0ad34b2d8913..1dd310a3c41f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -205,6 +205,7 @@ struct mv88e6xxx_irq_ops; struct mv88e6xxx_gpio_ops; struct mv88e6xxx_avb_ops; struct mv88e6xxx_ptp_ops; +struct mv88e6xxx_pcs_ops; struct mv88e6xxx_irq { u16 masked; @@ -288,6 +289,7 @@ struct mv88e6xxx_port { unsigned int serdes_irq; char serdes_irq_name[64]; struct devlink_region *region; + void *pcs_private; /* MacAuth Bypass control flag */ bool mab; @@ -664,6 +666,8 @@ struct mv88e6xxx_ops { void (*phylink_get_caps)(struct mv88e6xxx_chip *chip, int port, struct phylink_config *config); + const struct mv88e6xxx_pcs_ops *pcs_ops; + /* Max Frame Size */ int (*set_max_frame_size)(struct mv88e6xxx_chip *chip, int mtu); }; @@ -736,6 +740,14 @@ struct mv88e6xxx_ptp_ops { u32 cc_mult_dem; }; +struct mv88e6xxx_pcs_ops { + int (*pcs_init)(struct mv88e6xxx_chip *chip, int port); + void (*pcs_teardown)(struct mv88e6xxx_chip *chip, int port); + struct phylink_pcs *(*pcs_select)(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); + +}; + #define STATS_TYPE_PORT BIT(0) #define STATS_TYPE_BANK0 BIT(1) #define STATS_TYPE_BANK1 BIT(2) -- cgit From 05407b0ebc3932cf9a6010eb81168ba0b6c5e8ab Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:38 +0100 Subject: net: dsa: mv88e6xxx: export mv88e6xxx_pcs_decode_state() Rename and export the PCS state decoding function so our PCS can make use of the functionality provided by this. Reviewed-by: Andrew Lunn Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/serdes.c | 11 +++++------ drivers/net/dsa/mv88e6xxx/serdes.h | 5 +++++ 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 80167d53212f..7ea36d04d9fa 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -45,9 +45,8 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, return mv88e6xxx_phy_write_c45(chip, lane, device, reg, val); } -static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, - u16 bmsr, u16 lpa, u16 status, - struct phylink_link_state *state) +int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, + u16 status, struct phylink_link_state *state) { state->link = false; @@ -88,7 +87,7 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, state->speed = SPEED_10; break; default: - dev_err(chip->dev, "invalid PHY speed\n"); + dev_err(dev, "invalid PHY speed\n"); return -EINVAL; } } else if (state->link && @@ -211,7 +210,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, return err; } - return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state); + return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state); } int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, @@ -942,7 +941,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, return err; } - return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state); + return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state); } static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index e245687ddb1d..93d40d66d7c5 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -12,6 +12,8 @@ #include "chip.h" +struct phylink_link_state; + #define MV88E6352_ADDR_SERDES 0x0f #define MV88E6352_SERDES_PAGE_FIBER 0x01 #define MV88E6352_SERDES_IRQ 0x0b @@ -107,6 +109,9 @@ #define MV88E6393X_ERRATA_4_8_REG 0xF074 #define MV88E6393X_ERRATA_4_8_BIT BIT(14) +int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, + u16 status, struct phylink_link_state *state); + int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); -- cgit From 4aabe35c385ce6c28613ab56b334b4a9521d62b7 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:43 +0100 Subject: net: dsa: mv88e6xxx: convert 88e6185 to phylink_pcs Convert the 88E6185 SERDES code to use the phylink_pcs infrastructure. Reviewed-by: Andrew Lunn Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 14 +-- drivers/net/dsa/mv88e6xxx/pcs-6185.c | 190 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/serdes.c | 109 -------------------- drivers/net/dsa/mv88e6xxx/serdes.h | 11 +- 5 files changed, 196 insertions(+), 129 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/pcs-6185.c (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 1409e691ab77..9becf56fdec1 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o mv88e6xxx-objs += global2_avb.o mv88e6xxx-objs += global2_scratch.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o +mv88e6xxx-objs += pcs-6185.o mv88e6xxx-objs += phy.o mv88e6xxx-objs += port.o mv88e6xxx-objs += port_hidden.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index acbe55762f5e..fd876cf5577f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4230,15 +4230,13 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, - .serdes_power = mv88e6185_serdes_power, - .serdes_get_lane = mv88e6185_serdes_get_lane, - .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state, .ppu_enable = mv88e6185_g1_ppu_enable, .ppu_disable = mv88e6185_g1_ppu_disable, .reset = mv88e6185_g1_reset, .vtu_getnext = mv88e6185_g1_vtu_getnext, .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, .phylink_get_caps = mv88e6095_phylink_get_caps, + .pcs_ops = &mv88e6185_pcs_ops, .set_max_frame_size = mv88e6185_g1_set_max_frame_size, }; @@ -4276,18 +4274,14 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .set_egress_port = mv88e6095_g1_set_egress_port, .watchdog_ops = &mv88e6097_watchdog_ops, .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, - .serdes_power = mv88e6185_serdes_power, - .serdes_get_lane = mv88e6185_serdes_get_lane, - .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6097_serdes_irq_enable, - .serdes_irq_status = mv88e6097_serdes_irq_status, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6085_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .phylink_get_caps = mv88e6095_phylink_get_caps, + .pcs_ops = &mv88e6185_pcs_ops, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, .set_max_frame_size = mv88e6185_g1_set_max_frame_size, @@ -4768,9 +4762,6 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .set_egress_port = mv88e6095_g1_set_egress_port, .watchdog_ops = &mv88e6097_watchdog_ops, .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, - .serdes_power = mv88e6185_serdes_power, - .serdes_get_lane = mv88e6185_serdes_get_lane, - .serdes_pcs_get_state = mv88e6185_serdes_pcs_get_state, .set_cascade_port = mv88e6185_g1_set_cascade_port, .ppu_enable = mv88e6185_g1_ppu_enable, .ppu_disable = mv88e6185_g1_ppu_disable, @@ -4778,6 +4769,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .vtu_getnext = mv88e6185_g1_vtu_getnext, .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, .phylink_get_caps = mv88e6185_phylink_get_caps, + .pcs_ops = &mv88e6185_pcs_ops, .set_max_frame_size = mv88e6185_g1_set_max_frame_size, }; diff --git a/drivers/net/dsa/mv88e6xxx/pcs-6185.c b/drivers/net/dsa/mv88e6xxx/pcs-6185.c new file mode 100644 index 000000000000..4d677f836807 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/pcs-6185.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Marvell 88E6185 family SERDES PCS support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2017 Andrew Lunn + */ +#include + +#include "global2.h" +#include "port.h" +#include "serdes.h" + +struct mv88e6185_pcs { + struct phylink_pcs phylink_pcs; + unsigned int irq; + char name[64]; + + struct mv88e6xxx_chip *chip; + int port; +}; + +static struct mv88e6185_pcs *pcs_to_mv88e6185_pcs(struct phylink_pcs *pcs) +{ + return container_of(pcs, struct mv88e6185_pcs, phylink_pcs); +} + +static irqreturn_t mv88e6185_pcs_handle_irq(int irq, void *dev_id) +{ + struct mv88e6185_pcs *mpcs = dev_id; + struct mv88e6xxx_chip *chip; + irqreturn_t ret = IRQ_NONE; + bool link_up; + u16 status; + int port; + int err; + + chip = mpcs->chip; + port = mpcs->port; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status); + mv88e6xxx_reg_unlock(chip); + + if (!err) { + link_up = !!(status & MV88E6XXX_PORT_STS_LINK); + + phylink_pcs_change(&mpcs->phylink_pcs, link_up); + + ret = IRQ_HANDLED; + } + + return ret; +} + +static void mv88e6185_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct mv88e6185_pcs *mpcs = pcs_to_mv88e6185_pcs(pcs); + struct mv88e6xxx_chip *chip = mpcs->chip; + int port = mpcs->port; + u16 status; + int err; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status); + mv88e6xxx_reg_unlock(chip); + + if (err) + status = 0; + + state->link = !!(status & MV88E6XXX_PORT_STS_LINK); + if (state->link) { + state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? + DUPLEX_FULL : DUPLEX_HALF; + + switch (status & MV88E6XXX_PORT_STS_SPEED_MASK) { + case MV88E6XXX_PORT_STS_SPEED_1000: + state->speed = SPEED_1000; + break; + + case MV88E6XXX_PORT_STS_SPEED_100: + state->speed = SPEED_100; + break; + + case MV88E6XXX_PORT_STS_SPEED_10: + state->speed = SPEED_10; + break; + + default: + state->link = false; + break; + } + } +} + +static int mv88e6185_pcs_config(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + return 0; +} + +static void mv88e6185_pcs_an_restart(struct phylink_pcs *pcs) +{ +} + +static const struct phylink_pcs_ops mv88e6185_phylink_pcs_ops = { + .pcs_get_state = mv88e6185_pcs_get_state, + .pcs_config = mv88e6185_pcs_config, + .pcs_an_restart = mv88e6185_pcs_an_restart, +}; + +static int mv88e6185_pcs_init(struct mv88e6xxx_chip *chip, int port) +{ + struct mv88e6185_pcs *mpcs; + struct device *dev; + unsigned int irq; + int err; + + /* There are no configurable serdes lanes on this switch chip, so + * we use the static cmode configuration to determine whether we + * have a PCS or not. + */ + if (chip->ports[port].cmode != MV88E6185_PORT_STS_CMODE_SERDES && + chip->ports[port].cmode != MV88E6185_PORT_STS_CMODE_1000BASE_X) + return 0; + + dev = chip->dev; + + mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); + if (!mpcs) + return -ENOMEM; + + mpcs->chip = chip; + mpcs->port = port; + mpcs->phylink_pcs.ops = &mv88e6185_phylink_pcs_ops; + + irq = mv88e6xxx_serdes_irq_mapping(chip, port); + if (irq) { + snprintf(mpcs->name, sizeof(mpcs->name), + "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); + + err = request_threaded_irq(irq, NULL, mv88e6185_pcs_handle_irq, + IRQF_ONESHOT, mpcs->name, mpcs); + if (err) { + kfree(mpcs); + return err; + } + + mpcs->irq = irq; + } else { + mpcs->phylink_pcs.poll = true; + } + + chip->ports[port].pcs_private = &mpcs->phylink_pcs; + + return 0; +} + +static void mv88e6185_pcs_teardown(struct mv88e6xxx_chip *chip, int port) +{ + struct mv88e6185_pcs *mpcs; + + mpcs = chip->ports[port].pcs_private; + if (!mpcs) + return; + + if (mpcs->irq) + free_irq(mpcs->irq, mpcs); + + kfree(mpcs); + + chip->ports[port].pcs_private = NULL; +} + +static struct phylink_pcs *mv88e6185_pcs_select(struct mv88e6xxx_chip *chip, + int port, + phy_interface_t interface) +{ + return chip->ports[port].pcs_private; +} + +const struct mv88e6xxx_pcs_ops mv88e6185_pcs_ops = { + .pcs_init = mv88e6185_pcs_init, + .pcs_teardown = mv88e6185_pcs_teardown, + .pcs_select = mv88e6185_pcs_select, +}; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 7ea36d04d9fa..5ac5687e76a9 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -460,115 +460,6 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) return lane; } -int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up) -{ - /* The serdes power can't be controlled on this switch chip but we need - * to supply this function to avoid returning -EOPNOTSUPP in - * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down - */ - return 0; -} - -int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) -{ - /* There are no configurable serdes lanes on this switch chip but we - * need to return a non-negative lane number so that callers of - * mv88e6xxx_serdes_get_lane() know this is a serdes port. - */ - switch (chip->ports[port].cmode) { - case MV88E6185_PORT_STS_CMODE_SERDES: - case MV88E6185_PORT_STS_CMODE_1000BASE_X: - return 0; - default: - return -ENODEV; - } -} - -int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state) -{ - int err; - u16 status; - - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status); - if (err) - return err; - - state->link = !!(status & MV88E6XXX_PORT_STS_LINK); - - if (state->link) { - state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF; - - switch (status & MV88E6XXX_PORT_STS_SPEED_MASK) { - case MV88E6XXX_PORT_STS_SPEED_1000: - state->speed = SPEED_1000; - break; - case MV88E6XXX_PORT_STS_SPEED_100: - state->speed = SPEED_100; - break; - case MV88E6XXX_PORT_STS_SPEED_10: - state->speed = SPEED_10; - break; - default: - dev_err(chip->dev, "invalid PHY speed\n"); - return -EINVAL; - } - } else { - state->duplex = DUPLEX_UNKNOWN; - state->speed = SPEED_UNKNOWN; - } - - return 0; -} - -int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable) -{ - u8 cmode = chip->ports[port].cmode; - - /* The serdes interrupts are enabled in the G2_INT_MASK register. We - * need to return 0 to avoid returning -EOPNOTSUPP in - * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable - */ - switch (cmode) { - case MV88E6185_PORT_STS_CMODE_SERDES: - case MV88E6185_PORT_STS_CMODE_1000BASE_X: - return 0; - } - - return -EOPNOTSUPP; -} - -static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) -{ - u16 status; - int err; - - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status); - if (err) { - dev_err(chip->dev, "can't read port status: %d\n", err); - return; - } - - dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK)); -} - -irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - u8 cmode = chip->ports[port].cmode; - - switch (cmode) { - case MV88E6185_PORT_STS_CMODE_SERDES: - case MV88E6185_PORT_STS_CMODE_1000BASE_X: - mv88e6097_serdes_irq_link(chip, port); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) { u8 cmode = chip->ports[port].cmode; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 93d40d66d7c5..93d363eb61ea 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -112,7 +112,6 @@ struct phylink_link_state; int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state); -int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); @@ -126,8 +125,6 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, int lane, unsigned int mode, phy_interface_t interface, const unsigned long *advertise); -int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, int lane, struct phylink_link_state *state); int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, @@ -146,8 +143,6 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); -int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up); int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, bool on); int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, @@ -155,16 +150,12 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, bool on); int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip); -int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, bool enable); int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, bool enable); int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, bool enable); -irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane); irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, @@ -254,4 +245,6 @@ mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane) return chip->info->ops->serdes_irq_status(chip, port, lane); } +extern const struct mv88e6xxx_pcs_ops mv88e6185_pcs_ops; + #endif -- cgit From 85764555442fad03b67ee91c066a49586cceef5d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Jul 2023 09:42:48 +0100 Subject: net: dsa: mv88e6xxx: convert 88e6352 to phylink_pcs Convert the 88E6352 SERDES code to use the phylink_pcs infrastructure. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 34 +-- drivers/net/dsa/mv88e6xxx/pcs-6352.c | 390 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/serdes.c | 205 ------------------ drivers/net/dsa/mv88e6xxx/serdes.h | 18 +- 5 files changed, 396 insertions(+), 252 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/pcs-6352.c (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 9becf56fdec1..05976e1f93f6 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -10,6 +10,7 @@ mv88e6xxx-objs += global2_avb.o mv88e6xxx-objs += global2_scratch.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o mv88e6xxx-objs += pcs-6185.o +mv88e6xxx-objs += pcs-6352.o mv88e6xxx-objs += phy.o mv88e6xxx-objs += port.o mv88e6xxx-objs += port_hidden.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index fd876cf5577f..90573407d404 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4614,16 +4614,11 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, - .serdes_power = mv88e6352_serdes_power, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, .phylink_get_caps = mv88e6352_phylink_get_caps, + .pcs_ops = &mv88e6352_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -4719,20 +4714,13 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, - .serdes_power = mv88e6352_serdes_power, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, - .serdes_irq_enable = mv88e6352_serdes_irq_enable, - .serdes_irq_status = mv88e6352_serdes_irq_status, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude, .gpio_ops = &mv88e6352_gpio_ops, .phylink_get_caps = mv88e6352_phylink_get_caps, + .pcs_ops = &mv88e6352_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -5014,15 +5002,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, - .serdes_power = mv88e6352_serdes_power, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, - .serdes_irq_enable = mv88e6352_serdes_irq_enable, - .serdes_irq_status = mv88e6352_serdes_irq_status, .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, .serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude, @@ -5030,6 +5010,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, .phylink_get_caps = mv88e6352_phylink_get_caps, + .pcs_ops = &mv88e6352_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6250_ops = { @@ -5445,15 +5426,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, - .serdes_power = mv88e6352_serdes_power, .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, - .serdes_irq_enable = mv88e6352_serdes_irq_enable, - .serdes_irq_status = mv88e6352_serdes_irq_status, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, @@ -5464,6 +5437,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .serdes_get_regs = mv88e6352_serdes_get_regs, .serdes_set_tx_amplitude = mv88e6352_serdes_set_tx_amplitude, .phylink_get_caps = mv88e6352_phylink_get_caps, + .pcs_ops = &mv88e6352_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6390_ops = { diff --git a/drivers/net/dsa/mv88e6xxx/pcs-6352.c b/drivers/net/dsa/mv88e6xxx/pcs-6352.c new file mode 100644 index 000000000000..88f624b65470 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/pcs-6352.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Marvell 88E6352 family SERDES PCS support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2017 Andrew Lunn + */ +#include + +#include "global2.h" +#include "port.h" +#include "serdes.h" + +/* Definitions from drivers/net/phy/marvell.c, which would be good to reuse. */ +#define MII_M1011_PHY_STATUS 17 +#define MII_M1011_IMASK 18 +#define MII_M1011_IMASK_LINK_CHANGE BIT(10) +#define MII_M1011_IEVENT 19 +#define MII_M1011_IEVENT_LINK_CHANGE BIT(10) +#define MII_MARVELL_PHY_PAGE 22 +#define MII_MARVELL_FIBER_PAGE 1 + +struct marvell_c22_pcs { + struct mdio_device mdio; + struct phylink_pcs phylink_pcs; + unsigned int irq; + char name[64]; + bool (*link_check)(struct marvell_c22_pcs *mpcs); + struct mv88e6xxx_port *port; +}; + +static struct marvell_c22_pcs *pcs_to_marvell_c22_pcs(struct phylink_pcs *pcs) +{ + return container_of(pcs, struct marvell_c22_pcs, phylink_pcs); +} + +static int marvell_c22_pcs_set_fiber_page(struct marvell_c22_pcs *mpcs) +{ + u16 page; + int err; + + mutex_lock(&mpcs->mdio.bus->mdio_lock); + + err = __mdiodev_read(&mpcs->mdio, MII_MARVELL_PHY_PAGE); + if (err < 0) { + dev_err(mpcs->mdio.dev.parent, + "%s: can't read Serdes page register: %pe\n", + mpcs->name, ERR_PTR(err)); + return err; + } + + page = err; + + err = __mdiodev_write(&mpcs->mdio, MII_MARVELL_PHY_PAGE, + MII_MARVELL_FIBER_PAGE); + if (err) { + dev_err(mpcs->mdio.dev.parent, + "%s: can't set Serdes page register: %pe\n", + mpcs->name, ERR_PTR(err)); + return err; + } + + return page; +} + +static int marvell_c22_pcs_restore_page(struct marvell_c22_pcs *mpcs, + int oldpage, int ret) +{ + int err; + + if (oldpage >= 0) { + err = __mdiodev_write(&mpcs->mdio, MII_MARVELL_PHY_PAGE, + oldpage); + if (err) + dev_err(mpcs->mdio.dev.parent, + "%s: can't restore Serdes page register: %pe\n", + mpcs->name, ERR_PTR(err)); + if (!err || ret < 0) + err = ret; + } else { + err = oldpage; + } + mutex_unlock(&mpcs->mdio.bus->mdio_lock); + + return err; +} + +static irqreturn_t marvell_c22_pcs_handle_irq(int irq, void *dev_id) +{ + struct marvell_c22_pcs *mpcs = dev_id; + irqreturn_t status = IRQ_NONE; + int err, oldpage; + + oldpage = marvell_c22_pcs_set_fiber_page(mpcs); + if (oldpage < 0) + goto fail; + + err = __mdiodev_read(&mpcs->mdio, MII_M1011_IEVENT); + if (err >= 0 && err & MII_M1011_IEVENT_LINK_CHANGE) { + phylink_pcs_change(&mpcs->phylink_pcs, true); + status = IRQ_HANDLED; + } + +fail: + marvell_c22_pcs_restore_page(mpcs, oldpage, 0); + + return status; +} + +static int marvell_c22_pcs_modify(struct marvell_c22_pcs *mpcs, u8 reg, + u16 mask, u16 val) +{ + int oldpage, err = 0; + + oldpage = marvell_c22_pcs_set_fiber_page(mpcs); + if (oldpage >= 0) + err = __mdiodev_modify(&mpcs->mdio, reg, mask, val); + + return marvell_c22_pcs_restore_page(mpcs, oldpage, err); +} + +static int marvell_c22_pcs_power(struct marvell_c22_pcs *mpcs, + bool on) +{ + u16 val = on ? 0 : BMCR_PDOWN; + + return marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_PDOWN, val); +} + +static int marvell_c22_pcs_control_irq(struct marvell_c22_pcs *mpcs, + bool enable) +{ + u16 val = enable ? MII_M1011_IMASK_LINK_CHANGE : 0; + + return marvell_c22_pcs_modify(mpcs, MII_M1011_IMASK, + MII_M1011_IMASK_LINK_CHANGE, val); +} + +static int marvell_c22_pcs_enable(struct phylink_pcs *pcs) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + int err; + + err = marvell_c22_pcs_power(mpcs, true); + if (err) + return err; + + return marvell_c22_pcs_control_irq(mpcs, !!mpcs->irq); +} + +static void marvell_c22_pcs_disable(struct phylink_pcs *pcs) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + + marvell_c22_pcs_control_irq(mpcs, false); + marvell_c22_pcs_power(mpcs, false); +} + +static void marvell_c22_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + int oldpage, bmsr, lpa, status; + + state->link = false; + + if (mpcs->link_check && !mpcs->link_check(mpcs)) + return; + + oldpage = marvell_c22_pcs_set_fiber_page(mpcs); + if (oldpage >= 0) { + bmsr = __mdiodev_read(&mpcs->mdio, MII_BMSR); + lpa = __mdiodev_read(&mpcs->mdio, MII_LPA); + status = __mdiodev_read(&mpcs->mdio, MII_M1011_PHY_STATUS); + } + + if (marvell_c22_pcs_restore_page(mpcs, oldpage, 0) >= 0 && + bmsr >= 0 && lpa >= 0 && status >= 0) + mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, + status, state); +} + +static int marvell_c22_pcs_config(struct phylink_pcs *pcs, + unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + int oldpage, adv, err, ret = 0; + u16 bmcr; + + adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); + if (adv < 0) + return 0; + + bmcr = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE : 0; + + oldpage = marvell_c22_pcs_set_fiber_page(mpcs); + if (oldpage < 0) + goto restore; + + err = __mdiodev_modify_changed(&mpcs->mdio, MII_ADVERTISE, 0xffff, adv); + ret = err; + if (err < 0) + goto restore; + + err = __mdiodev_modify_changed(&mpcs->mdio, MII_BMCR, BMCR_ANENABLE, + bmcr); + if (err < 0) { + ret = err; + goto restore; + } + + /* If the ANENABLE bit was changed, the PHY will restart negotiation, + * so we don't need to flag a change to trigger its own restart. + */ + if (err) + ret = 0; + +restore: + return marvell_c22_pcs_restore_page(mpcs, oldpage, ret); +} + +static void marvell_c22_pcs_an_restart(struct phylink_pcs *pcs) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + + marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_ANRESTART, BMCR_ANRESTART); +} + +static void marvell_c22_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, int speed, + int duplex) +{ + struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); + u16 bmcr; + int err; + + if (phylink_autoneg_inband(mode)) + return; + + bmcr = mii_bmcr_encode_fixed(speed, duplex); + + err = marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_SPEED100 | + BMCR_FULLDPLX | BMCR_SPEED1000, bmcr); + if (err) + dev_err(mpcs->mdio.dev.parent, + "%s: failed to configure mpcs: %pe\n", mpcs->name, + ERR_PTR(err)); +} + +static const struct phylink_pcs_ops marvell_c22_pcs_ops = { + .pcs_enable = marvell_c22_pcs_enable, + .pcs_disable = marvell_c22_pcs_disable, + .pcs_get_state = marvell_c22_pcs_get_state, + .pcs_config = marvell_c22_pcs_config, + .pcs_an_restart = marvell_c22_pcs_an_restart, + .pcs_link_up = marvell_c22_pcs_link_up, +}; + +static struct marvell_c22_pcs *marvell_c22_pcs_alloc(struct device *dev, + struct mii_bus *bus, + unsigned int addr) +{ + struct marvell_c22_pcs *mpcs; + + mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); + if (!mpcs) + return NULL; + + mpcs->mdio.dev.parent = dev; + mpcs->mdio.bus = bus; + mpcs->mdio.addr = addr; + mpcs->phylink_pcs.ops = &marvell_c22_pcs_ops; + mpcs->phylink_pcs.neg_mode = true; + + return mpcs; +} + +static int marvell_c22_pcs_setup_irq(struct marvell_c22_pcs *mpcs, + unsigned int irq) +{ + int err; + + mpcs->phylink_pcs.poll = !irq; + mpcs->irq = irq; + + if (irq) { + err = request_threaded_irq(irq, NULL, + marvell_c22_pcs_handle_irq, + IRQF_ONESHOT, mpcs->name, mpcs); + if (err) + return err; + } + + return 0; +} + +/* mv88e6352 specifics */ + +static bool mv88e6352_pcs_link_check(struct marvell_c22_pcs *mpcs) +{ + struct mv88e6xxx_port *port = mpcs->port; + struct mv88e6xxx_chip *chip = port->chip; + u8 cmode; + + /* Port 4 can be in auto-media mode. Check that the port is + * associated with the mpcs. + */ + mv88e6xxx_reg_lock(chip); + chip->info->ops->port_get_cmode(chip, port->port, &cmode); + mv88e6xxx_reg_unlock(chip); + + return cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX || + cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || + cmode == MV88E6XXX_PORT_STS_CMODE_SGMII; +} + +static int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port) +{ + struct marvell_c22_pcs *mpcs; + struct mii_bus *bus; + struct device *dev; + unsigned int irq; + int err; + + mv88e6xxx_reg_lock(chip); + err = mv88e6352_g2_scratch_port_has_serdes(chip, port); + mv88e6xxx_reg_unlock(chip); + if (err <= 0) + return err; + + irq = mv88e6xxx_serdes_irq_mapping(chip, port); + bus = mv88e6xxx_default_mdio_bus(chip); + dev = chip->dev; + + mpcs = marvell_c22_pcs_alloc(dev, bus, MV88E6352_ADDR_SERDES); + if (!mpcs) + return -ENOMEM; + + snprintf(mpcs->name, sizeof(mpcs->name), + "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); + + mpcs->link_check = mv88e6352_pcs_link_check; + mpcs->port = &chip->ports[port]; + + err = marvell_c22_pcs_setup_irq(mpcs, irq); + if (err) { + kfree(mpcs); + return err; + } + + chip->ports[port].pcs_private = &mpcs->phylink_pcs; + + return 0; +} + +static void mv88e6352_pcs_teardown(struct mv88e6xxx_chip *chip, int port) +{ + struct marvell_c22_pcs *mpcs; + struct phylink_pcs *pcs; + + pcs = chip->ports[port].pcs_private; + if (!pcs) + return; + + mpcs = pcs_to_marvell_c22_pcs(pcs); + + if (mpcs->irq) + free_irq(mpcs->irq, mpcs); + + kfree(mpcs); + + chip->ports[port].pcs_private = NULL; +} + +static struct phylink_pcs *mv88e6352_pcs_select(struct mv88e6xxx_chip *chip, + int port, + phy_interface_t interface) +{ + return chip->ports[port].pcs_private; +} + +const struct mv88e6xxx_pcs_ops mv88e6352_pcs_ops = { + .pcs_init = mv88e6352_pcs_init, + .pcs_teardown = mv88e6352_pcs_teardown, + .pcs_select = mv88e6352_pcs_select, +}; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 5ac5687e76a9..5eea0cba3ee0 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -39,12 +39,6 @@ static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip, return mv88e6xxx_phy_read_c45(chip, lane, device, reg, val); } -static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, - int lane, int device, int reg, u16 val) -{ - return mv88e6xxx_phy_write_c45(chip, lane, device, reg, val); -} - int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state) { @@ -116,160 +110,6 @@ int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, return 0; } -int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up) -{ - u16 val, new_val; - int err; - - err = mv88e6352_serdes_read(chip, MII_BMCR, &val); - if (err) - return err; - - if (up) - new_val = val & ~BMCR_PDOWN; - else - new_val = val | BMCR_PDOWN; - - if (val != new_val) - err = mv88e6352_serdes_write(chip, MII_BMCR, new_val); - - return err; -} - -int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise) -{ - u16 adv, bmcr, val; - bool changed; - int err; - - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - adv = 0x0001; - break; - - case PHY_INTERFACE_MODE_1000BASEX: - adv = linkmode_adv_to_mii_adv_x(advertise, - ETHTOOL_LINK_MODE_1000baseX_Full_BIT); - break; - - default: - return 0; - } - - err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val); - if (err) - return err; - - changed = val != adv; - if (changed) { - err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv); - if (err) - return err; - } - - err = mv88e6352_serdes_read(chip, MII_BMCR, &val); - if (err) - return err; - - if (phylink_autoneg_inband(mode)) - bmcr = val | BMCR_ANENABLE; - else - bmcr = val & ~BMCR_ANENABLE; - - if (bmcr == val) - return changed; - - return mv88e6352_serdes_write(chip, MII_BMCR, bmcr); -} - -int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state) -{ - u16 bmsr, lpa, status; - int err; - - err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err); - return err; - } - - err = mv88e6352_serdes_read(chip, 0x11, &status); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); - return err; - } - - err = mv88e6352_serdes_read(chip, MII_LPA, &lpa); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err); - return err; - } - - return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state); -} - -int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - u16 bmcr; - int err; - - err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr); - if (err) - return err; - - return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART); -} - -int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex) -{ - u16 val, bmcr; - int err; - - err = mv88e6352_serdes_read(chip, MII_BMCR, &val); - if (err) - return err; - - bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000); - switch (speed) { - case SPEED_1000: - bmcr |= BMCR_SPEED1000; - break; - case SPEED_100: - bmcr |= BMCR_SPEED100; - break; - case SPEED_10: - break; - } - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - if (bmcr == val) - return 0; - - return mv88e6352_serdes_write(chip, MII_BMCR, bmcr); -} - -int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) -{ - u8 cmode = chip->ports[port].cmode; - int lane = -ENODEV; - - if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) || - (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) || - (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) - lane = 0xff; /* Unused */ - - return lane; -} - struct mv88e6352_serdes_hw_stat { char string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -362,51 +202,6 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, return ARRAY_SIZE(mv88e6352_serdes_hw_stats); } -static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) -{ - u16 bmsr; - int err; - - /* If the link has dropped, we want to know about it. */ - err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr); - if (err) { - dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); - return; - } - - dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS)); -} - -irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - irqreturn_t ret = IRQ_NONE; - u16 status; - int err; - - err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); - if (err) - return ret; - - if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { - ret = IRQ_HANDLED; - mv88e6352_serdes_irq_link(chip, port); - } - - return ret; -} - -int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable) -{ - u16 val = 0; - - if (enable) - val |= MV88E6352_SERDES_INT_LINK_CHANGE; - - return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val); -} - unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) { return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 93d363eb61ea..73cf2d0b8bb3 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -113,51 +113,34 @@ int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state); int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); -int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); -int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise); int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, int lane, unsigned int mode, phy_interface_t interface, const unsigned long *advertise); -int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, int lane, struct phylink_link_state *state); int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, int lane, struct phylink_link_state *state); -int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, - int lane); int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, int lane); -int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex); int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, int lane, int speed, int duplex); unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); -int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on); int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, bool on); int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, bool on); int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip); -int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, bool enable); int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, bool enable); -irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane); irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, @@ -246,5 +229,6 @@ mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane) } extern const struct mv88e6xxx_pcs_ops mv88e6185_pcs_ops; +extern const struct mv88e6xxx_pcs_ops mv88e6352_pcs_ops; #endif -- cgit From e5b732a275f5fae0f1342fb8cf76de654cd51e50 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:53 +0100 Subject: net: dsa: mv88e6xxx: convert 88e639x to phylink_pcs Convert the 88E6390, 88E6390X, and 88E6393X family of switches to use the phylink_pcs infrastructure. Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 80 +--- drivers/net/dsa/mv88e6xxx/pcs-639x.c | 898 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/serdes.c | 785 ------------------------------ drivers/net/dsa/mv88e6xxx/serdes.h | 31 +- 5 files changed, 914 insertions(+), 881 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/pcs-639x.c (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 05976e1f93f6..a9a9651187db 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -11,6 +11,7 @@ mv88e6xxx-objs += global2_scratch.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o mv88e6xxx-objs += pcs-6185.o mv88e6xxx-objs += pcs-6352.o +mv88e6xxx-objs += pcs-639x.o mv88e6xxx-objs += phy.o mv88e6xxx-objs += port.o mv88e6xxx-objs += port_hidden.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 90573407d404..a1ca82715714 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4417,16 +4417,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6341_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .gpio_ops = &mv88e6352_gpio_ops, .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, .serdes_get_strings = mv88e6390_serdes_get_strings, @@ -4434,6 +4426,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .phylink_get_caps = mv88e6341_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -4808,22 +4801,15 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .serdes_get_strings = mv88e6390_serdes_get_strings, .serdes_get_stats = mv88e6390_serdes_get_stats, .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, .phylink_get_caps = mv88e6390_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6190x_ops = { @@ -4873,22 +4859,15 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390x_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .serdes_get_strings = mv88e6390_serdes_get_strings, .serdes_get_stats = mv88e6390_serdes_get_stats, .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .gpio_ops = &mv88e6352_gpio_ops, .phylink_get_caps = mv88e6390x_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6191_ops = { @@ -4936,16 +4915,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .serdes_get_strings = mv88e6390_serdes_get_strings, .serdes_get_stats = mv88e6390_serdes_get_stats, .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, @@ -4953,6 +4924,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, .phylink_get_caps = mv88e6390_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -5102,16 +5074,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .serdes_get_strings = mv88e6390_serdes_get_strings, .serdes_get_stats = mv88e6390_serdes_get_stats, .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, @@ -5120,6 +5084,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6390_ptp_ops, .phylink_get_caps = mv88e6390_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -5264,16 +5229,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, .stu_loadpurge = mv88e6352_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6341_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, @@ -5283,6 +5240,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .phylink_get_caps = mv88e6341_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6350_ops = { @@ -5488,16 +5446,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390_serdes_get_lane, - /* Check status register pause & lpa register */ - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6390_ptp_ops, @@ -5507,6 +5457,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, .serdes_get_regs = mv88e6390_serdes_get_regs, .phylink_get_caps = mv88e6390_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6390x_ops = { @@ -5557,15 +5508,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6390_serdes_power, .serdes_get_lane = mv88e6390x_serdes_get_lane, - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6390_serdes_irq_enable, - .serdes_irq_status = mv88e6390_serdes_irq_status, .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, .serdes_get_strings = mv88e6390_serdes_get_strings, .serdes_get_stats = mv88e6390_serdes_get_stats, @@ -5575,11 +5519,11 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6390_ptp_ops, .phylink_get_caps = mv88e6390x_phylink_get_caps, + .pcs_ops = &mv88e6390_pcs_ops, }; static const struct mv88e6xxx_ops mv88e6393x_ops = { /* MV88E6XXX_FAMILY_6393 */ - .setup_errata = mv88e6393x_serdes_setup_errata, .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -5629,20 +5573,14 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .stu_getnext = mv88e6390_g1_stu_getnext, .stu_loadpurge = mv88e6390_g1_stu_loadpurge, - .serdes_power = mv88e6393x_serdes_power, .serdes_get_lane = mv88e6393x_serdes_get_lane, - .serdes_pcs_get_state = mv88e6393x_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6390_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, - .serdes_irq_enable = mv88e6393x_serdes_irq_enable, - .serdes_irq_status = mv88e6393x_serdes_irq_status, /* TODO: serdes stats */ .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, .phylink_get_caps = mv88e6393x_phylink_get_caps, + .pcs_ops = &mv88e6393x_pcs_ops, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/pcs-639x.c b/drivers/net/dsa/mv88e6xxx/pcs-639x.c new file mode 100644 index 000000000000..98dd49dac421 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/pcs-639x.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Marvell 88E6352 family SERDES PCS support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2017 Andrew Lunn + */ +#include +#include +#include + +#include "chip.h" +#include "global2.h" +#include "phy.h" +#include "port.h" +#include "serdes.h" + +struct mv88e639x_pcs { + struct mdio_device mdio; + struct phylink_pcs sgmii_pcs; + struct phylink_pcs xg_pcs; + bool supports_5g; + phy_interface_t interface; + unsigned int irq; + char name[64]; + irqreturn_t (*handle_irq)(struct mv88e639x_pcs *mpcs); +}; + +static int mv88e639x_read(struct mv88e639x_pcs *mpcs, u16 regnum, u16 *val) +{ + int err; + + err = mdiodev_c45_read(&mpcs->mdio, MDIO_MMD_PHYXS, regnum); + if (err < 0) + return err; + + *val = err; + + return 0; +} + +static int mv88e639x_write(struct mv88e639x_pcs *mpcs, u16 regnum, u16 val) +{ + return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, val); +} + +static int mv88e639x_modify(struct mv88e639x_pcs *mpcs, u16 regnum, u16 mask, + u16 val) +{ + return mdiodev_c45_modify(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, mask, + val); +} + +static int mv88e639x_modify_changed(struct mv88e639x_pcs *mpcs, u16 regnum, + u16 mask, u16 set) +{ + return mdiodev_c45_modify_changed(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, + mask, set); +} + +static struct mv88e639x_pcs * +mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr, + int port) +{ + struct mv88e639x_pcs *mpcs; + + mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); + if (!mpcs) + return NULL; + + mpcs->mdio.dev.parent = dev; + mpcs->mdio.bus = bus; + mpcs->mdio.addr = addr; + + snprintf(mpcs->name, sizeof(mpcs->name), + "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); + + return mpcs; +} + +static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id) +{ + struct mv88e639x_pcs *mpcs = dev_id; + irqreturn_t (*handler)(struct mv88e639x_pcs *); + + handler = READ_ONCE(mpcs->handle_irq); + if (!handler) + return IRQ_NONE; + + return handler(mpcs); +} + +static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs *mpcs, + struct mv88e6xxx_chip *chip, int port) +{ + unsigned int irq; + + irq = mv88e6xxx_serdes_irq_mapping(chip, port); + if (!irq) { + /* Use polling mode */ + mpcs->sgmii_pcs.poll = true; + mpcs->xg_pcs.poll = true; + return 0; + } + + mpcs->irq = irq; + + return request_threaded_irq(irq, NULL, mv88e639x_pcs_handle_irq, + IRQF_ONESHOT, mpcs->name, mpcs); +} + +static void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port) +{ + struct mv88e639x_pcs *mpcs = chip->ports[port].pcs_private; + + if (!mpcs) + return; + + if (mpcs->irq) + free_irq(mpcs->irq, mpcs); + + kfree(mpcs); + + chip->ports[port].pcs_private = NULL; +} + +static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) +{ + return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs); +} + +static irqreturn_t mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs *mpcs) +{ + u16 int_status; + int err; + + err = mv88e639x_read(mpcs, MV88E6390_SGMII_INT_STATUS, &int_status); + if (err) + return IRQ_NONE; + + if (int_status & (MV88E6390_SGMII_INT_LINK_DOWN | + MV88E6390_SGMII_INT_LINK_UP)) { + phylink_pcs_change(&mpcs->sgmii_pcs, + int_status & MV88E6390_SGMII_INT_LINK_UP); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs *mpcs, + bool enable) +{ + u16 val = 0; + + if (enable) + val |= MV88E6390_SGMII_INT_LINK_DOWN | + MV88E6390_SGMII_INT_LINK_UP; + + return mv88e639x_modify(mpcs, MV88E6390_SGMII_INT_ENABLE, + MV88E6390_SGMII_INT_LINK_DOWN | + MV88E6390_SGMII_INT_LINK_UP, val); +} + +static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs *mpcs, + bool enable) +{ + u16 mask, val; + + if (enable) { + mask = BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN; + val = 0; + } else { + mask = val = BMCR_PDOWN; + } + + return mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, mask, val); +} + +static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + /* power enable done in post_config */ + mpcs->handle_irq = mv88e639x_sgmii_handle_irq; + + return mv88e639x_sgmii_pcs_control_irq(mpcs, !!mpcs->irq); +} + +static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_sgmii_pcs_control_irq(mpcs, false); + mv88e639x_sgmii_pcs_control_pwr(mpcs, false); +} + +static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_sgmii_pcs_control_pwr(mpcs, false); +} + +static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_sgmii_pcs_control_pwr(mpcs, true); + + return 0; +} + +static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + u16 bmsr, lpa, status; + int err; + + err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr); + if (err) { + dev_err(mpcs->mdio.dev.parent, + "can't read Serdes PHY %s: %pe\n", + "BMSR", ERR_PTR(err)); + state->link = false; + return; + } + + err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa); + if (err) { + dev_err(mpcs->mdio.dev.parent, + "can't read Serdes PHY %s: %pe\n", + "LPA", ERR_PTR(err)); + state->link = false; + return; + } + + err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status); + if (err) { + dev_err(mpcs->mdio.dev.parent, + "can't read Serdes PHY %s: %pe\n", + "status", ERR_PTR(err)); + state->link = false; + return; + } + + mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status, + state); +} + +static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs, + unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + u16 val, bmcr; + bool changed; + int adv, err; + + adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); + if (adv < 0) + return 0; + + mpcs->interface = interface; + + err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE, + 0xffff, adv); + if (err < 0) + return err; + + changed = err > 0; + + err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val); + if (err) + return err; + + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr = val | BMCR_ANENABLE; + else + bmcr = val & ~BMCR_ANENABLE; + + /* setting ANENABLE triggers a restart of negotiation */ + if (bmcr == val) + return changed; + + return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr); +} + +static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, + BMCR_ANRESTART, BMCR_ANRESTART); +} + +static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs, + unsigned int mode, + phy_interface_t interface, + int speed, int duplex) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + u16 bmcr; + int err; + + if (phylink_autoneg_inband(mode)) + return; + + bmcr = mii_bmcr_encode_fixed(speed, duplex); + + err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, + BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX, + bmcr); + if (err) + dev_err(mpcs->mdio.dev.parent, + "can't access Serdes PHY %s: %pe\n", + "BMCR", ERR_PTR(err)); +} + +static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = { + .pcs_enable = mv88e639x_sgmii_pcs_enable, + .pcs_disable = mv88e639x_sgmii_pcs_disable, + .pcs_pre_config = mv88e639x_sgmii_pcs_pre_config, + .pcs_post_config = mv88e639x_sgmii_pcs_post_config, + .pcs_get_state = mv88e639x_sgmii_pcs_get_state, + .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, + .pcs_config = mv88e639x_sgmii_pcs_config, + .pcs_link_up = mv88e639x_sgmii_pcs_link_up, +}; + +static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) +{ + return container_of(pcs, struct mv88e639x_pcs, xg_pcs); +} + +static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs) +{ + return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, + MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK | + MDIO_CTRL1_LPOWER, 0); +} + +static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs) +{ + mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER, + MDIO_CTRL1_LPOWER); +} + +static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + u16 status; + int err; + + state->link = false; + + err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status); + if (err) { + dev_err(mpcs->mdio.dev.parent, + "can't read Serdes PHY %s: %pe\n", + "STAT1", ERR_PTR(err)); + return; + } + + state->link = !!(status & MDIO_STAT1_LSTATUS); + if (state->link) { + switch (state->interface) { + case PHY_INTERFACE_MODE_5GBASER: + state->speed = SPEED_5000; + break; + + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: + state->speed = SPEED_10000; + break; + + default: + state->link = false; + return; + } + + state->duplex = DUPLEX_FULL; + } +} + +static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs, + unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + return 0; +} + +static struct phylink_pcs * +mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + struct mv88e639x_pcs *mpcs; + + mpcs = chip->ports[port].pcs_private; + if (!mpcs) + return NULL; + + switch (mode) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + return &mpcs->sgmii_pcs; + + case PHY_INTERFACE_MODE_5GBASER: + if (!mpcs->supports_5g) + return NULL; + fallthrough; + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_RXAUI: + return &mpcs->xg_pcs; + + default: + return NULL; + } +} + +/* Marvell 88E6390 Specific support */ + +static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs) +{ + u16 int_status; + int err; + + err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status); + if (err) + return IRQ_NONE; + + if (int_status & (MV88E6390_10G_INT_LINK_DOWN | + MV88E6390_10G_INT_LINK_UP)) { + phylink_pcs_change(&mpcs->xg_pcs, + int_status & MV88E6390_10G_INT_LINK_UP); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) +{ + u16 val = 0; + + if (enable) + val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP; + + return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE, + MV88E6390_10G_INT_LINK_DOWN | + MV88E6390_10G_INT_LINK_UP, val); +} + +static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + int err; + + err = mv88e639x_xg_pcs_enable(mpcs); + if (err) + return err; + + mpcs->handle_irq = mv88e6390_xg_handle_irq; + + return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq); +} + +static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + + mv88e6390_xg_control_irq(mpcs, false); + mv88e639x_xg_pcs_disable(mpcs); +} + +static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = { + .pcs_enable = mv88e6390_xg_pcs_enable, + .pcs_disable = mv88e6390_xg_pcs_disable, + .pcs_get_state = mv88e639x_xg_pcs_get_state, + .pcs_config = mv88e639x_xg_pcs_config, +}; + +static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs) +{ + return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL, + MV88E6390_PG_CONTROL_ENABLE_PC, + MV88E6390_PG_CONTROL_ENABLE_PC); +} + +static int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) +{ + struct mv88e639x_pcs *mpcs; + struct mii_bus *bus; + struct device *dev; + int lane, err; + + lane = mv88e6xxx_serdes_get_lane(chip, port); + if (lane < 0) + return 0; + + bus = mv88e6xxx_default_mdio_bus(chip); + dev = chip->dev; + + mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); + if (!mpcs) + return -ENOMEM; + + mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops; + mpcs->sgmii_pcs.neg_mode = true; + mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops; + mpcs->xg_pcs.neg_mode = true; + + err = mv88e639x_pcs_setup_irq(mpcs, chip, port); + if (err) + goto err_free; + + /* 6390 and 6390x has the checker, 6393x doesn't appear to? */ + /* This is to enable gathering the statistics. Maybe this + * should call out to a helper? Or we could do this at init time. + */ + err = mv88e6390_pcs_enable_checker(mpcs); + if (err) + goto err_free; + + chip->ports[port].pcs_private = mpcs; + + return 0; + +err_free: + kfree(mpcs); + return err; +} + +const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops = { + .pcs_init = mv88e6390_pcs_init, + .pcs_teardown = mv88e639x_pcs_teardown, + .pcs_select = mv88e639x_pcs_select, +}; + +/* Marvell 88E6393X Specific support */ + +static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) +{ + u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | + MV88E6393X_SERDES_CTRL1_RX_PDOWN; + + return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, + enable ? 0 : val); +} + +/* mv88e6393x family errata 4.6: + * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or + * P0_mode is configured for [x]MII. + * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. + * + * It seems that after this workaround the SERDES is automatically powered up + * (the bit is cleared), so power it down. + */ +static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) +{ + int err; + + err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, + MV88E6393X_SERDES_POC_PDOWN | + MV88E6393X_SERDES_POC_RESET, + MV88E6393X_SERDES_POC_RESET); + if (err) + return err; + + err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, + BMCR_PDOWN, BMCR_PDOWN); + if (err) + return err; + + err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); + if (err) + return err; + + return mv88e6393x_power_lane(mpcs, false); +} + +/* mv88e6393x family errata 4.8: + * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not + * come up after hardware reset or software reset of SERDES core. Workaround + * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all + * other modes. + */ +static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs) +{ + u16 reg, poc; + int err; + + err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc); + if (err) + return err; + + poc &= MV88E6393X_SERDES_POC_PCS_MASK; + if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX || + poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || + poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) + reg = MV88E6393X_ERRATA_4_8_BIT; + else + reg = 0; + + return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG, + MV88E6393X_ERRATA_4_8_BIT, reg); +} + +/* mv88e6393x family errata 5.2: + * For optimal signal integrity the following sequence should be applied to + * SERDES operating in 10G mode. These registers only apply to 10G operation + * and have no effect on other speeds. + */ +static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs) +{ + static const struct { + u16 dev, reg, val, mask; + } fixes[] = { + { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, + { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, + { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, + { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, + { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, + { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, + { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, + MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, + }; + int err, i; + + for (i = 0; i < ARRAY_SIZE(fixes); ++i) { + err = mdiodev_c45_modify(&mpcs->mdio, fixes[i].dev, + fixes[i].reg, fixes[i].mask, + fixes[i].val); + if (err) + return err; + } + + return 0; +} + +/* Inband AN is broken on Amethyst in 2500base-x mode when set by standard + * mechanism (via cmode). + * We can get around this by configuring the PCS mode to 1000base-x and then + * writing value 0x58 to register 1e.8000. (This must be done while SerDes + * receiver and transmitter are disabled, which is, when this function is + * called.) + * It seem that when we do this configuration to 2500base-x mode (by changing + * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then + * configure to sgmii or 1000base-x, the device thinks that it already has + * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes + * at 3.125 GHz. + * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from + * 2500base-x mode. + */ +static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) +{ + u16 reg; + int err; + + if (on) + reg = MV88E6393X_SERDES_POC_PCS_1000BASEX | + MV88E6393X_SERDES_POC_AN; + else + reg = MV88E6393X_SERDES_POC_PCS_2500BASEX; + + reg |= MV88E6393X_SERDES_POC_RESET; + + err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, + MV88E6393X_SERDES_POC_PCS_MASK | + MV88E6393X_SERDES_POC_AN | + MV88E6393X_SERDES_POC_RESET, reg); + if (err) + return err; + + return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_VEND1, 0x8000, 0x58); +} + +static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, + phy_interface_t interface, + bool enable) +{ + int err; + + if (interface != PHY_INTERFACE_MODE_2500BASEX) + return 0; + + err = mv88e6393x_fix_2500basex_an(mpcs, enable); + if (err) + dev_err(mpcs->mdio.dev.parent, + "failed to %s 2500basex fix: %pe\n", + enable ? "enable" : "disable", ERR_PTR(err)); + + return err; +} + +static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_sgmii_pcs_disable(pcs); + mv88e6393x_power_lane(mpcs, false); + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); +} + +static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_sgmii_pcs_pre_config(pcs, interface); + mv88e6393x_power_lane(mpcs, false); + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); +} + +static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + int err; + + err = mv88e6393x_erratum_4_8(mpcs); + if (err) + return err; + + err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); + if (err) + return err; + + err = mv88e6393x_power_lane(mpcs, true); + if (err) + return err; + + return mv88e639x_sgmii_pcs_post_config(pcs, interface); +} + +static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { + .pcs_enable = mv88e639x_sgmii_pcs_enable, + .pcs_disable = mv88e6393x_sgmii_pcs_disable, + .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, + .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, + .pcs_get_state = mv88e639x_sgmii_pcs_get_state, + .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, + .pcs_config = mv88e639x_sgmii_pcs_config, + .pcs_link_up = mv88e639x_sgmii_pcs_link_up, +}; + +static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs) +{ + u16 int_status, stat1; + bool link_down; + int err; + + err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status); + if (err) + return IRQ_NONE; + + if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) { + err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1); + if (err) + return IRQ_NONE; + + link_down = !(stat1 & MDIO_STAT1_LSTATUS); + + phylink_pcs_change(&mpcs->xg_pcs, !link_down); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) +{ + u16 val = 0; + + if (enable) + val = MV88E6393X_10G_INT_LINK_CHANGE; + + return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE, + MV88E6393X_10G_INT_LINK_CHANGE, val); +} + +static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + + mpcs->handle_irq = mv88e6393x_xg_handle_irq; + + return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); +} + +static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + + mv88e6393x_xg_control_irq(mpcs, false); + mv88e639x_xg_pcs_disable(mpcs); + mv88e6393x_power_lane(mpcs, false); +} + +/* The PCS has to be powered down while CMODE is changed */ +static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + + mv88e639x_xg_pcs_disable(mpcs); + mv88e6393x_power_lane(mpcs, false); +} + +static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); + int err; + + if (interface == PHY_INTERFACE_MODE_10GBASER) { + err = mv88e6393x_erratum_5_2(mpcs); + if (err) + return err; + } + + err = mv88e6393x_power_lane(mpcs, true); + if (err) + return err; + + return mv88e639x_xg_pcs_enable(mpcs); +} + +static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { + .pcs_enable = mv88e6393x_xg_pcs_enable, + .pcs_disable = mv88e6393x_xg_pcs_disable, + .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, + .pcs_post_config = mv88e6393x_xg_pcs_post_config, + .pcs_get_state = mv88e639x_xg_pcs_get_state, + .pcs_config = mv88e639x_xg_pcs_config, +}; + +static int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port) +{ + struct mv88e639x_pcs *mpcs; + struct mii_bus *bus; + struct device *dev; + int lane, err; + + lane = mv88e6xxx_serdes_get_lane(chip, port); + if (lane < 0) + return 0; + + bus = mv88e6xxx_default_mdio_bus(chip); + dev = chip->dev; + + mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); + if (!mpcs) + return -ENOMEM; + + mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops; + mpcs->sgmii_pcs.neg_mode = true; + mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops; + mpcs->xg_pcs.neg_mode = true; + mpcs->supports_5g = true; + + err = mv88e6393x_erratum_4_6(mpcs); + if (err) + goto err_free; + + err = mv88e639x_pcs_setup_irq(mpcs, chip, port); + if (err) + goto err_free; + + chip->ports[port].pcs_private = mpcs; + + return 0; + +err_free: + kfree(mpcs); + return err; +} + +const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops = { + .pcs_init = mv88e6393x_pcs_init, + .pcs_teardown = mv88e639x_pcs_teardown, + .pcs_select = mv88e639x_pcs_select, +}; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 5eea0cba3ee0..3b4b42651fa3 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -375,57 +375,6 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) return lane; } -/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ -static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, - bool up) -{ - u16 val, new_val; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_10G_CTRL1, &val); - - if (err) - return err; - - if (up) - new_val = val & ~(MDIO_CTRL1_RESET | - MDIO_PCS_CTRL1_LOOPBACK | - MDIO_CTRL1_LPOWER); - else - new_val = val | MDIO_CTRL1_LPOWER; - - if (val != new_val) - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_10G_CTRL1, new_val); - - return err; -} - -/* Set power up/down for SGMII and 1000Base-X */ -static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, - bool up) -{ - u16 val, new_val; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, &val); - if (err) - return err; - - if (up) - new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN); - else - new_val = val | BMCR_PDOWN; - - if (val != new_val) - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, new_val); - - return err; -} - struct mv88e6390_serdes_hw_stat { char string[ETH_GSTRING_LEN]; int reg; @@ -499,484 +448,6 @@ int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, return ARRAY_SIZE(mv88e6390_serdes_hw_stats); } -static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane) -{ - u16 reg; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_PG_CONTROL, ®); - if (err) - return err; - - reg |= MV88E6390_PG_CONTROL_ENABLE_PC; - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_PG_CONTROL, reg); -} - -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up) -{ - u8 cmode = chip->ports[port].cmode; - int err; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - err = mv88e6390_serdes_power_sgmii(chip, lane, up); - break; - case MV88E6XXX_PORT_STS_CMODE_XAUI: - case MV88E6XXX_PORT_STS_CMODE_RXAUI: - err = mv88e6390_serdes_power_10g(chip, lane, up); - break; - default: - err = -EINVAL; - break; - } - - if (!err && up) - err = mv88e6390_serdes_enable_checker(chip, lane); - - return err; -} - -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise) -{ - u16 val, bmcr, adv; - bool changed; - int err; - - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - adv = 0x0001; - break; - - case PHY_INTERFACE_MODE_1000BASEX: - adv = linkmode_adv_to_mii_adv_x(advertise, - ETHTOOL_LINK_MODE_1000baseX_Full_BIT); - break; - - case PHY_INTERFACE_MODE_2500BASEX: - adv = linkmode_adv_to_mii_adv_x(advertise, - ETHTOOL_LINK_MODE_2500baseX_Full_BIT); - break; - - default: - return 0; - } - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_ADVERTISE, &val); - if (err) - return err; - - changed = val != adv; - if (changed) { - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_ADVERTISE, adv); - if (err) - return err; - } - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, &val); - if (err) - return err; - - if (phylink_autoneg_inband(mode)) - bmcr = val | BMCR_ANENABLE; - else - bmcr = val & ~BMCR_ANENABLE; - - /* setting ANENABLE triggers a restart of negotiation */ - if (bmcr == val) - return changed; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, bmcr); -} - -static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, - int port, int lane, struct phylink_link_state *state) -{ - u16 bmsr, lpa, status; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMSR, &bmsr); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err); - return err; - } - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_PHY_STATUS, &status); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); - return err; - } - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_LPA, &lpa); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err); - return err; - } - - return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state); -} - -static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, - int port, int lane, struct phylink_link_state *state) -{ - u16 status; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_10G_STAT1, &status); - if (err) - return err; - - state->link = !!(status & MDIO_STAT1_LSTATUS); - if (state->link) { - state->speed = SPEED_10000; - state->duplex = DUPLEX_FULL; - } - - return 0; -} - -static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, - int port, int lane, - struct phylink_link_state *state) -{ - u16 status; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_10G_STAT1, &status); - if (err) - return err; - - state->link = !!(status & MDIO_STAT1_LSTATUS); - if (state->link) { - if (state->interface == PHY_INTERFACE_MODE_5GBASER) - state->speed = SPEED_5000; - else - state->speed = SPEED_10000; - state->duplex = DUPLEX_FULL; - } - return 0; -} - -/* USXGMII registers for Marvell switch 88e639x are undocumented and this function is based - * on some educated guesses. It appears that there are no status bits related to - * autonegotiation complete or flow control. - */ -static int mv88e639x_serdes_pcs_get_state_usxgmii(struct mv88e6xxx_chip *chip, - int port, int lane, - struct phylink_link_state *state) -{ - u16 status, lp_status; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_USXGMII_PHY_STATUS, &status); - if (err) { - dev_err(chip->dev, "can't read Serdes USXGMII PHY status: %d\n", err); - return err; - } - dev_dbg(chip->dev, "USXGMII PHY status: 0x%x\n", status); - - state->link = !!(status & MDIO_USXGMII_LINK); - state->an_complete = state->link; - - if (state->link) { - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_USXGMII_LP_STATUS, &lp_status); - if (err) { - dev_err(chip->dev, "can't read Serdes USXGMII LP status: %d\n", err); - return err; - } - dev_dbg(chip->dev, "USXGMII LP status: 0x%x\n", lp_status); - /* lp_status appears to include the "link" bit as per USXGMII spec. */ - phylink_decode_usxgmii_word(state, lp_status); - } - return 0; -} - -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state) -{ - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: - return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane, - state); - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_RXAUI: - return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane, - state); - - default: - return -EOPNOTSUPP; - } -} - -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state) -{ - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: - return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane, - state); - case PHY_INTERFACE_MODE_5GBASER: - case PHY_INTERFACE_MODE_10GBASER: - return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane, - state); - case PHY_INTERFACE_MODE_USXGMII: - return mv88e639x_serdes_pcs_get_state_usxgmii(chip, port, lane, - state); - - default: - return -EOPNOTSUPP; - } -} - -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - u16 bmcr; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, &bmcr); - if (err) - return err; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, - bmcr | BMCR_ANRESTART); -} - -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex) -{ - u16 val, bmcr; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, &val); - if (err) - return err; - - bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000); - switch (speed) { - case SPEED_2500: - case SPEED_1000: - bmcr |= BMCR_SPEED1000; - break; - case SPEED_100: - bmcr |= BMCR_SPEED100; - break; - case SPEED_10: - break; - } - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - - if (bmcr == val) - return 0; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, bmcr); -} - -static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, - int port, int lane) -{ - u16 bmsr; - int err; - - /* If the link has dropped, we want to know about it. */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMSR, &bmsr); - if (err) { - dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); - return; - } - - dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS)); -} - -static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip, - int port, u8 lane) -{ - u16 status; - int err; - - /* If the link has dropped, we want to know about it. */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_10G_STAT1, &status); - if (err) { - dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err); - return; - } - - dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS)); -} - -static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, - int lane, bool enable) -{ - u16 val = 0; - - if (enable) - val |= MV88E6390_SGMII_INT_LINK_DOWN | - MV88E6390_SGMII_INT_LINK_UP; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_INT_ENABLE, val); -} - -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable) -{ - u8 cmode = chip->ports[port].cmode; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); - } - - return 0; -} - -static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, - int lane, u16 *status) -{ - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_INT_STATUS, status); - - return err; -} - -static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip, - u8 lane, bool enable) -{ - u16 val = 0; - - if (enable) - val |= MV88E6393X_10G_INT_LINK_CHANGE; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_10G_INT_ENABLE, val); -} - -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, - int lane, bool enable) -{ - u8 cmode = chip->ports[port].cmode; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); - case MV88E6393X_PORT_STS_CMODE_5GBASER: - case MV88E6393X_PORT_STS_CMODE_10GBASER: - case MV88E6393X_PORT_STS_CMODE_USXGMII: - return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable); - } - - return 0; -} - -static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip, - u8 lane, u16 *status) -{ - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_10G_INT_STATUS, status); - - return err; -} - -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - u8 cmode = chip->ports[port].cmode; - irqreturn_t ret = IRQ_NONE; - u16 status; - int err; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); - if (err) - return ret; - if (status & (MV88E6390_SGMII_INT_LINK_DOWN | - MV88E6390_SGMII_INT_LINK_UP)) { - ret = IRQ_HANDLED; - mv88e6390_serdes_irq_link_sgmii(chip, port, lane); - } - break; - case MV88E6393X_PORT_STS_CMODE_5GBASER: - case MV88E6393X_PORT_STS_CMODE_10GBASER: - case MV88E6393X_PORT_STS_CMODE_USXGMII: - err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status); - if (err) - return err; - if (status & MV88E6393X_10G_INT_LINK_CHANGE) { - ret = IRQ_HANDLED; - mv88e6393x_serdes_irq_link_10g(chip, port, lane); - } - break; - } - - return ret; -} - -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - u8 cmode = chip->ports[port].cmode; - irqreturn_t ret = IRQ_NONE; - u16 status; - int err; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); - if (err) - return ret; - if (status & (MV88E6390_SGMII_INT_LINK_DOWN | - MV88E6390_SGMII_INT_LINK_UP)) { - ret = IRQ_HANDLED; - mv88e6390_serdes_irq_link_sgmii(chip, port, lane); - } - } - - return ret; -} - unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) { return irq_find_mapping(chip->g2_irq.domain, port); @@ -1075,259 +546,3 @@ int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port, return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl); } - -static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, - bool on) -{ - u16 reg; - int err; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_CTRL1, ®); - if (err) - return err; - - if (on) - reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | - MV88E6393X_SERDES_CTRL1_RX_PDOWN); - else - reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN | - MV88E6393X_SERDES_CTRL1_RX_PDOWN; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_CTRL1, reg); -} - -static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) -{ - u16 reg; - int err; - - /* mv88e6393x family errata 4.6: - * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD - * mode or P0_mode is configured for [x]MII. - * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. - * - * It seems that after this workaround the SERDES is automatically - * powered up (the bit is cleared), so power it down. - */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, ®); - if (err) - return err; - - reg &= ~MV88E6393X_SERDES_POC_PDOWN; - reg |= MV88E6393X_SERDES_POC_RESET; - - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, reg); - if (err) - return err; - - err = mv88e6390_serdes_power_sgmii(chip, lane, false); - if (err) - return err; - - return mv88e6393x_serdes_power_lane(chip, lane, false); -} - -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) -{ - int err; - - err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE); - if (err) - return err; - - err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE); - if (err) - return err; - - return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE); -} - -static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane) -{ - u16 reg, pcs; - int err; - - /* mv88e6393x family errata 4.8: - * When a SERDES port is operating in 1000BASE-X or SGMII mode link may - * not come up after hardware reset or software reset of SERDES core. - * Workaround is to write SERDES register 4.F074.14=1 for only those - * modes and 0 in all other modes. - */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, &pcs); - if (err) - return err; - - pcs &= MV88E6393X_SERDES_POC_PCS_MASK; - - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_ERRATA_4_8_REG, ®); - if (err) - return err; - - if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX || - pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || - pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) - reg |= MV88E6393X_ERRATA_4_8_BIT; - else - reg &= ~MV88E6393X_ERRATA_4_8_BIT; - - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_ERRATA_4_8_REG, reg); -} - -static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, - u8 cmode) -{ - static const struct { - u16 dev, reg, val, mask; - } fixes[] = { - { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, - { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, - { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, - { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, - { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, - { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, - { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, - MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, - }; - int err, i; - u16 reg; - - /* mv88e6393x family errata 5.2: - * For optimal signal integrity the following sequence should be applied - * to SERDES operating in 10G mode. These registers only apply to 10G - * operation and have no effect on other speeds. - */ - if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER && - cmode != MV88E6393X_PORT_STS_CMODE_USXGMII) - return 0; - - for (i = 0; i < ARRAY_SIZE(fixes); ++i) { - err = mv88e6390_serdes_read(chip, lane, fixes[i].dev, - fixes[i].reg, ®); - if (err) - return err; - - reg &= ~fixes[i].mask; - reg |= fixes[i].val; - - err = mv88e6390_serdes_write(chip, lane, fixes[i].dev, - fixes[i].reg, reg); - if (err) - return err; - } - - return 0; -} - -static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip, - int lane, u8 cmode, bool on) -{ - u16 reg; - int err; - - if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX) - return 0; - - /* Inband AN is broken on Amethyst in 2500base-x mode when set by - * standard mechanism (via cmode). - * We can get around this by configuring the PCS mode to 1000base-x - * and then writing value 0x58 to register 1e.8000. (This must be done - * while SerDes receiver and transmitter are disabled, which is, when - * this function is called.) - * It seem that when we do this configuration to 2500base-x mode (by - * changing PCS mode to 1000base-x and frequency to 3.125 GHz from - * 1.25 GHz) and then configure to sgmii or 1000base-x, the device - * thinks that it already has SerDes at 1.25 GHz and does not change - * the 1e.8000 register, leaving SerDes at 3.125 GHz. - * To avoid this, change PCS mode back to 2500base-x when disabling - * SerDes from 2500base-x mode. - */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, ®); - if (err) - return err; - - reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN); - if (on) - reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX | - MV88E6393X_SERDES_POC_AN; - else - reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX; - reg |= MV88E6393X_SERDES_POC_RESET; - - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, reg); - if (err) - return err; - - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58); - if (err) - return err; - - return 0; -} - -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on) -{ - u8 cmode = chip->ports[port].cmode; - int err; - - if (port != 0 && port != 9 && port != 10) - return -EOPNOTSUPP; - - if (on) { - err = mv88e6393x_serdes_erratum_4_8(chip, lane); - if (err) - return err; - - err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode); - if (err) - return err; - - err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, - true); - if (err) - return err; - - err = mv88e6393x_serdes_power_lane(chip, lane, true); - if (err) - return err; - } - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: - err = mv88e6390_serdes_power_sgmii(chip, lane, on); - break; - case MV88E6393X_PORT_STS_CMODE_5GBASER: - case MV88E6393X_PORT_STS_CMODE_10GBASER: - case MV88E6393X_PORT_STS_CMODE_USXGMII: - err = mv88e6390_serdes_power_10g(chip, lane, on); - break; - default: - err = -EINVAL; - break; - } - - if (err) - return err; - - if (!on) { - err = mv88e6393x_serdes_power_lane(chip, lane, false); - if (err) - return err; - - err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, - false); - } - - return err; -} diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 73cf2d0b8bb3..67584cb1fdb9 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -46,6 +46,10 @@ struct phylink_link_state; /* 10GBASE-R and 10GBASE-X4/X2 */ #define MV88E6390_10G_CTRL1 (0x1000 + MDIO_CTRL1) #define MV88E6390_10G_STAT1 (0x1000 + MDIO_STAT1) +#define MV88E6390_10G_INT_ENABLE 0x9001 +#define MV88E6390_10G_INT_LINK_DOWN BIT(3) +#define MV88E6390_10G_INT_LINK_UP BIT(2) +#define MV88E6390_10G_INT_STATUS 0x9003 #define MV88E6393X_10G_INT_ENABLE 0x9000 #define MV88E6393X_10G_INT_LINK_CHANGE BIT(2) #define MV88E6393X_10G_INT_STATUS 0x9001 @@ -116,35 +120,10 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise); -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, - int lane); -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex); unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port); -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on); -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on); -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip); -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, - int lane, bool enable); -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port, uint8_t *data); @@ -230,5 +209,7 @@ mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane) extern const struct mv88e6xxx_pcs_ops mv88e6185_pcs_ops; extern const struct mv88e6xxx_pcs_ops mv88e6352_pcs_ops; +extern const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops; +extern const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops; #endif -- cgit From d20acfdd3f88fc2a68897c202310194654988276 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 13 Jul 2023 09:42:59 +0100 Subject: net: dsa: mv88e6xxx: cleanup after phylink_pcs conversion Now that mv88e6xxx is completely converted to using phylink_pcs support, we have no need for the serdes methods. Remove all this infrastructure. Also remove the __maybe_unused from mv88e6xxx_pcs_select(). Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 238 +------------------------------------ drivers/net/dsa/mv88e6xxx/chip.h | 21 ---- drivers/net/dsa/mv88e6xxx/port.c | 30 ----- drivers/net/dsa/mv88e6xxx/serdes.h | 45 ------- 4 files changed, 2 insertions(+), 332 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index a1ca82715714..6174855188d9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -492,81 +492,6 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) return !!(reg & MV88E6XXX_PORT_STS_PHY_DETECT); } -static int mv88e6xxx_serdes_pcs_get_state(struct dsa_switch *ds, int port, - struct phylink_link_state *state) -{ - struct mv88e6xxx_chip *chip = ds->priv; - int lane; - int err; - - mv88e6xxx_reg_lock(chip); - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0 && chip->info->ops->serdes_pcs_get_state) - err = chip->info->ops->serdes_pcs_get_state(chip, port, lane, - state); - else - err = -EOPNOTSUPP; - mv88e6xxx_reg_unlock(chip); - - return err; -} - -static int mv88e6xxx_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise) -{ - const struct mv88e6xxx_ops *ops = chip->info->ops; - int lane; - - if (ops->serdes_pcs_config) { - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0) - return ops->serdes_pcs_config(chip, port, lane, mode, - interface, advertise); - } - - return 0; -} - -static void mv88e6xxx_serdes_pcs_an_restart(struct dsa_switch *ds, int port) -{ - struct mv88e6xxx_chip *chip = ds->priv; - const struct mv88e6xxx_ops *ops; - int err = 0; - int lane; - - ops = chip->info->ops; - - if (ops->serdes_pcs_an_restart) { - mv88e6xxx_reg_lock(chip); - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0) - err = ops->serdes_pcs_an_restart(chip, port, lane); - mv88e6xxx_reg_unlock(chip); - - if (err) - dev_err(ds->dev, "p%d: failed to restart AN\n", port); - } -} - -static int mv88e6xxx_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - unsigned int mode, - int speed, int duplex) -{ - const struct mv88e6xxx_ops *ops = chip->info->ops; - int lane; - - if (!phylink_autoneg_inband(mode) && ops->serdes_pcs_link_up) { - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0) - return ops->serdes_pcs_link_up(chip, port, lane, - speed, duplex); - } - - return 0; -} - static const u8 mv88e6185_phy_interface_modes[] = { [MV88E6185_PORT_STS_CMODE_GMII_FD] = PHY_INTERFACE_MODE_GMII, [MV88E6185_PORT_STS_CMODE_MII_100_FD_PS] = PHY_INTERFACE_MODE_MII, @@ -845,15 +770,8 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, config->supported_interfaces); } - /* If we have a .pcs_ops, or don't have a .serdes_pcs_get_state, - * serdes_pcs_config, serdes_pcs_an_restart, or serdes_pcs_link_up, - * we are not legacy. - */ - if (chip->info->ops->pcs_ops || - (!chip->info->ops->serdes_pcs_get_state && - !chip->info->ops->serdes_pcs_config && - !chip->info->ops->serdes_pcs_an_restart && - !chip->info->ops->serdes_pcs_link_up)) + /* If we have a .pcs_init, we are not legacy. */ + if (chip->info->ops->pcs_ops) config->legacy_pre_march2020 = false; } @@ -907,16 +825,6 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, state->interface); if (err && err != -EOPNOTSUPP) goto err_unlock; - - err = mv88e6xxx_serdes_pcs_config(chip, port, mode, - state->interface, - state->advertising); - /* FIXME: we should restart negotiation if something changed - - * which is something we get if we convert to using phylinks - * PCS operations. - */ - if (err > 0) - err = 0; } err_unlock: @@ -1000,17 +908,6 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, */ if (!mv88e6xxx_port_ppu_updates(chip, port) || mode == MLO_AN_FIXED) { - /* FIXME: for an automedia port, should we force the link - * down here - what if the link comes up due to "other" media - * while we're bringing the port up, how is the exclusivity - * handled in the Marvell hardware? E.g. port 2 on 88E6390 - * shared between internal PHY and Serdes. - */ - err = mv88e6xxx_serdes_pcs_link_up(chip, port, mode, speed, - duplex); - if (err) - goto error; - if (ops->port_set_speed_duplex) { err = ops->port_set_speed_duplex(chip, port, speed, duplex); @@ -3181,102 +3078,6 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port) return 0; } -static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id) -{ - struct mv88e6xxx_port *mvp = dev_id; - struct mv88e6xxx_chip *chip = mvp->chip; - irqreturn_t ret = IRQ_NONE; - int port = mvp->port; - int lane; - - mv88e6xxx_reg_lock(chip); - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0) - ret = mv88e6xxx_serdes_irq_status(chip, port, lane); - mv88e6xxx_reg_unlock(chip); - - return ret; -} - -static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - struct mv88e6xxx_port *dev_id = &chip->ports[port]; - unsigned int irq; - int err; - - /* Nothing to request if this SERDES port has no IRQ */ - irq = mv88e6xxx_serdes_irq_mapping(chip, port); - if (!irq) - return 0; - - snprintf(dev_id->serdes_irq_name, sizeof(dev_id->serdes_irq_name), - "mv88e6xxx-%s-serdes-%d", dev_name(chip->dev), port); - - /* Requesting the IRQ will trigger IRQ callbacks, so release the lock */ - mv88e6xxx_reg_unlock(chip); - err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn, - IRQF_ONESHOT, dev_id->serdes_irq_name, - dev_id); - mv88e6xxx_reg_lock(chip); - if (err) - return err; - - dev_id->serdes_irq = irq; - - return mv88e6xxx_serdes_irq_enable(chip, port, lane); -} - -static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port, - int lane) -{ - struct mv88e6xxx_port *dev_id = &chip->ports[port]; - unsigned int irq = dev_id->serdes_irq; - int err; - - /* Nothing to free if no IRQ has been requested */ - if (!irq) - return 0; - - err = mv88e6xxx_serdes_irq_disable(chip, port, lane); - - /* Freeing the IRQ will trigger IRQ callbacks, so release the lock */ - mv88e6xxx_reg_unlock(chip); - free_irq(irq, dev_id); - mv88e6xxx_reg_lock(chip); - - dev_id->serdes_irq = 0; - - return err; -} - -static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port, - bool on) -{ - int lane; - int err; - - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane < 0) - return 0; - - if (on) { - err = mv88e6xxx_serdes_power_up(chip, port, lane); - if (err) - return err; - - err = mv88e6xxx_serdes_irq_request(chip, port, lane); - } else { - err = mv88e6xxx_serdes_irq_free(chip, port, lane); - if (err) - return err; - - err = mv88e6xxx_serdes_power_down(chip, port, lane); - } - - return err; -} - static int mv88e6xxx_set_egress_port(struct mv88e6xxx_chip *chip, enum mv88e6xxx_egress_direction direction, int port) @@ -3601,37 +3402,6 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) return ret; } -static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port, - struct phy_device *phydev) -{ - struct mv88e6xxx_chip *chip = ds->priv; - int err; - - /* Do not control power or request irqs if using PCS */ - if (chip->info->ops->pcs_ops) - return 0; - - mv88e6xxx_reg_lock(chip); - err = mv88e6xxx_serdes_power(chip, port, true); - mv88e6xxx_reg_unlock(chip); - - return err; -} - -static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port) -{ - struct mv88e6xxx_chip *chip = ds->priv; - - /* Do not control power or request irqs if using PCS */ - if (chip->info->ops->pcs_ops) - return; - - mv88e6xxx_reg_lock(chip); - if (mv88e6xxx_serdes_power(chip, port, false)) - dev_err(chip->dev, "failed to power off SERDES\n"); - mv88e6xxx_reg_unlock(chip); -} - static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, unsigned int ageing_time) { @@ -7013,18 +6783,14 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .port_teardown = mv88e6xxx_port_teardown, .phylink_get_caps = mv88e6xxx_get_caps, .phylink_mac_select_pcs = mv88e6xxx_mac_select_pcs, - .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, .phylink_mac_prepare = mv88e6xxx_mac_prepare, .phylink_mac_config = mv88e6xxx_mac_config, .phylink_mac_finish = mv88e6xxx_mac_finish, - .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart, .phylink_mac_link_down = mv88e6xxx_mac_link_down, .phylink_mac_link_up = mv88e6xxx_mac_link_up, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, - .port_enable = mv88e6xxx_port_enable, - .port_disable = mv88e6xxx_port_disable, .port_max_mtu = mv88e6xxx_get_max_mtu, .port_change_mtu = mv88e6xxx_change_mtu, .get_mac_eee = mv88e6xxx_get_mac_eee, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 1dd310a3c41f..44383a03ef2f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -286,8 +286,6 @@ struct mv88e6xxx_port { u8 cmode; bool mirror_ingress; bool mirror_egress; - unsigned int serdes_irq; - char serdes_irq_name[64]; struct devlink_region *region; void *pcs_private; @@ -592,31 +590,12 @@ struct mv88e6xxx_ops { int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); - /* Power on/off a SERDES interface */ - int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, int lane, - bool up); - /* SERDES lane mapping */ int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port); - int (*serdes_pcs_get_state)(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); - int (*serdes_pcs_config)(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise); - int (*serdes_pcs_an_restart)(struct mv88e6xxx_chip *chip, int port, - int lane); - int (*serdes_pcs_link_up)(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex); - /* SERDES interrupt handling */ unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip, int port); - int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); - irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port, - int lane); /* Statistics from the SERDES interface */ int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index dd66ec902d4c..5394a8cf7bf1 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -524,7 +524,6 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode, bool force) { u16 cmode; - int lane; u16 reg; int err; @@ -577,19 +576,6 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, if (cmode == chip->ports[port].cmode && !force) return 0; - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane >= 0) { - if (chip->ports[port].serdes_irq) { - err = mv88e6xxx_serdes_irq_disable(chip, port, lane); - if (err) - return err; - } - - err = mv88e6xxx_serdes_power_down(chip, port, lane); - if (err) - return err; - } - chip->ports[port].cmode = 0; if (cmode) { @@ -605,22 +591,6 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, return err; chip->ports[port].cmode = cmode; - - lane = mv88e6xxx_serdes_get_lane(chip, port); - if (lane == -ENODEV) - return 0; - if (lane < 0) - return lane; - - err = mv88e6xxx_serdes_power_up(chip, port, lane); - if (err) - return err; - - if (chip->ports[port].serdes_irq) { - err = mv88e6xxx_serdes_irq_enable(chip, port, lane); - if (err) - return err; - } } return 0; diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 67584cb1fdb9..aac95cab46e3 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -153,24 +153,6 @@ static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, return chip->info->ops->serdes_get_lane(chip, port); } -static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip, - int port, int lane) -{ - if (!chip->info->ops->serdes_power) - return -EOPNOTSUPP; - - return chip->info->ops->serdes_power(chip, port, lane, true); -} - -static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip, - int port, int lane) -{ - if (!chip->info->ops->serdes_power) - return -EOPNOTSUPP; - - return chip->info->ops->serdes_power(chip, port, lane, false); -} - static inline unsigned int mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) { @@ -180,33 +162,6 @@ mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) return chip->info->ops->serdes_irq_mapping(chip, port); } -static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip, - int port, int lane) -{ - if (!chip->info->ops->serdes_irq_enable) - return -EOPNOTSUPP; - - return chip->info->ops->serdes_irq_enable(chip, port, lane, true); -} - -static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip, - int port, int lane) -{ - if (!chip->info->ops->serdes_irq_enable) - return -EOPNOTSUPP; - - return chip->info->ops->serdes_irq_enable(chip, port, lane, false); -} - -static inline irqreturn_t -mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane) -{ - if (!chip->info->ops->serdes_irq_status) - return IRQ_NONE; - - return chip->info->ops->serdes_irq_status(chip, port, lane); -} - extern const struct mv88e6xxx_pcs_ops mv88e6185_pcs_ops; extern const struct mv88e6xxx_pcs_ops mv88e6352_pcs_ops; extern const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops; -- cgit From 02b34d03a24b18970925cf57434be28ba4a29d3a Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Thu, 13 Jul 2023 15:20:23 +0200 Subject: netdevsim: add dummy macsec offload When the kernel is compiled with MACsec support, add the NETIF_F_HW_MACSEC feature to netdevsim devices and implement macsec_ops. To allow easy testing of failure from the device, support is limited to 3 SecY's per netdevsim device, and 1 RXSC per SecY. v2: - nsim_macsec_add_secy, return -ENOSPC if secy_count isn't full but we can't find an empty slot (Simon Horman) - add sci_to_cpu to make sparse happy (Simon Horman) - remove set but not used secy variable (kernel test robot and Simon Horman) Signed-off-by: Sabrina Dubroca Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/netdevsim/Makefile | 4 + drivers/net/netdevsim/macsec.c | 356 ++++++++++++++++++++++++++++++++++++++ drivers/net/netdevsim/netdev.c | 3 + drivers/net/netdevsim/netdevsim.h | 34 ++++ 4 files changed, 397 insertions(+) create mode 100644 drivers/net/netdevsim/macsec.c (limited to 'drivers/net') diff --git a/drivers/net/netdevsim/Makefile b/drivers/net/netdevsim/Makefile index 5735e5b1a2cb..f8de93bc5f5b 100644 --- a/drivers/net/netdevsim/Makefile +++ b/drivers/net/netdevsim/Makefile @@ -17,3 +17,7 @@ endif ifneq ($(CONFIG_PSAMPLE),) netdevsim-objs += psample.o endif + +ifneq ($(CONFIG_MACSEC),) +netdevsim-objs += macsec.o +endif diff --git a/drivers/net/netdevsim/macsec.c b/drivers/net/netdevsim/macsec.c new file mode 100644 index 000000000000..0d5f50430dd3 --- /dev/null +++ b/drivers/net/netdevsim/macsec.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include "netdevsim.h" + +static inline u64 sci_to_cpu(sci_t sci) +{ + return be64_to_cpu((__force __be64)sci); +} + +static int nsim_macsec_find_secy(struct netdevsim *ns, sci_t sci) +{ + int i; + + for (i = 0; i < NSIM_MACSEC_MAX_SECY_COUNT; i++) { + if (ns->macsec.nsim_secy[i].sci == sci) + return i; + } + + return -1; +} + +static int nsim_macsec_find_rxsc(struct nsim_secy *ns_secy, sci_t sci) +{ + int i; + + for (i = 0; i < NSIM_MACSEC_MAX_RXSC_COUNT; i++) { + if (ns_secy->nsim_rxsc[i].sci == sci) + return i; + } + + return -1; +} + +static int nsim_macsec_add_secy(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + if (ns->macsec.nsim_secy_count == NSIM_MACSEC_MAX_SECY_COUNT) + return -ENOSPC; + + for (idx = 0; idx < NSIM_MACSEC_MAX_SECY_COUNT; idx++) { + if (!ns->macsec.nsim_secy[idx].used) + break; + } + + if (idx == NSIM_MACSEC_MAX_SECY_COUNT) { + netdev_err(ctx->netdev, "%s: nsim_secy_count not full but all SecYs used\n", + __func__); + return -ENOSPC; + } + + netdev_dbg(ctx->netdev, "%s: adding new secy with sci %08llx at index %d\n", + __func__, sci_to_cpu(ctx->secy->sci), idx); + ns->macsec.nsim_secy[idx].used = true; + ns->macsec.nsim_secy[idx].nsim_rxsc_count = 0; + ns->macsec.nsim_secy[idx].sci = ctx->secy->sci; + ns->macsec.nsim_secy_count++; + + return 0; +} + +static int nsim_macsec_upd_secy(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: updating secy with sci %08llx at index %d\n", + __func__, sci_to_cpu(ctx->secy->sci), idx); + + return 0; +} + +static int nsim_macsec_del_secy(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: removing SecY with SCI %08llx at index %d\n", + __func__, sci_to_cpu(ctx->secy->sci), idx); + + ns->macsec.nsim_secy[idx].used = false; + memset(&ns->macsec.nsim_secy[idx], 0, sizeof(ns->macsec.nsim_secy[idx])); + ns->macsec.nsim_secy_count--; + + return 0; +} + +static int nsim_macsec_add_rxsc(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + if (secy->nsim_rxsc_count == NSIM_MACSEC_MAX_RXSC_COUNT) + return -ENOSPC; + + for (idx = 0; idx < NSIM_MACSEC_MAX_RXSC_COUNT; idx++) { + if (!secy->nsim_rxsc[idx].used) + break; + } + + if (idx == NSIM_MACSEC_MAX_RXSC_COUNT) + netdev_err(ctx->netdev, "%s: nsim_rxsc_count not full but all RXSCs used\n", + __func__); + + netdev_dbg(ctx->netdev, "%s: adding new rxsc with sci %08llx at index %d\n", + __func__, sci_to_cpu(ctx->rx_sc->sci), idx); + secy->nsim_rxsc[idx].used = true; + secy->nsim_rxsc[idx].sci = ctx->rx_sc->sci; + secy->nsim_rxsc_count++; + + return 0; +} + +static int nsim_macsec_upd_rxsc(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n", + __func__, sci_to_cpu(ctx->rx_sc->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: updating RXSC with sci %08llx at index %d\n", + __func__, sci_to_cpu(ctx->rx_sc->sci), idx); + + return 0; +} + +static int nsim_macsec_del_rxsc(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n", + __func__, sci_to_cpu(ctx->rx_sc->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: removing RXSC with sci %08llx at index %d\n", + __func__, sci_to_cpu(ctx->rx_sc->sci), idx); + + secy->nsim_rxsc[idx].used = false; + memset(&secy->nsim_rxsc[idx], 0, sizeof(secy->nsim_rxsc[idx])); + secy->nsim_rxsc_count--; + + return 0; +} + +static int nsim_macsec_add_rxsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num); + + return 0; +} + +static int nsim_macsec_upd_rxsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num); + + return 0; +} + +static int nsim_macsec_del_rxsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + struct nsim_secy *secy; + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + secy = &ns->macsec.nsim_secy[idx]; + + idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num); + + return 0; +} + +static int nsim_macsec_add_txsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num); + + return 0; +} + +static int nsim_macsec_upd_txsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num); + + return 0; +} + +static int nsim_macsec_del_txsa(struct macsec_context *ctx) +{ + struct netdevsim *ns = netdev_priv(ctx->netdev); + int idx; + + idx = nsim_macsec_find_secy(ns, ctx->secy->sci); + if (idx < 0) { + netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n", + __func__, sci_to_cpu(ctx->secy->sci)); + return -ENOENT; + } + + netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n", + __func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num); + + return 0; +} + +static const struct macsec_ops nsim_macsec_ops = { + .mdo_add_secy = nsim_macsec_add_secy, + .mdo_upd_secy = nsim_macsec_upd_secy, + .mdo_del_secy = nsim_macsec_del_secy, + .mdo_add_rxsc = nsim_macsec_add_rxsc, + .mdo_upd_rxsc = nsim_macsec_upd_rxsc, + .mdo_del_rxsc = nsim_macsec_del_rxsc, + .mdo_add_rxsa = nsim_macsec_add_rxsa, + .mdo_upd_rxsa = nsim_macsec_upd_rxsa, + .mdo_del_rxsa = nsim_macsec_del_rxsa, + .mdo_add_txsa = nsim_macsec_add_txsa, + .mdo_upd_txsa = nsim_macsec_upd_txsa, + .mdo_del_txsa = nsim_macsec_del_txsa, +}; + +void nsim_macsec_init(struct netdevsim *ns) +{ + ns->netdev->macsec_ops = &nsim_macsec_ops; + ns->netdev->features |= NETIF_F_HW_MACSEC; + memset(&ns->macsec, 0, sizeof(ns->macsec)); +} + +void nsim_macsec_teardown(struct netdevsim *ns) +{ +} diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 35fa1ca98671..0c8daeb0d62b 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -304,6 +304,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns) if (err) goto err_utn_destroy; + nsim_macsec_init(ns); nsim_ipsec_init(ns); err = register_netdevice(ns->netdev); @@ -314,6 +315,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns) err_ipsec_teardown: nsim_ipsec_teardown(ns); + nsim_macsec_teardown(ns); nsim_bpf_uninit(ns); err_utn_destroy: rtnl_unlock(); @@ -374,6 +376,7 @@ void nsim_destroy(struct netdevsim *ns) rtnl_lock(); unregister_netdevice(dev); if (nsim_dev_port_is_pf(ns->nsim_dev_port)) { + nsim_macsec_teardown(ns); nsim_ipsec_teardown(ns); nsim_bpf_uninit(ns); } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 7d8ed8d8df5c..7be98b7dcca9 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -23,6 +23,7 @@ #include #include #include +#include #define DRV_NAME "netdevsim" @@ -52,6 +53,25 @@ struct nsim_ipsec { u32 ok; }; +#define NSIM_MACSEC_MAX_SECY_COUNT 3 +#define NSIM_MACSEC_MAX_RXSC_COUNT 1 +struct nsim_rxsc { + sci_t sci; + bool used; +}; + +struct nsim_secy { + sci_t sci; + struct nsim_rxsc nsim_rxsc[NSIM_MACSEC_MAX_RXSC_COUNT]; + u8 nsim_rxsc_count; + bool used; +}; + +struct nsim_macsec { + struct nsim_secy nsim_secy[NSIM_MACSEC_MAX_SECY_COUNT]; + u8 nsim_secy_count; +}; + struct nsim_ethtool_pauseparam { bool rx; bool tx; @@ -93,6 +113,7 @@ struct netdevsim { bool bpf_map_accept; struct nsim_ipsec ipsec; + struct nsim_macsec macsec; struct { u32 inject_error; u32 sleep; @@ -366,6 +387,19 @@ static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) } #endif +#if IS_ENABLED(CONFIG_MACSEC) +void nsim_macsec_init(struct netdevsim *ns); +void nsim_macsec_teardown(struct netdevsim *ns); +#else +static inline void nsim_macsec_init(struct netdevsim *ns) +{ +} + +static inline void nsim_macsec_teardown(struct netdevsim *ns) +{ +} +#endif + struct nsim_bus_dev { struct device dev; struct list_head list; -- cgit From 352be882deda87d30b5f6249994e2ab2749e5106 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:24 +0200 Subject: mlxsw: spectrum_switchdev: Pass extack to mlxsw_sp_br_ban_rif_pvid_change() Currently the reason for rejection of PVID manipulation is dumped to syslog, and a generic -EBUSY is returned to the userspace. But switchdev_handle_port_obj_add(), through which we get to mlxsw_sp_port_vlans_add(), handles extack just fine, and we can pass the message this way. This improves visibility into reasons why the request to change PVID was rejected. Before the change: # bridge vlan add dev br vid 2 self pvid untagged RTNETLINK answers: Device or resource busy (plus a syslog line) After the change: # bridge vlan add dev br vid 2 self pvid untagged Error: mlxsw_spectrum: Can't change PVID, it's used by router interface. Note that this particular error message is going away in the following patches. However the ability to pass error messages through extack will be useful more broadly for communicating in particular reasons why a RIF failed to be created. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index d88e62bc759f..a3365f7437d6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1481,7 +1481,8 @@ err_port_vlan_set: static int mlxsw_sp_br_ban_rif_pvid_change(struct mlxsw_sp *mlxsw_sp, const struct net_device *br_dev, - const struct switchdev_obj_port_vlan *vlan) + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { u16 pvid; @@ -1491,12 +1492,12 @@ mlxsw_sp_br_ban_rif_pvid_change(struct mlxsw_sp *mlxsw_sp, if (vlan->flags & BRIDGE_VLAN_INFO_PVID) { if (vlan->vid != pvid) { - netdev_err(br_dev, "Can't change PVID, it's used by router interface\n"); + NL_SET_ERR_MSG_MOD(extack, "Can't change PVID, it's used by router interface"); return -EBUSY; } } else { if (vlan->vid == pvid) { - netdev_err(br_dev, "Can't remove PVID, it's used by router interface\n"); + NL_SET_ERR_MSG_MOD(extack, "Can't remove PVID, it's used by router interface"); return -EBUSY; } } @@ -1519,7 +1520,8 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, if (br_vlan_enabled(orig_dev)) err = mlxsw_sp_br_ban_rif_pvid_change(mlxsw_sp, - orig_dev, vlan); + orig_dev, vlan, + extack); if (!err) err = -EOPNOTSUPP; return err; -- cgit From 5ca9f42caf8103a5b51cbe78777f7df972cc6263 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:25 +0200 Subject: mlxsw: spectrum_router: Pass struct mlxsw_sp_rif_params to fid_get The fid_get callback is called to allocate a FID for the newly-created RIF. In a following patch, the fid_get implementation for VLANs will be modified to take the VLAN ID from the parameters instead of deducing it from the netdevice. To that end, propagate the RIF parameters to the fid_get callback. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index b32adf277a22..adfb1ef2a664 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -139,6 +139,7 @@ struct mlxsw_sp_rif_ops { struct netlink_ext_ack *extack); void (*deconfigure)(struct mlxsw_sp_rif *rif); struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif, + const struct mlxsw_sp_rif_params *params, struct netlink_ext_ack *extack); void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac); }; @@ -8300,7 +8301,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, rif->rif_entries = rif_entries; if (ops->fid_get) { - fid = ops->fid_get(rif, extack); + fid = ops->fid_get(rif, params, extack); if (IS_ERR(fid)) { err = PTR_ERR(fid); goto err_fid_get; @@ -8678,7 +8679,7 @@ __mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, return PTR_ERR(rif); /* FID was already created, just take a reference */ - fid = rif->ops->fid_get(rif, extack); + fid = rif->ops->fid_get(rif, ¶ms, extack); err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid); if (err) goto err_fid_port_vid_map; @@ -9724,6 +9725,7 @@ static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif) static struct mlxsw_sp_fid * mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif, + const struct mlxsw_sp_rif_params *params, struct netlink_ext_ack *extack) { return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index); @@ -9836,6 +9838,7 @@ static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif) static struct mlxsw_sp_fid * mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif, + const struct mlxsw_sp_rif_params *params, struct netlink_ext_ack *extack) { int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif); @@ -9869,6 +9872,7 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = { static struct mlxsw_sp_fid * mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, + const struct mlxsw_sp_rif_params *params, struct netlink_ext_ack *extack) { struct net_device *dev = mlxsw_sp_rif_dev(rif); -- cgit From a0944b24d278b2657ffd5dcbaaf8c24d43e39e0c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:26 +0200 Subject: mlxsw: spectrum_router: Take VID for VLAN FIDs from RIF params Currently, when an IP address is added to a bridge that has no PVID, the operation is rejected. An IP address addition is interpreted as a request to create a RIF for the bridge device, but without a PVID there is no VLAN for which the RIF should be created. Thus the correct way to create a RIF for a bridge as a user is to first add a PVID, and then add the IP address. Ideally this ordering requirement would not exist. RIF would be created either because an IP address is added, or because a PVID is added, depending on which comes last. For that, the switchdev code (which notices the PVID change request) must be able to request that a RIF is created with a given VLAN ID, because at the time that the PVID notification is distributed, the PVID setting is not yet visible for querying. Therefore when creating a VLAN-based RIF, use mlxsw_sp_rif_params.vid to communicate the VID, and do not determine it ad-hoc in the fid_get callback. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index adfb1ef2a664..e840ca9a9673 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8665,14 +8665,17 @@ __mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, { struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_rif_params params = { - .dev = l3_dev, - }; + struct mlxsw_sp_rif_params params; u16 vid = mlxsw_sp_port_vlan->vid; struct mlxsw_sp_rif *rif; struct mlxsw_sp_fid *fid; int err; + params = (struct mlxsw_sp_rif_params) { + .dev = l3_dev, + .vid = vid, + }; + mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan); rif = mlxsw_sp_rif_subport_get(mlxsw_sp, ¶ms, extack); if (IS_ERR(rif)) @@ -8830,6 +8833,7 @@ static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, .dev = l3_dev, }; struct mlxsw_sp_rif *rif; + int err; switch (event) { case NETDEV_UP: @@ -8841,6 +8845,13 @@ static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(extack, "Adding an IP address to 802.1ad bridge is not supported"); return -EOPNOTSUPP; } + err = br_vlan_get_pvid(l3_dev, ¶ms.vid); + if (err < 0 || !params.vid) { + NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); + return -EINVAL; + } + } else if (is_vlan_dev(l3_dev)) { + params.vid = vlan_dev_vlan_id(l3_dev); } rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack); if (IS_ERR(rif)) @@ -9877,23 +9888,17 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, { struct net_device *dev = mlxsw_sp_rif_dev(rif); struct net_device *br_dev; - u16 vid; - int err; + + if (WARN_ON(!params->vid)) + return ERR_PTR(-EINVAL); if (is_vlan_dev(dev)) { - vid = vlan_dev_vlan_id(dev); br_dev = vlan_dev_real_dev(dev); if (WARN_ON(!netif_is_bridge_master(br_dev))) return ERR_PTR(-EINVAL); - } else { - err = br_vlan_get_pvid(dev, &vid); - if (err < 0 || !vid) { - NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); - return ERR_PTR(-EINVAL); - } } - return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid); + return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, params->vid); } static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) -- cgit From a24a4d29ff0a4a425913e3f538ba429f2bbd2bbd Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:27 +0200 Subject: mlxsw: spectrum_router: Adjust mlxsw_sp_inetaddr_vlan_event() coding style The bridge branch of the dispatch in this function is going to get more code and will need curly braces. Per the doctrine, that means the whole if-else chain should get them. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index e840ca9a9673..3a5103269830 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8877,15 +8877,17 @@ static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp, if (netif_is_bridge_port(vlan_dev)) return 0; - if (mlxsw_sp_port_dev_check(real_dev)) + if (mlxsw_sp_port_dev_check(real_dev)) { return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev, event, vid, extack); - else if (netif_is_lag_master(real_dev)) + } else if (netif_is_lag_master(real_dev)) { return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event, vid, extack); - else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev)) + } else if (netif_is_bridge_master(real_dev) && + br_vlan_enabled(real_dev)) { return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev, event, extack); + } return 0; } -- cgit From 3430f2cf91a4b0ee4d639644c75f7c7b4b0bf1cf Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:28 +0200 Subject: mlxsw: spectrum_router: mlxsw_sp_inetaddr_bridge_event: Add an argument For purposes of replay, mlxsw_sp_inetaddr_bridge_event() will need to make decisions based on the proposed value of PVID. Querying PVID reveals the current settings, not the in-flight values that the user requested and that the notifiers are acting upon. Add a parameter, lower_pvid, which carries the proposed PVID of the lower bridge, or -1 if the lower is not a bridge. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 3a5103269830..63f40d16be3b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8826,6 +8826,7 @@ static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev, static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, struct net_device *l3_dev, + int lower_pvid, unsigned long event, struct netlink_ext_ack *extack) { @@ -8873,6 +8874,8 @@ static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp, { struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); u16 vid = vlan_dev_vlan_id(vlan_dev); + u16 lower_pvid; + int err; if (netif_is_bridge_port(vlan_dev)) return 0; @@ -8885,7 +8888,11 @@ static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp, vid, extack); } else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev)) { - return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev, event, + err = br_vlan_get_pvid(real_dev, &lower_pvid); + if (err) + return err; + return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev, + lower_pvid, event, extack); } @@ -9022,7 +9029,7 @@ static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp, else if (netif_is_lag_master(dev)) return mlxsw_sp_inetaddr_lag_event(dev, event, extack); else if (netif_is_bridge_master(dev)) - return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, event, + return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, -1, event, extack); else if (is_vlan_dev(dev)) return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp, dev, event, -- cgit From a5b52692e69338e4fc6abe0609679db3bade0d22 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 13 Jul 2023 18:15:29 +0200 Subject: mlxsw: spectrum_switchdev: Manage RIFs on PVID change Currently, mlxsw has several shortcomings with regards to RIF handling due to PVID changes: - In order to cause RIF for a bridge device to be created, the user is expected first to set PVID, then to add an IP address. The reverse ordering is disallowed, which is not very user-friendly. - When such bridge gets a VLAN upper whose VID was the same as the existing PVID, and this VLAN netdevice gets an IP address, a RIF is created for this netdevice. The new RIF is then assigned to the 802.1Q FID for the given VID. This results in a working configuration. However, then, when the VLAN netdevice is removed again, the RIF for the bridge itself is never reassociated to the VLAN. - PVID cannot be changed once the bridge has uppers. Presumably this is because the driver does not manage RIFs properly in face of PVID changes. However, as the previous point shows, it is still possible to get into invalid configurations. In this patch, add the logic necessary for creation of a RIF as a result of PVID change. Moreover, when a VLAN upper is created whose VID matches lower PVID, do not create RIF for this netdevice. These changes obviate the need for ordering of IP address additions and PVID configuration, so stop forbidding addition of an IP address to a PVID-less bridge. Instead, bail out quietly. Also stop preventing PVID changes when the bridge has uppers. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 119 ++++++++++++++++++++- .../net/ethernet/mellanox/mlxsw/spectrum_router.h | 4 + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 34 ++---- 3 files changed, 128 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 63f40d16be3b..109ac2db0d65 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8411,6 +8411,110 @@ out: mutex_unlock(&mlxsw_sp->router->lock); } +static void mlxsw_sp_rif_destroy_vlan_upper(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev, + u16 vid) +{ + struct net_device *upper_dev; + struct mlxsw_sp_crif *crif; + + rcu_read_lock(); + upper_dev = __vlan_find_dev_deep_rcu(br_dev, htons(ETH_P_8021Q), vid); + rcu_read_unlock(); + + if (!upper_dev) + return; + + crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, upper_dev); + if (!crif || !crif->rif) + return; + + mlxsw_sp_rif_destroy(crif->rif); +} + +static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, + struct net_device *l3_dev, + int lower_pvid, + unsigned long event, + struct netlink_ext_ack *extack); + +int mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev, + u16 new_vid, bool is_pvid, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_rif *old_rif; + struct mlxsw_sp_rif *new_rif; + struct net_device *upper_dev; + u16 old_pvid = 0; + u16 new_pvid; + int err = 0; + + mutex_lock(&mlxsw_sp->router->lock); + old_rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev); + if (old_rif) { + /* If the RIF on the bridge is not a VLAN RIF, we shouldn't have + * gotten a PVID notification. + */ + if (WARN_ON(old_rif->ops->type != MLXSW_SP_RIF_TYPE_VLAN)) + old_rif = NULL; + else + old_pvid = mlxsw_sp_fid_8021q_vid(old_rif->fid); + } + + if (is_pvid) + new_pvid = new_vid; + else if (old_pvid == new_vid) + new_pvid = 0; + else + goto out; + + if (old_pvid == new_pvid) + goto out; + + if (new_pvid) { + struct mlxsw_sp_rif_params params = { + .dev = br_dev, + .vid = new_pvid, + }; + + /* If there is a VLAN upper with the same VID as the new PVID, + * kill its RIF, if there is one. + */ + mlxsw_sp_rif_destroy_vlan_upper(mlxsw_sp, br_dev, new_pvid); + + if (mlxsw_sp_dev_addr_list_empty(br_dev)) + goto out; + new_rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack); + if (IS_ERR(new_rif)) { + err = PTR_ERR(new_rif); + goto out; + } + + if (old_pvid) + mlxsw_sp_rif_migrate_destroy(mlxsw_sp, old_rif, new_rif, + true); + } else { + mlxsw_sp_rif_destroy(old_rif); + } + + if (old_pvid) { + rcu_read_lock(); + upper_dev = __vlan_find_dev_deep_rcu(br_dev, htons(ETH_P_8021Q), + old_pvid); + rcu_read_unlock(); + if (upper_dev) + err = mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, + upper_dev, + new_pvid, + NETDEV_UP, extack); + } + +out: + mutex_unlock(&mlxsw_sp->router->lock); + return err; +} + static void mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params, struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) @@ -8847,13 +8951,20 @@ static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, return -EOPNOTSUPP; } err = br_vlan_get_pvid(l3_dev, ¶ms.vid); - if (err < 0 || !params.vid) { - NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); - return -EINVAL; - } + if (err) + return err; + if (!params.vid) + return 0; } else if (is_vlan_dev(l3_dev)) { params.vid = vlan_dev_vlan_id(l3_dev); + + /* If the VID matches PVID of the bridge below, the + * bridge owns the RIF for this VLAN. Don't do anything. + */ + if ((int)params.vid == lower_pvid) + return 0; } + rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack); if (IS_ERR(rif)) return PTR_ERR(rif); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 9a2669a08480..74242220a0cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -171,6 +171,10 @@ int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); struct net_device * mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev); +int mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev, + u16 new_vid, bool is_pvid, + struct netlink_ext_ack *extack); int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index a3365f7437d6..79d45c6c6edf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1479,30 +1479,15 @@ err_port_vlan_set: } static int -mlxsw_sp_br_ban_rif_pvid_change(struct mlxsw_sp *mlxsw_sp, - const struct net_device *br_dev, - const struct switchdev_obj_port_vlan *vlan, - struct netlink_ext_ack *extack) +mlxsw_sp_br_rif_pvid_change(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { - u16 pvid; - - pvid = mlxsw_sp_rif_vid(mlxsw_sp, br_dev); - if (!pvid) - return 0; - - if (vlan->flags & BRIDGE_VLAN_INFO_PVID) { - if (vlan->vid != pvid) { - NL_SET_ERR_MSG_MOD(extack, "Can't change PVID, it's used by router interface"); - return -EBUSY; - } - } else { - if (vlan->vid == pvid) { - NL_SET_ERR_MSG_MOD(extack, "Can't remove PVID, it's used by router interface"); - return -EBUSY; - } - } + bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; - return 0; + return mlxsw_sp_router_bridge_vlan_add(mlxsw_sp, br_dev, vlan->vid, + flag_pvid, extack); } static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, @@ -1519,9 +1504,8 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, int err = 0; if (br_vlan_enabled(orig_dev)) - err = mlxsw_sp_br_ban_rif_pvid_change(mlxsw_sp, - orig_dev, vlan, - extack); + err = mlxsw_sp_br_rif_pvid_change(mlxsw_sp, orig_dev, + vlan, extack); if (!err) err = -EOPNOTSUPP; return err; -- cgit From 68af900072c157c0cdce0256968edd15067e1e5a Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 13 Jul 2023 17:54:37 +0200 Subject: gve: trivial spell fix Recive to Receive Spotted this trivial spell mistake while casually reading the google GVE driver code. Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/google/gve/gve_desc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/google/gve/gve_desc.h b/drivers/net/ethernet/google/gve/gve_desc.h index f4ae9e19b844..c2874cdcf40c 100644 --- a/drivers/net/ethernet/google/gve/gve_desc.h +++ b/drivers/net/ethernet/google/gve/gve_desc.h @@ -105,10 +105,10 @@ union gve_rx_data_slot { __be64 addr; }; -/* GVE Recive Packet Descriptor Seq No */ +/* GVE Receive Packet Descriptor Seq No */ #define GVE_SEQNO(x) (be16_to_cpu(x) & 0x7) -/* GVE Recive Packet Descriptor Flags */ +/* GVE Receive Packet Descriptor Flags */ #define GVE_RXFLG(x) cpu_to_be16(1 << (3 + (x))) #define GVE_RXF_FRAG GVE_RXFLG(3) /* IP Fragment */ #define GVE_RXF_IPV4 GVE_RXFLG(4) /* IPv4 */ -- cgit From df84f0ce569dbec8cb4895a9aafab53fc9306320 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 13 Jul 2023 16:57:54 +0200 Subject: i40e: Add helper for VF inited state check with timeout Move the check for VF inited state (with optional up-to 300ms timeout to separate helper i40e_check_vf_init_timeout() that will be used in the following commit. Tested-by: Ma Yuying Signed-off-by: Ivan Vecera Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 49 +++++++++++++++------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index be59ba3774e1..b203465357af 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -4304,6 +4304,38 @@ err_out: return ret; } +/** + * i40e_check_vf_init_timeout + * @vf: the virtual function + * + * Check that the VF's initialization was successfully done and if not + * wait up to 300ms for its finish. + * + * Returns true when VF is initialized, false on timeout + **/ +static bool i40e_check_vf_init_timeout(struct i40e_vf *vf) +{ + int i; + + /* When the VF is resetting wait until it is done. + * It can take up to 200 milliseconds, but wait for + * up to 300 milliseconds to be safe. + */ + for (i = 0; i < 15; i++) { + if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) + return true; + msleep(20); + } + + if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { + dev_err(&vf->pf->pdev->dev, + "VF %d still in reset. Try again.\n", vf->vf_id); + return false; + } + + return true; +} + /** * i40e_ndo_set_vf_mac * @netdev: network interface device structure @@ -4322,7 +4354,6 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) int ret = 0; struct hlist_node *h; int bkt; - u8 i; if (test_and_set_bit(__I40E_VIRTCHNL_OP_PENDING, pf->state)) { dev_warn(&pf->pdev->dev, "Unable to configure VFs, other operation is pending.\n"); @@ -4335,21 +4366,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) goto error_param; vf = &pf->vf[vf_id]; - - /* When the VF is resetting wait until it is done. - * It can take up to 200 milliseconds, - * but wait for up to 300 milliseconds to be safe. - * Acquire the VSI pointer only after the VF has been - * properly initialized. - */ - for (i = 0; i < 15; i++) { - if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) - break; - msleep(20); - } - if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { - dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n", - vf_id); + if (!i40e_check_vf_init_timeout(vf)) { ret = -EAGAIN; goto error_param; } -- cgit From efb6f4a35954de375a74daf9770fe6b634f6ca56 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 13 Jul 2023 16:57:55 +0200 Subject: i40e: Wait for pending VF reset in VF set callbacks Commit 028daf80117376 ("i40e: Fix attach VF to VM issue") fixed a race between i40e_ndo_set_vf_mac() and i40e_reset_vf() during an attachment of VF device to VM. This issue is not related to setting MAC address only but also VLAN assignment to particular VF because the newer libvirt sets configured MAC address as well as an optional VLAN. The same behavior is also for i40e's .ndo_set_vf_rate and .ndo_set_vf_spoofchk where the callbacks just check if the VF was initialized but not wait for the finish of pending reset. Reproducer: [root@host ~]# virsh attach-interface guest hostdev --managed 0000:02:02.0 --mac 52:54:00:b4:aa:bb error: Failed to attach interface error: Cannot set interface MAC/vlanid to 52:54:00:b4:aa:bb/0 for ifname enp2s0f0 vf 0: Resource temporarily unavailable Fix this issue by using i40e_check_vf_init_timeout() helper to check whether a reset of particular VF was finished in i40e's .ndo_set_vf_vlan, .ndo_set_vf_rate and .ndo_set_vf_spoofchk callbacks. Tested-by: Ma Yuying Signed-off-by: Ivan Vecera Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index b203465357af..398fb4854cbe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -4468,13 +4468,11 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, } vf = &pf->vf[vf_id]; - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { - dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n", - vf_id); + if (!i40e_check_vf_init_timeout(vf)) { ret = -EAGAIN; goto error_pvid; } + vsi = pf->vsi[vf->lan_vsi_idx]; if (le16_to_cpu(vsi->info.pvid) == vlanprio) /* duplicate request, so just return success */ @@ -4618,13 +4616,11 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, } vf = &pf->vf[vf_id]; - vsi = pf->vsi[vf->lan_vsi_idx]; - if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { - dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n", - vf_id); + if (!i40e_check_vf_init_timeout(vf)) { ret = -EAGAIN; goto error; } + vsi = pf->vsi[vf->lan_vsi_idx]; ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate); if (ret) @@ -4791,9 +4787,7 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable) } vf = &(pf->vf[vf_id]); - if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { - dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n", - vf_id); + if (!i40e_check_vf_init_timeout(vf)) { ret = -EAGAIN; goto out; } -- cgit From f08469d0f664ff7b22f91871fa77bc59f8f7cec8 Mon Sep 17 00:00:00 2001 From: Csókás Bence Date: Thu, 13 Jul 2023 11:09:33 +0000 Subject: net: fec: Refactor: rename `adapter` to `fep` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename local `struct fec_enet_private *adapter` to `fep` in `fec_ptp_gettime()` to match the rest of the driver Signed-off-by: Csókás Bence Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_ptp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index ab86bb8562ef..afc658d2c271 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -443,21 +443,21 @@ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) */ static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { - struct fec_enet_private *adapter = + struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); u64 ns; unsigned long flags; - mutex_lock(&adapter->ptp_clk_mutex); + mutex_lock(&fep->ptp_clk_mutex); /* Check the ptp clock */ - if (!adapter->ptp_clk_on) { - mutex_unlock(&adapter->ptp_clk_mutex); + if (!fep->ptp_clk_on) { + mutex_unlock(&fep->ptp_clk_mutex); return -EINVAL; } - spin_lock_irqsave(&adapter->tmreg_lock, flags); - ns = timecounter_read(&adapter->tc); - spin_unlock_irqrestore(&adapter->tmreg_lock, flags); - mutex_unlock(&adapter->ptp_clk_mutex); + spin_lock_irqsave(&fep->tmreg_lock, flags); + ns = timecounter_read(&fep->tc); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + mutex_unlock(&fep->ptp_clk_mutex); *ts = ns_to_timespec64(ns); -- cgit From 490cb412007de593e07c1d3e2b1ec4233886707c Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:18:58 -0700 Subject: net: bcmasp: Add support for ASP2.0 Ethernet controller Add support for the Broadcom ASP 2.0 Ethernet controller which is first introduced with 72165. This controller features two distinct Ethernet ports that can be independently operated. Reviewed-by: Simon Horman Signed-off-by: Florian Fainelli Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 11 + drivers/net/ethernet/broadcom/Makefile | 1 + drivers/net/ethernet/broadcom/asp2/Makefile | 2 + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 696 ++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp.h | 503 ++++++++ .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 40 + drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 1342 ++++++++++++++++++++ .../net/ethernet/broadcom/asp2/bcmasp_intf_defs.h | 196 +++ 8 files changed, 2791 insertions(+) create mode 100644 drivers/net/ethernet/broadcom/asp2/Makefile create mode 100644 drivers/net/ethernet/broadcom/asp2/bcmasp.c create mode 100644 drivers/net/ethernet/broadcom/asp2/bcmasp.h create mode 100644 drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c create mode 100644 drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c create mode 100644 drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 948586bf1b5b..d4166141145d 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -255,4 +255,15 @@ config BNXT_HWMON Say Y if you want to expose the thermal sensor data on NetXtreme-C/E devices, via the hwmon sysfs interface. +config BCMASP + tristate "Broadcom ASP 2.0 Ethernet support" + default ARCH_BRCMSTB + depends on OF + select MII + select PHYLIB + select MDIO_BCM_UNIMAC + help + This configuration enables the Broadcom ASP 2.0 Ethernet controller + driver which is present in Broadcom STB SoCs such as 72165. + endif # NET_VENDOR_BROADCOM diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile index 0ddfb5b5d53c..bac5cb6ad0cd 100644 --- a/drivers/net/ethernet/broadcom/Makefile +++ b/drivers/net/ethernet/broadcom/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_BGMAC_BCMA) += bgmac-bcma.o bgmac-bcma-mdio.o obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o obj-$(CONFIG_BNXT) += bnxt/ +obj-$(CONFIG_BCMASP) += asp2/ diff --git a/drivers/net/ethernet/broadcom/asp2/Makefile b/drivers/net/ethernet/broadcom/asp2/Makefile new file mode 100644 index 000000000000..e07550315f83 --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_BCMASP) += bcm-asp.o +bcm-asp-objs := bcmasp.o bcmasp_intf.o bcmasp_ethtool.o diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c new file mode 100644 index 000000000000..83494641b545 --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -0,0 +1,696 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Broadcom STB ASP 2.0 Driver + * + * Copyright (c) 2023 Broadcom + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcmasp.h" +#include "bcmasp_intf_defs.h" + +static void _intr2_mask_clear(struct bcmasp_priv *priv, u32 mask) +{ + intr2_core_wl(priv, mask, ASP_INTR2_MASK_CLEAR); + priv->irq_mask &= ~mask; +} + +static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask) +{ + intr2_core_wl(priv, mask, ASP_INTR2_MASK_SET); + priv->irq_mask |= mask; +} + +void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en) +{ + struct bcmasp_priv *priv = intf->parent; + + if (en) + _intr2_mask_clear(priv, ASP_INTR2_TX_DESC(intf->channel)); + else + _intr2_mask_set(priv, ASP_INTR2_TX_DESC(intf->channel)); +} +EXPORT_SYMBOL_GPL(bcmasp_enable_tx_irq); + +void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en) +{ + struct bcmasp_priv *priv = intf->parent; + + if (en) + _intr2_mask_clear(priv, ASP_INTR2_RX_ECH(intf->channel)); + else + _intr2_mask_set(priv, ASP_INTR2_RX_ECH(intf->channel)); +} +EXPORT_SYMBOL_GPL(bcmasp_enable_rx_irq); + +static void bcmasp_intr2_mask_set_all(struct bcmasp_priv *priv) +{ + _intr2_mask_set(priv, 0xffffffff); + priv->irq_mask = 0xffffffff; +} + +static void bcmasp_intr2_clear_all(struct bcmasp_priv *priv) +{ + intr2_core_wl(priv, 0xffffffff, ASP_INTR2_CLEAR); +} + +static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status) +{ + if (status & ASP_INTR2_RX_ECH(intf->channel)) { + if (likely(napi_schedule_prep(&intf->rx_napi))) { + bcmasp_enable_rx_irq(intf, 0); + __napi_schedule_irqoff(&intf->rx_napi); + } + } + + if (status & ASP_INTR2_TX_DESC(intf->channel)) { + if (likely(napi_schedule_prep(&intf->tx_napi))) { + bcmasp_enable_tx_irq(intf, 0); + __napi_schedule_irqoff(&intf->tx_napi); + } + } +} + +static irqreturn_t bcmasp_isr(int irq, void *data) +{ + struct bcmasp_priv *priv = data; + struct bcmasp_intf *intf; + u32 status; + + status = intr2_core_rl(priv, ASP_INTR2_STATUS) & + ~intr2_core_rl(priv, ASP_INTR2_MASK_STATUS); + + intr2_core_wl(priv, status, ASP_INTR2_CLEAR); + + if (unlikely(status == 0)) { + dev_warn(&priv->pdev->dev, "l2 spurious interrupt\n"); + return IRQ_NONE; + } + + /* Handle intferfaces */ + list_for_each_entry(intf, &priv->intfs, list) + bcmasp_intr2_handling(intf, status); + + return IRQ_HANDLED; +} + +void bcmasp_flush_rx_port(struct bcmasp_intf *intf) +{ + struct bcmasp_priv *priv = intf->parent; + u32 mask; + + switch (intf->port) { + case 0: + mask = ASP_CTRL_UMAC0_FLUSH_MASK; + break; + case 1: + mask = ASP_CTRL_UMAC1_FLUSH_MASK; + break; + case 2: + mask = ASP_CTRL_SPB_FLUSH_MASK; + break; + default: + /* Not valid port */ + return; + } + + rx_ctrl_core_wl(priv, mask, priv->hw_info->rx_ctrl_flush); +} + +static void bcmasp_addr_to_uint(unsigned char *addr, u32 *high, u32 *low) +{ + *high = (u32)(addr[0] << 8 | addr[1]); + *low = (u32)(addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | + addr[5]); +} + +static void bcmasp_set_mda_filter(struct bcmasp_intf *intf, + const unsigned char *addr, + unsigned char *mask, + unsigned int i) +{ + struct bcmasp_priv *priv = intf->parent; + u32 addr_h, addr_l, mask_h, mask_l; + + /* Set local copy */ + ether_addr_copy(priv->mda_filters[i].mask, mask); + ether_addr_copy(priv->mda_filters[i].addr, addr); + + /* Write to HW */ + bcmasp_addr_to_uint(priv->mda_filters[i].mask, &mask_h, &mask_l); + bcmasp_addr_to_uint(priv->mda_filters[i].addr, &addr_h, &addr_l); + rx_filter_core_wl(priv, addr_h, ASP_RX_FILTER_MDA_PAT_H(i)); + rx_filter_core_wl(priv, addr_l, ASP_RX_FILTER_MDA_PAT_L(i)); + rx_filter_core_wl(priv, mask_h, ASP_RX_FILTER_MDA_MSK_H(i)); + rx_filter_core_wl(priv, mask_l, ASP_RX_FILTER_MDA_MSK_L(i)); +} + +static void bcmasp_en_mda_filter(struct bcmasp_intf *intf, bool en, + unsigned int i) +{ + struct bcmasp_priv *priv = intf->parent; + + if (priv->mda_filters[i].en == en) + return; + + priv->mda_filters[i].en = en; + priv->mda_filters[i].port = intf->port; + + rx_filter_core_wl(priv, ((intf->channel + 8) | + (en << ASP_RX_FILTER_MDA_CFG_EN_SHIFT) | + ASP_RX_FILTER_MDA_CFG_UMC_SEL(intf->port)), + ASP_RX_FILTER_MDA_CFG(i)); +} + +/* There are 32 MDA filters shared between all ports, we reserve 4 filters per + * port for the following. + * - Promisc: Filter to allow all packets when promisc is enabled + * - All Multicast + * - Broadcast + * - Own address + * + * The reserved filters are identified as so. + * - Promisc: (index * 4) + 0 + * - All Multicast: (index * 4) + 1 + * - Broadcast: (index * 4) + 2 + * - Own address: (index * 4) + 3 + */ +enum asp_rx_filter_id { + ASP_RX_FILTER_MDA_PROMISC = 0, + ASP_RX_FILTER_MDA_ALLMULTI, + ASP_RX_FILTER_MDA_BROADCAST, + ASP_RX_FILTER_MDA_OWN_ADDR, + ASP_RX_FILTER_MDA_RES_MAX, +}; + +#define ASP_RX_FILT_MDA(intf, name) (((intf)->index * \ + ASP_RX_FILTER_MDA_RES_MAX) \ + + ASP_RX_FILTER_MDA_##name) + +static int bcmasp_total_res_mda_cnt(struct bcmasp_priv *priv) +{ + return list_count_nodes(&priv->intfs) * ASP_RX_FILTER_MDA_RES_MAX; +} + +void bcmasp_set_promisc(struct bcmasp_intf *intf, bool en) +{ + unsigned int i = ASP_RX_FILT_MDA(intf, PROMISC); + unsigned char promisc[ETH_ALEN]; + + eth_zero_addr(promisc); + /* Set mask to 00:00:00:00:00:00 to match all packets */ + bcmasp_set_mda_filter(intf, promisc, promisc, i); + bcmasp_en_mda_filter(intf, en, i); +} + +void bcmasp_set_allmulti(struct bcmasp_intf *intf, bool en) +{ + unsigned char allmulti[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned int i = ASP_RX_FILT_MDA(intf, ALLMULTI); + + /* Set mask to 01:00:00:00:00:00 to match all multicast */ + bcmasp_set_mda_filter(intf, allmulti, allmulti, i); + bcmasp_en_mda_filter(intf, en, i); +} + +void bcmasp_set_broad(struct bcmasp_intf *intf, bool en) +{ + unsigned int i = ASP_RX_FILT_MDA(intf, BROADCAST); + unsigned char addr[ETH_ALEN]; + + eth_broadcast_addr(addr); + bcmasp_set_mda_filter(intf, addr, addr, i); + bcmasp_en_mda_filter(intf, en, i); +} + +void bcmasp_set_oaddr(struct bcmasp_intf *intf, const unsigned char *addr, + bool en) +{ + unsigned char mask[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + unsigned int i = ASP_RX_FILT_MDA(intf, OWN_ADDR); + + bcmasp_set_mda_filter(intf, addr, mask, i); + bcmasp_en_mda_filter(intf, en, i); +} + +void bcmasp_disable_all_filters(struct bcmasp_intf *intf) +{ + struct bcmasp_priv *priv = intf->parent; + unsigned int i; + int res_count; + + res_count = bcmasp_total_res_mda_cnt(intf->parent); + + /* Disable all filters held by this port */ + for (i = res_count; i < NUM_MDA_FILTERS; i++) { + if (priv->mda_filters[i].en && + priv->mda_filters[i].port == intf->port) + bcmasp_en_mda_filter(intf, 0, i); + } +} + +static int bcmasp_combine_set_filter(struct bcmasp_intf *intf, + unsigned char *addr, unsigned char *mask, + int i) +{ + struct bcmasp_priv *priv = intf->parent; + u64 addr1, addr2, mask1, mask2, mask3; + + /* Switch to u64 to help with the calculations */ + addr1 = ether_addr_to_u64(priv->mda_filters[i].addr); + mask1 = ether_addr_to_u64(priv->mda_filters[i].mask); + addr2 = ether_addr_to_u64(addr); + mask2 = ether_addr_to_u64(mask); + + /* Check if one filter resides within the other */ + mask3 = mask1 & mask2; + if (mask3 == mask1 && ((addr1 & mask1) == (addr2 & mask1))) { + /* Filter 2 resides within filter 1, so everything is good */ + return 0; + } else if (mask3 == mask2 && ((addr1 & mask2) == (addr2 & mask2))) { + /* Filter 1 resides within filter 2, so swap filters */ + bcmasp_set_mda_filter(intf, addr, mask, i); + return 0; + } + + /* Unable to combine */ + return -EINVAL; +} + +int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr, + unsigned char *mask) +{ + struct bcmasp_priv *priv = intf->parent; + int ret, res_count; + unsigned int i; + + res_count = bcmasp_total_res_mda_cnt(intf->parent); + + for (i = res_count; i < NUM_MDA_FILTERS; i++) { + /* If filter not enabled or belongs to another port skip */ + if (!priv->mda_filters[i].en || + priv->mda_filters[i].port != intf->port) + continue; + + /* Attempt to combine filters */ + ret = bcmasp_combine_set_filter(intf, addr, mask, i); + if (!ret) + return 0; + } + + /* Create new filter if possible */ + for (i = res_count; i < NUM_MDA_FILTERS; i++) { + if (priv->mda_filters[i].en) + continue; + + bcmasp_set_mda_filter(intf, addr, mask, i); + bcmasp_en_mda_filter(intf, 1, i); + return 0; + } + + /* No room for new filter */ + return -EINVAL; +} + +static void bcmasp_core_init_filters(struct bcmasp_priv *priv) +{ + unsigned int i; + + /* Disable all filters and reset software view since the HW + * can lose context while in deep sleep suspend states + */ + for (i = 0; i < NUM_MDA_FILTERS; i++) { + rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_MDA_CFG(i)); + priv->mda_filters[i].en = 0; + } + + /* Top level filter enable bit should be enabled at all times, set + * GEN_WAKE_CLEAR to clear the network filter wake-up which would + * otherwise be sticky + */ + rx_filter_core_wl(priv, (ASP_RX_FILTER_OPUT_EN | + ASP_RX_FILTER_MDA_EN | + ASP_RX_FILTER_GEN_WK_CLR | + ASP_RX_FILTER_NT_FLT_EN), + ASP_RX_FILTER_BLK_CTRL); +} + +/* ASP core initialization */ +static void bcmasp_core_init(struct bcmasp_priv *priv) +{ + tx_analytics_core_wl(priv, 0x0, ASP_TX_ANALYTICS_CTRL); + rx_analytics_core_wl(priv, 0x4, ASP_RX_ANALYTICS_CTRL); + + rx_edpkt_core_wl(priv, (ASP_EDPKT_HDR_SZ_128 << ASP_EDPKT_HDR_SZ_SHIFT), + ASP_EDPKT_HDR_CFG); + rx_edpkt_core_wl(priv, + (ASP_EDPKT_ENDI_BT_SWP_WD << ASP_EDPKT_ENDI_DESC_SHIFT), + ASP_EDPKT_ENDI); + + rx_edpkt_core_wl(priv, 0x1b, ASP_EDPKT_BURST_BUF_PSCAL_TOUT); + rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_WRITE_TOUT); + rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_READ_TOUT); + + rx_edpkt_core_wl(priv, ASP_EDPKT_ENABLE_EN, ASP_EDPKT_ENABLE); + + /* Disable and clear both UniMAC's wake-up interrupts to avoid + * sticky interrupts. + */ + _intr2_mask_set(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE); + intr2_core_wl(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE, + ASP_INTR2_CLEAR); +} + +static void bcmasp_core_clock_select(struct bcmasp_priv *priv, bool slow) +{ + u32 reg; + + reg = ctrl_core_rl(priv, ASP_CTRL_CORE_CLOCK_SELECT); + if (slow) + reg &= ~ASP_CTRL_CORE_CLOCK_SELECT_MAIN; + else + reg |= ASP_CTRL_CORE_CLOCK_SELECT_MAIN; + ctrl_core_wl(priv, reg, ASP_CTRL_CORE_CLOCK_SELECT); +} + +static void bcmasp_core_clock_set_ll(struct bcmasp_priv *priv, u32 clr, u32 set) +{ + u32 reg; + + reg = ctrl_core_rl(priv, ASP_CTRL_CLOCK_CTRL); + reg &= ~clr; + reg |= set; + ctrl_core_wl(priv, reg, ASP_CTRL_CLOCK_CTRL); + + reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0); + reg &= ~clr; + reg |= set; + ctrl_core_wl(priv, reg, ASP_CTRL_SCRATCH_0); +} + +static void bcmasp_core_clock_set(struct bcmasp_priv *priv, u32 clr, u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->clk_lock, flags); + bcmasp_core_clock_set_ll(priv, clr, set); + spin_unlock_irqrestore(&priv->clk_lock, flags); +} + +void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en) +{ + u32 intf_mask = ASP_CTRL_CLOCK_CTRL_ASP_RGMII_DIS(intf->port); + struct bcmasp_priv *priv = intf->parent; + unsigned long flags; + u32 reg; + + /* When enabling an interface, if the RX or TX clocks were not enabled, + * enable them. Conversely, while disabling an interface, if this is + * the last one enabled, we can turn off the shared RX and TX clocks as + * well. We control enable bits which is why we test for equality on + * the RGMII clock bit mask. + */ + spin_lock_irqsave(&priv->clk_lock, flags); + if (en) { + intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE | + ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE; + bcmasp_core_clock_set_ll(priv, intf_mask, 0); + } else { + reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0) | intf_mask; + if ((reg & ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK) == + ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK) + intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE | + ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE; + bcmasp_core_clock_set_ll(priv, 0, intf_mask); + } + spin_unlock_irqrestore(&priv->clk_lock, flags); +} + +static struct bcmasp_hw_info v20_hw_info = { + .rx_ctrl_flush = ASP_RX_CTRL_FLUSH, + .umac2fb = UMAC2FB_OFFSET, + .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT, + .rx_ctrl_fb_filt_out_frame_count = ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT, + .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH, +}; + +static const struct bcmasp_plat_data v20_plat_data = { + .hw_info = &v20_hw_info, +}; + +static struct bcmasp_hw_info v21_hw_info = { + .rx_ctrl_flush = ASP_RX_CTRL_FLUSH_2_1, + .umac2fb = UMAC2FB_OFFSET_2_1, + .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1, + .rx_ctrl_fb_filt_out_frame_count = + ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1, + .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1, +}; + +static const struct bcmasp_plat_data v21_plat_data = { + .hw_info = &v21_hw_info, +}; + +static const struct of_device_id bcmasp_of_match[] = { + { .compatible = "brcm,asp-v2.0", .data = &v20_plat_data }, + { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, bcmasp_of_match); + +static const struct of_device_id bcmasp_mdio_of_match[] = { + { .compatible = "brcm,asp-v2.1-mdio", }, + { .compatible = "brcm,asp-v2.0-mdio", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, bcmasp_mdio_of_match); + +static void bcmasp_remove_intfs(struct bcmasp_priv *priv) +{ + struct bcmasp_intf *intf, *n; + + list_for_each_entry_safe(intf, n, &priv->intfs, list) { + list_del(&intf->list); + bcmasp_interface_destroy(intf); + } +} + +static int bcmasp_probe(struct platform_device *pdev) +{ + struct device_node *ports_node, *intf_node; + const struct bcmasp_plat_data *pdata; + struct device *dev = &pdev->dev; + struct bcmasp_priv *priv; + struct bcmasp_intf *intf; + int ret = 0, count = 0; + unsigned int i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq <= 0) + return dev_err_probe(dev, -EINVAL, "invalid interrupt\n"); + + priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp"); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to request clock\n"); + + /* Base from parent node */ + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return dev_err_probe(dev, PTR_ERR(priv->base), "failed to iomap\n"); + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + if (ret) + return dev_err_probe(dev, ret, "unable to set DMA mask: %d\n", ret); + + dev_set_drvdata(&pdev->dev, priv); + priv->pdev = pdev; + spin_lock_init(&priv->mda_lock); + spin_lock_init(&priv->clk_lock); + INIT_LIST_HEAD(&priv->intfs); + + pdata = device_get_match_data(&pdev->dev); + if (!pdata) + return dev_err_probe(dev, -EINVAL, "unable to find platform data\n"); + + priv->hw_info = pdata->hw_info; + + /* Enable all clocks to ensure successful probing */ + bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); + + /* Switch to the main clock */ + bcmasp_core_clock_select(priv, false); + + bcmasp_intr2_mask_set_all(priv); + bcmasp_intr2_clear_all(priv); + + ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0, + pdev->name, priv); + if (ret) + return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret); + + /* Register mdio child nodes */ + of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev); + + /* ASP specific initialization, Needs to be done regardless of + * how many interfaces come up. + */ + bcmasp_core_init(priv); + bcmasp_core_init_filters(priv); + + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); + return -EINVAL; + } + + i = 0; + for_each_available_child_of_node(ports_node, intf_node) { + intf = bcmasp_interface_create(priv, intf_node, i); + if (!intf) { + dev_err(dev, "Cannot create eth interface %d\n", i); + bcmasp_remove_intfs(priv); + goto of_put_exit; + } + list_add_tail(&intf->list, &priv->intfs); + i++; + } + + /* Drop the clock reference count now and let ndo_open()/ndo_close() + * manage it for us from now on. + */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE); + + clk_disable_unprepare(priv->clk); + + /* Now do the registration of the network ports which will take care + * of managing the clock properly. + */ + list_for_each_entry(intf, &priv->intfs, list) { + ret = register_netdev(intf->ndev); + if (ret) { + netdev_err(intf->ndev, + "failed to register net_device: %d\n", ret); + bcmasp_remove_intfs(priv); + goto of_put_exit; + } + count++; + } + + dev_info(dev, "Initialized %d port(s)\n", count); + +of_put_exit: + of_node_put(ports_node); + return ret; +} + +static int bcmasp_remove(struct platform_device *pdev) +{ + struct bcmasp_priv *priv = dev_get_drvdata(&pdev->dev); + + if (!priv) + return 0; + + bcmasp_remove_intfs(priv); + + return 0; +} + +static void bcmasp_shutdown(struct platform_device *pdev) +{ + bcmasp_remove(pdev); +} + +static int __maybe_unused bcmasp_suspend(struct device *d) +{ + struct bcmasp_priv *priv = dev_get_drvdata(d); + struct bcmasp_intf *intf; + int ret; + + list_for_each_entry(intf, &priv->intfs, list) { + ret = bcmasp_interface_suspend(intf); + if (ret) + break; + } + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + /* Whether Wake-on-LAN is enabled or not, we can always disable + * the shared TX clock + */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE); + + bcmasp_core_clock_select(priv, true); + + clk_disable_unprepare(priv->clk); + + return ret; +} + +static int __maybe_unused bcmasp_resume(struct device *d) +{ + struct bcmasp_priv *priv = dev_get_drvdata(d); + struct bcmasp_intf *intf; + int ret; + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + /* Switch to the main clock domain */ + bcmasp_core_clock_select(priv, false); + + /* Re-enable all clocks for re-initialization */ + bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); + + bcmasp_core_init(priv); + bcmasp_core_init_filters(priv); + + /* And disable them to let the network devices take care of them */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE); + + clk_disable_unprepare(priv->clk); + + list_for_each_entry(intf, &priv->intfs, list) { + ret = bcmasp_interface_resume(intf); + if (ret) + break; + } + + return ret; +} + +static SIMPLE_DEV_PM_OPS(bcmasp_pm_ops, + bcmasp_suspend, bcmasp_resume); + +static struct platform_driver bcmasp_driver = { + .probe = bcmasp_probe, + .remove = bcmasp_remove, + .shutdown = bcmasp_shutdown, + .driver = { + .name = "brcm,asp-v2", + .of_match_table = bcmasp_of_match, + .pm = &bcmasp_pm_ops, + }, +}; +module_platform_driver(bcmasp_driver); + +MODULE_DESCRIPTION("Broadcom ASP 2.0 Ethernet controller driver"); +MODULE_ALIAS("platform:brcm,asp-v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h new file mode 100644 index 000000000000..4fe84d26251d --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -0,0 +1,503 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __BCMASP_H +#define __BCMASP_H + +#include +#include +#include +#include + +#define ASP_INTR2_OFFSET 0x1000 +#define ASP_INTR2_STATUS 0x0 +#define ASP_INTR2_SET 0x4 +#define ASP_INTR2_CLEAR 0x8 +#define ASP_INTR2_MASK_STATUS 0xc +#define ASP_INTR2_MASK_SET 0x10 +#define ASP_INTR2_MASK_CLEAR 0x14 + +#define ASP_INTR2_RX_ECH(intr) BIT(intr) +#define ASP_INTR2_TX_DESC(intr) BIT((intr) + 14) +#define ASP_INTR2_UMC0_WAKE BIT(22) +#define ASP_INTR2_UMC1_WAKE BIT(28) + +#define ASP_WAKEUP_INTR2_OFFSET 0x1200 +#define ASP_WAKEUP_INTR2_STATUS 0x0 +#define ASP_WAKEUP_INTR2_SET 0x4 +#define ASP_WAKEUP_INTR2_CLEAR 0x8 +#define ASP_WAKEUP_INTR2_MASK_STATUS 0xc +#define ASP_WAKEUP_INTR2_MASK_SET 0x10 +#define ASP_WAKEUP_INTR2_MASK_CLEAR 0x14 +#define ASP_WAKEUP_INTR2_MPD_0 BIT(0) +#define ASP_WAKEUP_INTR2_MPD_1 BIT(1) +#define ASP_WAKEUP_INTR2_FILT_0 BIT(2) +#define ASP_WAKEUP_INTR2_FILT_1 BIT(3) +#define ASP_WAKEUP_INTR2_FW BIT(4) + +#define ASP_TX_ANALYTICS_OFFSET 0x4c000 +#define ASP_TX_ANALYTICS_CTRL 0x0 + +#define ASP_RX_ANALYTICS_OFFSET 0x98000 +#define ASP_RX_ANALYTICS_CTRL 0x0 + +#define ASP_RX_CTRL_OFFSET 0x9f000 +#define ASP_RX_CTRL_UMAC_0_FRAME_COUNT 0x8 +#define ASP_RX_CTRL_UMAC_1_FRAME_COUNT 0xc +#define ASP_RX_CTRL_FB_0_FRAME_COUNT 0x14 +#define ASP_RX_CTRL_FB_1_FRAME_COUNT 0x18 +#define ASP_RX_CTRL_FB_8_FRAME_COUNT 0x1c +/* asp2.1 diverges offsets here */ +/* ASP2.0 */ +#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT 0x20 +#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT 0x24 +#define ASP_RX_CTRL_FLUSH 0x28 +#define ASP_CTRL_UMAC0_FLUSH_MASK (BIT(0) | BIT(12)) +#define ASP_CTRL_UMAC1_FLUSH_MASK (BIT(1) | BIT(13)) +#define ASP_CTRL_SPB_FLUSH_MASK (BIT(8) | BIT(20)) +#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH 0x30 +/* ASP2.1 */ +#define ASP_RX_CTRL_FB_9_FRAME_COUNT_2_1 0x20 +#define ASP_RX_CTRL_FB_10_FRAME_COUNT_2_1 0x24 +#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1 0x28 +#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1 0x2c +#define ASP_RX_CTRL_FLUSH_2_1 0x30 +#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1 0x38 + +#define ASP_RX_FILTER_OFFSET 0x80000 +#define ASP_RX_FILTER_BLK_CTRL 0x0 +#define ASP_RX_FILTER_OPUT_EN BIT(0) +#define ASP_RX_FILTER_MDA_EN BIT(1) +#define ASP_RX_FILTER_LNR_MD BIT(2) +#define ASP_RX_FILTER_GEN_WK_EN BIT(3) +#define ASP_RX_FILTER_GEN_WK_CLR BIT(4) +#define ASP_RX_FILTER_NT_FLT_EN BIT(5) +#define ASP_RX_FILTER_MDA_CFG(sel) (((sel) * 0x14) + 0x100) +#define ASP_RX_FILTER_MDA_CFG_EN_SHIFT 8 +#define ASP_RX_FILTER_MDA_CFG_UMC_SEL(sel) ((sel) > 1 ? BIT(17) : \ + BIT((sel) + 9)) +#define ASP_RX_FILTER_MDA_PAT_H(sel) (((sel) * 0x14) + 0x104) +#define ASP_RX_FILTER_MDA_PAT_L(sel) (((sel) * 0x14) + 0x108) +#define ASP_RX_FILTER_MDA_MSK_H(sel) (((sel) * 0x14) + 0x10c) +#define ASP_RX_FILTER_MDA_MSK_L(sel) (((sel) * 0x14) + 0x110) +#define ASP_RX_FILTER_MDA_CFG(sel) (((sel) * 0x14) + 0x100) +#define ASP_RX_FILTER_MDA_PAT_H(sel) (((sel) * 0x14) + 0x104) +#define ASP_RX_FILTER_MDA_PAT_L(sel) (((sel) * 0x14) + 0x108) +#define ASP_RX_FILTER_MDA_MSK_H(sel) (((sel) * 0x14) + 0x10c) +#define ASP_RX_FILTER_MDA_MSK_L(sel) (((sel) * 0x14) + 0x110) +#define ASP_RX_FILTER_NET_CFG(sel) (((sel) * 0xa04) + 0x400) +#define ASP_RX_FILTER_NET_CFG_CH(sel) ((sel) << 0) +#define ASP_RX_FILTER_NET_CFG_EN BIT(9) +#define ASP_RX_FILTER_NET_CFG_L2_EN BIT(10) +#define ASP_RX_FILTER_NET_CFG_L3_EN BIT(11) +#define ASP_RX_FILTER_NET_CFG_L4_EN BIT(12) +#define ASP_RX_FILTER_NET_CFG_L3_FRM(sel) ((sel) << 13) +#define ASP_RX_FILTER_NET_CFG_L4_FRM(sel) ((sel) << 15) +#define ASP_RX_FILTER_NET_CFG_UMC(sel) BIT((sel) + 19) +#define ASP_RX_FILTER_NET_CFG_DMA_EN BIT(27) + +#define ASP_RX_FILTER_NET_OFFSET_MAX 32 +#define ASP_RX_FILTER_NET_PAT(sel, block, off) \ + (((sel) * 0xa04) + ((block) * 0x200) + (off) + 0x600) +#define ASP_RX_FILTER_NET_MASK(sel, block, off) \ + (((sel) * 0xa04) + ((block) * 0x200) + (off) + 0x700) + +#define ASP_RX_FILTER_NET_OFFSET(sel) (((sel) * 0xa04) + 0xe00) +#define ASP_RX_FILTER_NET_OFFSET_L2(val) ((val) << 0) +#define ASP_RX_FILTER_NET_OFFSET_L3_0(val) ((val) << 8) +#define ASP_RX_FILTER_NET_OFFSET_L3_1(val) ((val) << 16) +#define ASP_RX_FILTER_NET_OFFSET_L4(val) ((val) << 24) + +#define ASP_EDPKT_OFFSET 0x9c000 +#define ASP_EDPKT_ENABLE 0x4 +#define ASP_EDPKT_ENABLE_EN BIT(0) +#define ASP_EDPKT_HDR_CFG 0xc +#define ASP_EDPKT_HDR_SZ_SHIFT 2 +#define ASP_EDPKT_HDR_SZ_32 0 +#define ASP_EDPKT_HDR_SZ_64 1 +#define ASP_EDPKT_HDR_SZ_96 2 +#define ASP_EDPKT_HDR_SZ_128 3 +#define ASP_EDPKT_BURST_BUF_PSCAL_TOUT 0x10 +#define ASP_EDPKT_BURST_BUF_WRITE_TOUT 0x14 +#define ASP_EDPKT_BURST_BUF_READ_TOUT 0x18 +#define ASP_EDPKT_RX_TS_COUNTER 0x38 +#define ASP_EDPKT_ENDI 0x48 +#define ASP_EDPKT_ENDI_DESC_SHIFT 8 +#define ASP_EDPKT_ENDI_NO_BT_SWP 0 +#define ASP_EDPKT_ENDI_BT_SWP_WD 1 +#define ASP_EDPKT_RX_PKT_CNT 0x138 +#define ASP_EDPKT_HDR_EXTR_CNT 0x13c +#define ASP_EDPKT_HDR_OUT_CNT 0x140 + +#define ASP_CTRL 0x101000 +#define ASP_CTRL_ASP_SW_INIT 0x04 +#define ASP_CTRL_ASP_SW_INIT_ACPUSS_CORE BIT(0) +#define ASP_CTRL_ASP_SW_INIT_ASP_TX BIT(1) +#define ASP_CTRL_ASP_SW_INIT_AS_RX BIT(2) +#define ASP_CTRL_ASP_SW_INIT_ASP_RGMII_UMAC0 BIT(3) +#define ASP_CTRL_ASP_SW_INIT_ASP_RGMII_UMAC1 BIT(4) +#define ASP_CTRL_ASP_SW_INIT_ASP_XMEMIF BIT(5) +#define ASP_CTRL_CLOCK_CTRL 0x04 +#define ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE BIT(0) +#define ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE BIT(1) +#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT 2 +#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK (0x7 << ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT) +#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_DIS(x) BIT(ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT + (x)) +#define ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE GENMASK(4, 0) +#define ASP_CTRL_CORE_CLOCK_SELECT 0x08 +#define ASP_CTRL_CORE_CLOCK_SELECT_MAIN BIT(0) +#define ASP_CTRL_SCRATCH_0 0x0c + +struct bcmasp_tx_cb { + struct sk_buff *skb; + unsigned int bytes_sent; + bool last; + + DEFINE_DMA_UNMAP_ADDR(dma_addr); + DEFINE_DMA_UNMAP_LEN(dma_len); +}; + +struct bcmasp_res { + /* Per interface resources */ + /* Port */ + void __iomem *umac; + void __iomem *umac2fb; + void __iomem *rgmii; + + /* TX slowpath/configuration */ + void __iomem *tx_spb_ctrl; + void __iomem *tx_spb_top; + void __iomem *tx_epkt_core; + void __iomem *tx_pause_ctrl; +}; + +#define DESC_ADDR(x) ((x) & GENMASK_ULL(39, 0)) +#define DESC_FLAGS(x) ((x) & GENMASK_ULL(63, 40)) + +struct bcmasp_desc { + u64 buf; + #define DESC_CHKSUM BIT_ULL(40) + #define DESC_CRC_ERR BIT_ULL(41) + #define DESC_RX_SYM_ERR BIT_ULL(42) + #define DESC_NO_OCT_ALN BIT_ULL(43) + #define DESC_PKT_TRUC BIT_ULL(44) + /* 39:0 (TX/RX) bits 0-39 of buf addr + * 40 (RX) checksum + * 41 (RX) crc_error + * 42 (RX) rx_symbol_error + * 43 (RX) non_octet_aligned + * 44 (RX) pkt_truncated + * 45 Reserved + * 56:46 (RX) mac_filter_id + * 60:57 (RX) rx_port_num (0-unicmac0, 1-unimac1) + * 61 Reserved + * 63:62 (TX) forward CRC, overwrite CRC + */ + u32 size; + u32 flags; + #define DESC_INT_EN BIT(0) + #define DESC_SOF BIT(1) + #define DESC_EOF BIT(2) + #define DESC_EPKT_CMD BIT(3) + #define DESC_SCRAM_ST BIT(8) + #define DESC_SCRAM_END BIT(9) + #define DESC_PCPP BIT(10) + #define DESC_PPPP BIT(11) + /* 0 (TX) tx_int_en + * 1 (TX/RX) SOF + * 2 (TX/RX) EOF + * 3 (TX) epkt_command + * 6:4 (TX) PA + * 7 (TX) pause at desc end + * 8 (TX) scram_start + * 9 (TX) scram_end + * 10 (TX) PCPP + * 11 (TX) PPPP + * 14:12 Reserved + * 15 (TX) pid ch Valid + * 19:16 (TX) data_pkt_type + * 32:20 (TX) pid_channel (RX) nw_filter_id + */ +}; + +struct bcmasp_intf; + +struct bcmasp_intf_stats64 { + /* Rx Stats */ + u64_stats_t rx_packets; + u64_stats_t rx_bytes; + u64_stats_t rx_errors; + u64_stats_t rx_dropped; + u64_stats_t rx_crc_errs; + u64_stats_t rx_sym_errs; + + /* Tx Stats*/ + u64_stats_t tx_packets; + u64_stats_t tx_bytes; + + struct u64_stats_sync syncp; +}; + +struct bcmasp_intf_ops { + unsigned long (*rx_desc_read)(struct bcmasp_intf *intf); + void (*rx_buffer_write)(struct bcmasp_intf *intf, dma_addr_t addr); + void (*rx_desc_write)(struct bcmasp_intf *intf, dma_addr_t addr); + unsigned long (*tx_read)(struct bcmasp_intf *intf); + void (*tx_write)(struct bcmasp_intf *intf, dma_addr_t addr); +}; + +struct bcmasp_priv; + +struct bcmasp_intf { + struct list_head list; + struct net_device *ndev; + struct bcmasp_priv *parent; + + /* ASP Ch */ + int channel; + int port; + const struct bcmasp_intf_ops *ops; + + /* Used for splitting shared resources */ + int index; + + struct napi_struct tx_napi; + /* TX ring, starts on a new cacheline boundary */ + void __iomem *tx_spb_dma; + int tx_spb_index; + int tx_spb_clean_index; + struct bcmasp_desc *tx_spb_cpu; + dma_addr_t tx_spb_dma_addr; + dma_addr_t tx_spb_dma_valid; + dma_addr_t tx_spb_dma_read; + struct bcmasp_tx_cb *tx_cbs; + + /* RX ring, starts on a new cacheline boundary */ + void __iomem *rx_edpkt_cfg; + void __iomem *rx_edpkt_dma; + int rx_edpkt_index; + int rx_buf_order; + struct bcmasp_desc *rx_edpkt_cpu; + dma_addr_t rx_edpkt_dma_addr; + dma_addr_t rx_edpkt_dma_read; + + /* RX buffer prefetcher ring*/ + void *rx_ring_cpu; + dma_addr_t rx_ring_dma; + dma_addr_t rx_ring_dma_valid; + struct napi_struct rx_napi; + + struct bcmasp_res res; + unsigned int crc_fwd; + + /* PHY device */ + struct device_node *phy_dn; + struct device_node *ndev_dn; + phy_interface_t phy_interface; + bool internal_phy; + int old_pause; + int old_link; + int old_duplex; + + u32 msg_enable; + + /* Statistics */ + struct bcmasp_intf_stats64 stats64; +}; + +#define NUM_MDA_FILTERS 32 +struct bcmasp_mda_filter { + /* Current owner of this filter */ + int port; + bool en; + u8 addr[ETH_ALEN]; + u8 mask[ETH_ALEN]; +}; + +struct bcmasp_hw_info { + u32 rx_ctrl_flush; + u32 umac2fb; + u32 rx_ctrl_fb_out_frame_count; + u32 rx_ctrl_fb_filt_out_frame_count; + u32 rx_ctrl_fb_rx_fifo_depth; +}; + +struct bcmasp_plat_data { + struct bcmasp_hw_info *hw_info; +}; + +struct bcmasp_priv { + struct platform_device *pdev; + struct clk *clk; + + int irq; + u32 irq_mask; + + void __iomem *base; + struct bcmasp_hw_info *hw_info; + + struct list_head intfs; + + struct bcmasp_mda_filter mda_filters[NUM_MDA_FILTERS]; + + /* MAC destination address filters lock */ + spinlock_t mda_lock; + + /* Protects accesses to ASP_CTRL_CLOCK_CTRL */ + spinlock_t clk_lock; +}; + +static inline unsigned long bcmasp_intf_rx_desc_read(struct bcmasp_intf *intf) +{ + return intf->ops->rx_desc_read(intf); +} + +static inline void bcmasp_intf_rx_buffer_write(struct bcmasp_intf *intf, + dma_addr_t addr) +{ + intf->ops->rx_buffer_write(intf, addr); +} + +static inline void bcmasp_intf_rx_desc_write(struct bcmasp_intf *intf, + dma_addr_t addr) +{ + intf->ops->rx_desc_write(intf, addr); +} + +static inline unsigned long bcmasp_intf_tx_read(struct bcmasp_intf *intf) +{ + return intf->ops->tx_read(intf); +} + +static inline void bcmasp_intf_tx_write(struct bcmasp_intf *intf, + dma_addr_t addr) +{ + intf->ops->tx_write(intf, addr); +} + +#define __BCMASP_IO_MACRO(name, m) \ +static inline u32 name##_rl(struct bcmasp_intf *intf, u32 off) \ +{ \ + u32 reg = readl_relaxed(intf->m + off); \ + return reg; \ +} \ +static inline void name##_wl(struct bcmasp_intf *intf, u32 val, u32 off)\ +{ \ + writel_relaxed(val, intf->m + off); \ +} + +#define BCMASP_IO_MACRO(name) __BCMASP_IO_MACRO(name, res.name) +#define BCMASP_FP_IO_MACRO(name) __BCMASP_IO_MACRO(name, name) + +BCMASP_IO_MACRO(umac); +BCMASP_IO_MACRO(umac2fb); +BCMASP_IO_MACRO(rgmii); +BCMASP_FP_IO_MACRO(tx_spb_dma); +BCMASP_IO_MACRO(tx_spb_ctrl); +BCMASP_IO_MACRO(tx_spb_top); +BCMASP_IO_MACRO(tx_epkt_core); +BCMASP_IO_MACRO(tx_pause_ctrl); +BCMASP_FP_IO_MACRO(rx_edpkt_dma); +BCMASP_FP_IO_MACRO(rx_edpkt_cfg); + +#define __BCMASP_FP_IO_MACRO_Q(name, m) \ +static inline u64 name##_rq(struct bcmasp_intf *intf, u32 off) \ +{ \ + u64 reg = readq_relaxed(intf->m + off); \ + return reg; \ +} \ +static inline void name##_wq(struct bcmasp_intf *intf, u64 val, u32 off)\ +{ \ + writeq_relaxed(val, intf->m + off); \ +} + +#define BCMASP_FP_IO_MACRO_Q(name) __BCMASP_FP_IO_MACRO_Q(name, name) + +BCMASP_FP_IO_MACRO_Q(tx_spb_dma); +BCMASP_FP_IO_MACRO_Q(rx_edpkt_dma); +BCMASP_FP_IO_MACRO_Q(rx_edpkt_cfg); + +#define PKT_OFFLOAD_NOP (0 << 28) +#define PKT_OFFLOAD_HDR_OP (1 << 28) +#define PKT_OFFLOAD_HDR_WRBACK BIT(19) +#define PKT_OFFLOAD_HDR_COUNT(x) ((x) << 16) +#define PKT_OFFLOAD_HDR_SIZE_1(x) ((x) << 4) +#define PKT_OFFLOAD_HDR_SIZE_2(x) (x) +#define PKT_OFFLOAD_HDR2_SIZE_2(x) ((x) << 24) +#define PKT_OFFLOAD_HDR2_SIZE_3(x) ((x) << 12) +#define PKT_OFFLOAD_HDR2_SIZE_4(x) (x) +#define PKT_OFFLOAD_EPKT_OP (2 << 28) +#define PKT_OFFLOAD_EPKT_WRBACK BIT(23) +#define PKT_OFFLOAD_EPKT_IP(x) ((x) << 21) +#define PKT_OFFLOAD_EPKT_TP(x) ((x) << 19) +#define PKT_OFFLOAD_EPKT_LEN(x) ((x) << 16) +#define PKT_OFFLOAD_EPKT_CSUM_L3 BIT(15) +#define PKT_OFFLOAD_EPKT_CSUM_L2 BIT(14) +#define PKT_OFFLOAD_EPKT_ID(x) ((x) << 12) +#define PKT_OFFLOAD_EPKT_SEQ(x) ((x) << 10) +#define PKT_OFFLOAD_EPKT_TS(x) ((x) << 8) +#define PKT_OFFLOAD_EPKT_BLOC(x) (x) +#define PKT_OFFLOAD_END_OP (7 << 28) + +struct bcmasp_pkt_offload { + __be32 nop; + __be32 header; + __be32 header2; + __be32 epkt; + __be32 end; +}; + +#define BCMASP_CORE_IO_MACRO(name, offset) \ +static inline u32 name##_core_rl(struct bcmasp_priv *priv, \ + u32 off) \ +{ \ + u32 reg = readl_relaxed(priv->base + (offset) + off); \ + return reg; \ +} \ +static inline void name##_core_wl(struct bcmasp_priv *priv, \ + u32 val, u32 off) \ +{ \ + writel_relaxed(val, priv->base + (offset) + off); \ +} + +BCMASP_CORE_IO_MACRO(intr2, ASP_INTR2_OFFSET); +BCMASP_CORE_IO_MACRO(wakeup_intr2, ASP_WAKEUP_INTR2_OFFSET); +BCMASP_CORE_IO_MACRO(tx_analytics, ASP_TX_ANALYTICS_OFFSET); +BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET); +BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET); +BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET); +BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET); +BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL); + +struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + struct device_node *ndev_dn, int i); + +void bcmasp_interface_destroy(struct bcmasp_intf *intf); + +void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en); + +void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en); + +void bcmasp_flush_rx_port(struct bcmasp_intf *intf); + +extern const struct ethtool_ops bcmasp_ethtool_ops; + +int bcmasp_interface_suspend(struct bcmasp_intf *intf); + +int bcmasp_interface_resume(struct bcmasp_intf *intf); + +void bcmasp_set_promisc(struct bcmasp_intf *intf, bool en); + +void bcmasp_set_allmulti(struct bcmasp_intf *intf, bool en); + +void bcmasp_set_broad(struct bcmasp_intf *intf, bool en); + +void bcmasp_set_oaddr(struct bcmasp_intf *intf, const unsigned char *addr, + bool en); + +int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr, + unsigned char *mask); + +void bcmasp_disable_all_filters(struct bcmasp_intf *intf); + +void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en); + +#endif diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c new file mode 100644 index 000000000000..394c0e1cb026 --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +#define pr_fmt(fmt) "bcmasp_ethtool: " fmt + +#include +#include +#include + +#include "bcmasp.h" +#include "bcmasp_intf_defs.h" + +static void bcmasp_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strscpy(info->driver, "bcmasp", sizeof(info->driver)); + strscpy(info->bus_info, dev_name(dev->dev.parent), + sizeof(info->bus_info)); +} + +static u32 bcmasp_get_msglevel(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + return intf->msg_enable; +} + +static void bcmasp_set_msglevel(struct net_device *dev, u32 level) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + intf->msg_enable = level; +} + +const struct ethtool_ops bcmasp_ethtool_ops = { + .get_drvinfo = bcmasp_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, + .get_msglevel = bcmasp_get_msglevel, + .set_msglevel = bcmasp_set_msglevel, +}; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c new file mode 100644 index 000000000000..0232f5cf8909 --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -0,0 +1,1342 @@ +// SPDX-License-Identifier: GPL-2.0 +#define pr_fmt(fmt) "bcmasp_intf: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcmasp.h" +#include "bcmasp_intf_defs.h" + +static int incr_ring(int index, int ring_count) +{ + index++; + if (index == ring_count) + return 0; + + return index; +} + +/* Points to last byte of descriptor */ +static dma_addr_t incr_last_byte(dma_addr_t addr, dma_addr_t beg, + int ring_count) +{ + dma_addr_t end = beg + (ring_count * DESC_SIZE); + + addr += DESC_SIZE; + if (addr > end) + return beg + DESC_SIZE - 1; + + return addr; +} + +/* Points to first byte of descriptor */ +static dma_addr_t incr_first_byte(dma_addr_t addr, dma_addr_t beg, + int ring_count) +{ + dma_addr_t end = beg + (ring_count * DESC_SIZE); + + addr += DESC_SIZE; + if (addr >= end) + return beg; + + return addr; +} + +static void bcmasp_enable_tx(struct bcmasp_intf *intf, int en) +{ + if (en) { + tx_spb_ctrl_wl(intf, TX_SPB_CTRL_ENABLE_EN, TX_SPB_CTRL_ENABLE); + tx_epkt_core_wl(intf, (TX_EPKT_C_CFG_MISC_EN | + TX_EPKT_C_CFG_MISC_PT | + (intf->port << TX_EPKT_C_CFG_MISC_PS_SHIFT)), + TX_EPKT_C_CFG_MISC); + } else { + tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE); + tx_epkt_core_wl(intf, 0x0, TX_EPKT_C_CFG_MISC); + } +} + +static void bcmasp_enable_rx(struct bcmasp_intf *intf, int en) +{ + if (en) + rx_edpkt_cfg_wl(intf, RX_EDPKT_CFG_ENABLE_EN, + RX_EDPKT_CFG_ENABLE); + else + rx_edpkt_cfg_wl(intf, 0x0, RX_EDPKT_CFG_ENABLE); +} + +static void bcmasp_set_rx_mode(struct net_device *dev) +{ + unsigned char mask[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct bcmasp_intf *intf = netdev_priv(dev); + struct netdev_hw_addr *ha; + int ret; + + spin_lock_bh(&intf->parent->mda_lock); + + bcmasp_disable_all_filters(intf); + + if (dev->flags & IFF_PROMISC) + goto set_promisc; + + bcmasp_set_promisc(intf, 0); + + bcmasp_set_broad(intf, 1); + + bcmasp_set_oaddr(intf, dev->dev_addr, 1); + + if (dev->flags & IFF_ALLMULTI) { + bcmasp_set_allmulti(intf, 1); + } else { + bcmasp_set_allmulti(intf, 0); + + netdev_for_each_mc_addr(ha, dev) { + ret = bcmasp_set_en_mda_filter(intf, ha->addr, mask); + if (ret) + goto set_promisc; + } + } + + netdev_for_each_uc_addr(ha, dev) { + ret = bcmasp_set_en_mda_filter(intf, ha->addr, mask); + if (ret) + goto set_promisc; + } + + spin_unlock_bh(&intf->parent->mda_lock); + return; + +set_promisc: + bcmasp_set_promisc(intf, 1); + + /* disable all filters used by this port */ + bcmasp_disable_all_filters(intf); + + spin_unlock_bh(&intf->parent->mda_lock); +} + +static void bcmasp_clean_txcb(struct bcmasp_intf *intf, int index) +{ + struct bcmasp_tx_cb *txcb = &intf->tx_cbs[index]; + + txcb->skb = NULL; + dma_unmap_addr_set(txcb, dma_addr, 0); + dma_unmap_len_set(txcb, dma_len, 0); + txcb->last = false; +} + +static int tx_spb_ring_full(struct bcmasp_intf *intf, int cnt) +{ + int next_index, i; + + /* Check if we have enough room for cnt descriptors */ + for (i = 0; i < cnt; i++) { + next_index = incr_ring(intf->tx_spb_index, DESC_RING_COUNT); + if (next_index == intf->tx_spb_clean_index) + return 1; + } + + return 0; +} + +static struct sk_buff *bcmasp_csum_offload(struct net_device *dev, + struct sk_buff *skb, + bool *csum_hw) +{ + u32 header = 0, header2 = 0, epkt = 0; + struct bcmasp_pkt_offload *offload; + unsigned int header_cnt = 0; + u8 ip_proto; + int ret; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return skb; + + ret = skb_cow_head(skb, sizeof(*offload)); + if (ret < 0) + goto help; + + switch (skb->protocol) { + case htons(ETH_P_IP): + header |= PKT_OFFLOAD_HDR_SIZE_2((ip_hdrlen(skb) >> 8) & 0xf); + header2 |= PKT_OFFLOAD_HDR2_SIZE_2(ip_hdrlen(skb) & 0xff); + epkt |= PKT_OFFLOAD_EPKT_IP(0) | PKT_OFFLOAD_EPKT_CSUM_L2; + ip_proto = ip_hdr(skb)->protocol; + header_cnt += 2; + break; + case htons(ETH_P_IPV6): + header |= PKT_OFFLOAD_HDR_SIZE_2((IP6_HLEN >> 8) & 0xf); + header2 |= PKT_OFFLOAD_HDR2_SIZE_2(IP6_HLEN & 0xff); + epkt |= PKT_OFFLOAD_EPKT_IP(1) | PKT_OFFLOAD_EPKT_CSUM_L2; + ip_proto = ipv6_hdr(skb)->nexthdr; + header_cnt += 2; + break; + default: + goto help; + } + + switch (ip_proto) { + case IPPROTO_TCP: + header2 |= PKT_OFFLOAD_HDR2_SIZE_3(tcp_hdrlen(skb)); + epkt |= PKT_OFFLOAD_EPKT_TP(0) | PKT_OFFLOAD_EPKT_CSUM_L3; + header_cnt++; + break; + case IPPROTO_UDP: + header2 |= PKT_OFFLOAD_HDR2_SIZE_3(UDP_HLEN); + epkt |= PKT_OFFLOAD_EPKT_TP(1) | PKT_OFFLOAD_EPKT_CSUM_L3; + header_cnt++; + break; + default: + goto help; + } + + offload = (struct bcmasp_pkt_offload *)skb_push(skb, sizeof(*offload)); + + header |= PKT_OFFLOAD_HDR_OP | PKT_OFFLOAD_HDR_COUNT(header_cnt) | + PKT_OFFLOAD_HDR_SIZE_1(ETH_HLEN); + epkt |= PKT_OFFLOAD_EPKT_OP; + + offload->nop = htonl(PKT_OFFLOAD_NOP); + offload->header = htonl(header); + offload->header2 = htonl(header2); + offload->epkt = htonl(epkt); + offload->end = htonl(PKT_OFFLOAD_END_OP); + *csum_hw = true; + + return skb; + +help: + skb_checksum_help(skb); + + return skb; +} + +static unsigned long bcmasp_rx_edpkt_dma_rq(struct bcmasp_intf *intf) +{ + return rx_edpkt_dma_rq(intf, RX_EDPKT_DMA_VALID); +} + +static void bcmasp_rx_edpkt_cfg_wq(struct bcmasp_intf *intf, dma_addr_t addr) +{ + rx_edpkt_cfg_wq(intf, addr, RX_EDPKT_RING_BUFFER_READ); +} + +static void bcmasp_rx_edpkt_dma_wq(struct bcmasp_intf *intf, dma_addr_t addr) +{ + rx_edpkt_dma_wq(intf, addr, RX_EDPKT_DMA_READ); +} + +static unsigned long bcmasp_tx_spb_dma_rq(struct bcmasp_intf *intf) +{ + return tx_spb_dma_rq(intf, TX_SPB_DMA_READ); +} + +static void bcmasp_tx_spb_dma_wq(struct bcmasp_intf *intf, dma_addr_t addr) +{ + tx_spb_dma_wq(intf, addr, TX_SPB_DMA_VALID); +} + +static const struct bcmasp_intf_ops bcmasp_intf_ops = { + .rx_desc_read = bcmasp_rx_edpkt_dma_rq, + .rx_buffer_write = bcmasp_rx_edpkt_cfg_wq, + .rx_desc_write = bcmasp_rx_edpkt_dma_wq, + .tx_read = bcmasp_tx_spb_dma_rq, + .tx_write = bcmasp_tx_spb_dma_wq, +}; + +static netdev_tx_t bcmasp_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + unsigned int total_bytes, size; + int spb_index, nr_frags, i, j; + struct bcmasp_tx_cb *txcb; + dma_addr_t mapping, valid; + struct bcmasp_desc *desc; + bool csum_hw = false; + struct device *kdev; + skb_frag_t *frag; + + kdev = &intf->parent->pdev->dev; + + nr_frags = skb_shinfo(skb)->nr_frags; + + if (tx_spb_ring_full(intf, nr_frags + 1)) { + netif_stop_queue(dev); + if (net_ratelimit()) + netdev_err(dev, "Tx Ring Full!\n"); + return NETDEV_TX_BUSY; + } + + /* Save skb len before adding csum offload header */ + total_bytes = skb->len; + skb = bcmasp_csum_offload(dev, skb, &csum_hw); + if (!skb) + return NETDEV_TX_OK; + + spb_index = intf->tx_spb_index; + valid = intf->tx_spb_dma_valid; + for (i = 0; i <= nr_frags; i++) { + if (!i) { + size = skb_headlen(skb); + if (!nr_frags && size < (ETH_ZLEN + ETH_FCS_LEN)) { + if (skb_put_padto(skb, ETH_ZLEN + ETH_FCS_LEN)) + return NETDEV_TX_OK; + size = skb->len; + } + mapping = dma_map_single(kdev, skb->data, size, + DMA_TO_DEVICE); + } else { + frag = &skb_shinfo(skb)->frags[i - 1]; + size = skb_frag_size(frag); + mapping = skb_frag_dma_map(kdev, frag, 0, size, + DMA_TO_DEVICE); + } + + if (dma_mapping_error(kdev, mapping)) { + spb_index = intf->tx_spb_index; + for (j = 0; j < i; j++) { + bcmasp_clean_txcb(intf, spb_index); + spb_index = incr_ring(spb_index, + DESC_RING_COUNT); + } + /* Rewind so we do not have a hole */ + spb_index = intf->tx_spb_index; + return NETDEV_TX_OK; + } + + txcb = &intf->tx_cbs[spb_index]; + desc = &intf->tx_spb_cpu[spb_index]; + memset(desc, 0, sizeof(*desc)); + txcb->skb = skb; + txcb->bytes_sent = total_bytes; + dma_unmap_addr_set(txcb, dma_addr, mapping); + dma_unmap_len_set(txcb, dma_len, size); + if (!i) { + desc->flags |= DESC_SOF; + if (csum_hw) + desc->flags |= DESC_EPKT_CMD; + } + + if (i == nr_frags) { + desc->flags |= DESC_EOF; + txcb->last = true; + } + + desc->buf = mapping; + desc->size = size; + desc->flags |= DESC_INT_EN; + + netif_dbg(intf, tx_queued, dev, + "%s dma_buf=%pad dma_len=0x%x flags=0x%x index=0x%x\n", + __func__, &mapping, desc->size, desc->flags, + spb_index); + + spb_index = incr_ring(spb_index, DESC_RING_COUNT); + valid = incr_last_byte(valid, intf->tx_spb_dma_addr, + DESC_RING_COUNT); + } + + /* Ensure all descriptors have been written to DRAM for the + * hardware to see up-to-date contents. + */ + wmb(); + + intf->tx_spb_index = spb_index; + intf->tx_spb_dma_valid = valid; + bcmasp_intf_tx_write(intf, intf->tx_spb_dma_valid); + + if (tx_spb_ring_full(intf, MAX_SKB_FRAGS + 1)) + netif_stop_queue(dev); + + return NETDEV_TX_OK; +} + +static void bcmasp_netif_start(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + bcmasp_set_rx_mode(dev); + napi_enable(&intf->tx_napi); + napi_enable(&intf->rx_napi); + + bcmasp_enable_rx_irq(intf, 1); + bcmasp_enable_tx_irq(intf, 1); + + phy_start(dev->phydev); +} + +static void umac_reset(struct bcmasp_intf *intf) +{ + umac_wl(intf, 0x0, UMC_CMD); + umac_wl(intf, UMC_CMD_SW_RESET, UMC_CMD); + usleep_range(10, 100); + umac_wl(intf, 0x0, UMC_CMD); +} + +static void umac_set_hw_addr(struct bcmasp_intf *intf, + const unsigned char *addr) +{ + u32 mac0 = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | + addr[3]; + u32 mac1 = (addr[4] << 8) | addr[5]; + + umac_wl(intf, mac0, UMC_MAC0); + umac_wl(intf, mac1, UMC_MAC1); +} + +static void umac_enable_set(struct bcmasp_intf *intf, u32 mask, + unsigned int enable) +{ + u32 reg; + + reg = umac_rl(intf, UMC_CMD); + if (enable) + reg |= mask; + else + reg &= ~mask; + umac_wl(intf, reg, UMC_CMD); + + /* UniMAC stops on a packet boundary, wait for a full-sized packet + * to be processed (1 msec). + */ + if (enable == 0) + usleep_range(1000, 2000); +} + +static void umac_init(struct bcmasp_intf *intf) +{ + umac_wl(intf, 0x800, UMC_FRM_LEN); + umac_wl(intf, 0xffff, UMC_PAUSE_CNTRL); + umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ); + umac_enable_set(intf, UMC_CMD_PROMISC, 1); +} + +static int bcmasp_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmasp_intf *intf = + container_of(napi, struct bcmasp_intf, tx_napi); + struct bcmasp_intf_stats64 *stats = &intf->stats64; + struct device *kdev = &intf->parent->pdev->dev; + unsigned long read, released = 0; + struct bcmasp_tx_cb *txcb; + struct bcmasp_desc *desc; + dma_addr_t mapping; + + read = bcmasp_intf_tx_read(intf); + while (intf->tx_spb_dma_read != read) { + txcb = &intf->tx_cbs[intf->tx_spb_clean_index]; + mapping = dma_unmap_addr(txcb, dma_addr); + + dma_unmap_single(kdev, mapping, + dma_unmap_len(txcb, dma_len), + DMA_TO_DEVICE); + + if (txcb->last) { + dev_consume_skb_any(txcb->skb); + + u64_stats_update_begin(&stats->syncp); + u64_stats_inc(&stats->tx_packets); + u64_stats_add(&stats->tx_bytes, txcb->bytes_sent); + u64_stats_update_end(&stats->syncp); + } + + desc = &intf->tx_spb_cpu[intf->tx_spb_clean_index]; + + netif_dbg(intf, tx_done, intf->ndev, + "%s dma_buf=%pad dma_len=0x%x flags=0x%x c_index=0x%x\n", + __func__, &mapping, desc->size, desc->flags, + intf->tx_spb_clean_index); + + bcmasp_clean_txcb(intf, intf->tx_spb_clean_index); + released++; + + intf->tx_spb_clean_index = incr_ring(intf->tx_spb_clean_index, + DESC_RING_COUNT); + intf->tx_spb_dma_read = incr_first_byte(intf->tx_spb_dma_read, + intf->tx_spb_dma_addr, + DESC_RING_COUNT); + } + + /* Ensure all descriptors have been written to DRAM for the hardware + * to see updated contents. + */ + wmb(); + + napi_complete(&intf->tx_napi); + + bcmasp_enable_tx_irq(intf, 1); + + if (released) + netif_wake_queue(intf->ndev); + + return 0; +} + +static int bcmasp_rx_poll(struct napi_struct *napi, int budget) +{ + struct bcmasp_intf *intf = + container_of(napi, struct bcmasp_intf, rx_napi); + struct bcmasp_intf_stats64 *stats = &intf->stats64; + struct device *kdev = &intf->parent->pdev->dev; + unsigned long processed = 0; + struct bcmasp_desc *desc; + struct sk_buff *skb; + dma_addr_t valid; + void *data; + u64 flags; + u32 len; + + valid = bcmasp_intf_rx_desc_read(intf) + 1; + if (valid == intf->rx_edpkt_dma_addr + DESC_RING_SIZE) + valid = intf->rx_edpkt_dma_addr; + + while ((processed < budget) && (valid != intf->rx_edpkt_dma_read)) { + desc = &intf->rx_edpkt_cpu[intf->rx_edpkt_index]; + + /* Ensure that descriptor has been fully written to DRAM by + * hardware before reading by the CPU + */ + rmb(); + + /* Calculate virt addr by offsetting from physical addr */ + data = intf->rx_ring_cpu + + (DESC_ADDR(desc->buf) - intf->rx_ring_dma); + + flags = DESC_FLAGS(desc->buf); + if (unlikely(flags & (DESC_CRC_ERR | DESC_RX_SYM_ERR))) { + if (net_ratelimit()) { + netif_err(intf, rx_status, intf->ndev, + "flags=0x%llx\n", flags); + } + + u64_stats_update_begin(&stats->syncp); + if (flags & DESC_CRC_ERR) + u64_stats_inc(&stats->rx_crc_errs); + if (flags & DESC_RX_SYM_ERR) + u64_stats_inc(&stats->rx_sym_errs); + u64_stats_update_end(&stats->syncp); + + goto next; + } + + dma_sync_single_for_cpu(kdev, DESC_ADDR(desc->buf), desc->size, + DMA_FROM_DEVICE); + + len = desc->size; + + skb = napi_alloc_skb(napi, len); + if (!skb) { + u64_stats_update_begin(&stats->syncp); + u64_stats_inc(&stats->rx_dropped); + u64_stats_update_end(&stats->syncp); + goto next; + } + + skb_put(skb, len); + memcpy(skb->data, data, len); + + skb_pull(skb, 2); + len -= 2; + if (likely(intf->crc_fwd)) { + skb_trim(skb, len - ETH_FCS_LEN); + len -= ETH_FCS_LEN; + } + + if ((intf->ndev->features & NETIF_F_RXCSUM) && + (desc->buf & DESC_CHKSUM)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb->protocol = eth_type_trans(skb, intf->ndev); + + napi_gro_receive(napi, skb); + + u64_stats_update_begin(&stats->syncp); + u64_stats_inc(&stats->rx_packets); + u64_stats_add(&stats->rx_bytes, len); + u64_stats_update_end(&stats->syncp); + +next: + bcmasp_intf_rx_buffer_write(intf, (DESC_ADDR(desc->buf) + + desc->size)); + + processed++; + intf->rx_edpkt_dma_read = + incr_first_byte(intf->rx_edpkt_dma_read, + intf->rx_edpkt_dma_addr, + DESC_RING_COUNT); + intf->rx_edpkt_index = incr_ring(intf->rx_edpkt_index, + DESC_RING_COUNT); + } + + bcmasp_intf_rx_desc_write(intf, intf->rx_edpkt_dma_read); + + if (processed < budget) { + napi_complete_done(&intf->rx_napi, processed); + bcmasp_enable_rx_irq(intf, 1); + } + + return processed; +} + +static void bcmasp_adj_link(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct phy_device *phydev = dev->phydev; + u32 cmd_bits = 0, reg; + int changed = 0; + + if (intf->old_link != phydev->link) { + changed = 1; + intf->old_link = phydev->link; + } + + if (intf->old_duplex != phydev->duplex) { + changed = 1; + intf->old_duplex = phydev->duplex; + } + + switch (phydev->speed) { + case SPEED_2500: + cmd_bits = UMC_CMD_SPEED_2500; + break; + case SPEED_1000: + cmd_bits = UMC_CMD_SPEED_1000; + break; + case SPEED_100: + cmd_bits = UMC_CMD_SPEED_100; + break; + case SPEED_10: + cmd_bits = UMC_CMD_SPEED_10; + break; + default: + break; + } + cmd_bits <<= UMC_CMD_SPEED_SHIFT; + + if (phydev->duplex == DUPLEX_HALF) + cmd_bits |= UMC_CMD_HD_EN; + + if (intf->old_pause != phydev->pause) { + changed = 1; + intf->old_pause = phydev->pause; + } + + if (!phydev->pause) + cmd_bits |= UMC_CMD_RX_PAUSE_IGNORE | UMC_CMD_TX_PAUSE_IGNORE; + + if (!changed) + return; + + if (phydev->link) { + reg = umac_rl(intf, UMC_CMD); + reg &= ~((UMC_CMD_SPEED_MASK << UMC_CMD_SPEED_SHIFT) | + UMC_CMD_HD_EN | UMC_CMD_RX_PAUSE_IGNORE | + UMC_CMD_TX_PAUSE_IGNORE); + reg |= cmd_bits; + umac_wl(intf, reg, UMC_CMD); + } + + reg = rgmii_rl(intf, RGMII_OOB_CNTRL); + if (phydev->link) + reg |= RGMII_LINK; + else + reg &= ~RGMII_LINK; + rgmii_wl(intf, reg, RGMII_OOB_CNTRL); + + if (changed) + phy_print_status(phydev); +} + +static int bcmasp_init_rx(struct bcmasp_intf *intf) +{ + struct device *kdev = &intf->parent->pdev->dev; + struct page *buffer_pg; + dma_addr_t dma; + void *p; + u32 reg; + int ret; + + intf->rx_buf_order = get_order(RING_BUFFER_SIZE); + buffer_pg = alloc_pages(GFP_KERNEL, intf->rx_buf_order); + + dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE, + DMA_FROM_DEVICE); + if (dma_mapping_error(kdev, dma)) { + __free_pages(buffer_pg, intf->rx_buf_order); + return -ENOMEM; + } + intf->rx_ring_cpu = page_to_virt(buffer_pg); + intf->rx_ring_dma = dma; + intf->rx_ring_dma_valid = intf->rx_ring_dma + RING_BUFFER_SIZE - 1; + + p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->rx_edpkt_dma_addr, + GFP_KERNEL); + if (!p) { + ret = -ENOMEM; + goto free_rx_ring; + } + intf->rx_edpkt_cpu = p; + + netif_napi_add(intf->ndev, &intf->rx_napi, bcmasp_rx_poll); + + intf->rx_edpkt_dma_read = intf->rx_edpkt_dma_addr; + intf->rx_edpkt_index = 0; + + /* Make sure channels are disabled */ + rx_edpkt_cfg_wl(intf, 0x0, RX_EDPKT_CFG_ENABLE); + + /* Rx SPB */ + rx_edpkt_cfg_wq(intf, intf->rx_ring_dma, RX_EDPKT_RING_BUFFER_READ); + rx_edpkt_cfg_wq(intf, intf->rx_ring_dma, RX_EDPKT_RING_BUFFER_WRITE); + rx_edpkt_cfg_wq(intf, intf->rx_ring_dma, RX_EDPKT_RING_BUFFER_BASE); + rx_edpkt_cfg_wq(intf, intf->rx_ring_dma_valid, + RX_EDPKT_RING_BUFFER_END); + rx_edpkt_cfg_wq(intf, intf->rx_ring_dma_valid, + RX_EDPKT_RING_BUFFER_VALID); + + /* EDPKT */ + rx_edpkt_cfg_wl(intf, (RX_EDPKT_CFG_CFG0_RBUF_4K << + RX_EDPKT_CFG_CFG0_DBUF_SHIFT) | + (RX_EDPKT_CFG_CFG0_64_ALN << + RX_EDPKT_CFG_CFG0_BALN_SHIFT) | + (RX_EDPKT_CFG_CFG0_EFRM_STUF), + RX_EDPKT_CFG_CFG0); + rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_WRITE); + rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_READ); + rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_BASE); + rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1), + RX_EDPKT_DMA_END); + rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1), + RX_EDPKT_DMA_VALID); + + reg = UMAC2FB_CFG_DEFAULT_EN | + ((intf->channel + 11) << UMAC2FB_CFG_CHID_SHIFT); + reg |= (0xd << UMAC2FB_CFG_OK_SEND_SHIFT); + umac2fb_wl(intf, reg, UMAC2FB_CFG); + + return 0; + +free_rx_ring: + dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE, + DMA_FROM_DEVICE); + __free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order); + + return ret; +} + +static void bcmasp_reclaim_free_all_rx(struct bcmasp_intf *intf) +{ + struct device *kdev = &intf->parent->pdev->dev; + + dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu, + intf->rx_edpkt_dma_addr); + dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE, + DMA_FROM_DEVICE); + __free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order); +} + +static int bcmasp_init_tx(struct bcmasp_intf *intf) +{ + struct device *kdev = &intf->parent->pdev->dev; + void *p; + int ret; + + p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->tx_spb_dma_addr, + GFP_KERNEL); + if (!p) + return -ENOMEM; + + intf->tx_spb_cpu = p; + intf->tx_spb_dma_valid = intf->tx_spb_dma_addr + DESC_RING_SIZE - 1; + intf->tx_spb_dma_read = intf->tx_spb_dma_addr; + + intf->tx_cbs = kcalloc(DESC_RING_COUNT, sizeof(struct bcmasp_tx_cb), + GFP_KERNEL); + if (!intf->tx_cbs) { + ret = -ENOMEM; + goto free_tx_spb; + } + + intf->tx_spb_index = 0; + intf->tx_spb_clean_index = 0; + + netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll); + + /* Make sure channels are disabled */ + tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE); + tx_epkt_core_wl(intf, 0x0, TX_EPKT_C_CFG_MISC); + + /* Tx SPB */ + tx_spb_ctrl_wl(intf, ((intf->channel + 8) << TX_SPB_CTRL_XF_BID_SHIFT), + TX_SPB_CTRL_XF_CTRL2); + tx_pause_ctrl_wl(intf, (1 << (intf->channel + 8)), TX_PAUSE_MAP_VECTOR); + tx_spb_top_wl(intf, 0x1e, TX_SPB_TOP_BLKOUT); + tx_spb_top_wl(intf, 0x0, TX_SPB_TOP_SPRE_BW_CTRL); + + tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_READ); + tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_BASE); + tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_END); + tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_VALID); + + return 0; + +free_tx_spb: + dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu, + intf->tx_spb_dma_addr); + + return ret; +} + +static void bcmasp_reclaim_free_all_tx(struct bcmasp_intf *intf) +{ + struct device *kdev = &intf->parent->pdev->dev; + + /* Free descriptors */ + dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu, + intf->tx_spb_dma_addr); + + /* Free cbs */ + kfree(intf->tx_cbs); +} + +static void bcmasp_ephy_enable_set(struct bcmasp_intf *intf, bool enable) +{ + u32 mask = RGMII_EPHY_CFG_IDDQ_BIAS | RGMII_EPHY_CFG_EXT_PWRDOWN | + RGMII_EPHY_CFG_IDDQ_GLOBAL; + u32 reg; + + reg = rgmii_rl(intf, RGMII_EPHY_CNTRL); + if (enable) { + reg &= ~RGMII_EPHY_CK25_DIS; + rgmii_wl(intf, reg, RGMII_EPHY_CNTRL); + mdelay(1); + + reg &= ~mask; + reg |= RGMII_EPHY_RESET; + rgmii_wl(intf, reg, RGMII_EPHY_CNTRL); + mdelay(1); + + reg &= ~RGMII_EPHY_RESET; + } else { + reg |= mask | RGMII_EPHY_RESET; + rgmii_wl(intf, reg, RGMII_EPHY_CNTRL); + mdelay(1); + reg |= RGMII_EPHY_CK25_DIS; + } + rgmii_wl(intf, reg, RGMII_EPHY_CNTRL); + mdelay(1); + + /* Set or clear the LED control override to avoid lighting up LEDs + * while the EPHY is powered off and drawing unnecessary current. + */ + reg = rgmii_rl(intf, RGMII_SYS_LED_CNTRL); + if (enable) + reg &= ~RGMII_SYS_LED_CNTRL_LINK_OVRD; + else + reg |= RGMII_SYS_LED_CNTRL_LINK_OVRD; + rgmii_wl(intf, reg, RGMII_SYS_LED_CNTRL); +} + +static void bcmasp_rgmii_mode_en_set(struct bcmasp_intf *intf, bool enable) +{ + u32 reg; + + reg = rgmii_rl(intf, RGMII_OOB_CNTRL); + reg &= ~RGMII_OOB_DIS; + if (enable) + reg |= RGMII_MODE_EN; + else + reg &= ~RGMII_MODE_EN; + rgmii_wl(intf, reg, RGMII_OOB_CNTRL); +} + +static void bcmasp_netif_deinit(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + u32 reg, timeout = 1000; + + napi_disable(&intf->tx_napi); + + bcmasp_enable_tx(intf, 0); + + /* Flush any TX packets in the pipe */ + tx_spb_dma_wl(intf, TX_SPB_DMA_FIFO_FLUSH, TX_SPB_DMA_FIFO_CTRL); + do { + reg = tx_spb_dma_rl(intf, TX_SPB_DMA_FIFO_STATUS); + if (!(reg & TX_SPB_DMA_FIFO_FLUSH)) + break; + usleep_range(1000, 2000); + } while (timeout-- > 0); + tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL); + + umac_enable_set(intf, UMC_CMD_TX_EN, 0); + + phy_stop(dev->phydev); + + umac_enable_set(intf, UMC_CMD_RX_EN, 0); + + bcmasp_flush_rx_port(intf); + usleep_range(1000, 2000); + bcmasp_enable_rx(intf, 0); + + napi_disable(&intf->rx_napi); + + /* Disable interrupts */ + bcmasp_enable_tx_irq(intf, 0); + bcmasp_enable_rx_irq(intf, 0); + + netif_napi_del(&intf->tx_napi); + bcmasp_reclaim_free_all_tx(intf); + + netif_napi_del(&intf->rx_napi); + bcmasp_reclaim_free_all_rx(intf); +} + +static int bcmasp_stop(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + netif_dbg(intf, ifdown, dev, "bcmasp stop\n"); + + /* Stop tx from updating HW */ + netif_tx_disable(dev); + + bcmasp_netif_deinit(dev); + + phy_disconnect(dev->phydev); + + /* Disable internal EPHY or external PHY */ + if (intf->internal_phy) + bcmasp_ephy_enable_set(intf, false); + else + bcmasp_rgmii_mode_en_set(intf, false); + + /* Disable the interface clocks */ + bcmasp_core_clock_set_intf(intf, false); + + clk_disable_unprepare(intf->parent->clk); + + return 0; +} + +static void bcmasp_configure_port(struct bcmasp_intf *intf) +{ + u32 reg, id_mode_dis = 0; + + reg = rgmii_rl(intf, RGMII_PORT_CNTRL); + reg &= ~RGMII_PORT_MODE_MASK; + + switch (intf->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + /* RGMII_NO_ID: TXC transitions at the same time as TXD + * (requires PCB or receiver-side delay) + * RGMII: Add 2ns delay on TXC (90 degree shift) + * + * ID is implicitly disabled for 100Mbps (RG)MII operation. + */ + id_mode_dis = RGMII_ID_MODE_DIS; + fallthrough; + case PHY_INTERFACE_MODE_RGMII_TXID: + reg |= RGMII_PORT_MODE_EXT_GPHY; + break; + case PHY_INTERFACE_MODE_MII: + reg |= RGMII_PORT_MODE_EXT_EPHY; + break; + default: + break; + } + + if (intf->internal_phy) + reg |= RGMII_PORT_MODE_EPHY; + + rgmii_wl(intf, reg, RGMII_PORT_CNTRL); + + reg = rgmii_rl(intf, RGMII_OOB_CNTRL); + reg &= ~RGMII_ID_MODE_DIS; + reg |= id_mode_dis; + rgmii_wl(intf, reg, RGMII_OOB_CNTRL); +} + +static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + phy_interface_t phy_iface = intf->phy_interface; + u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE | + PHY_BRCM_DIS_TXCRXC_NOENRGY | + PHY_BRCM_IDDQ_SUSPEND; + struct phy_device *phydev = NULL; + int ret; + + /* Always enable interface clocks */ + bcmasp_core_clock_set_intf(intf, true); + + /* Enable internal PHY or external PHY before any MAC activity */ + if (intf->internal_phy) + bcmasp_ephy_enable_set(intf, true); + else + bcmasp_rgmii_mode_en_set(intf, true); + bcmasp_configure_port(intf); + + /* This is an ugly quirk but we have not been correctly + * interpreting the phy_interface values and we have done that + * across different drivers, so at least we are consistent in + * our mistakes. + * + * When the Generic PHY driver is in use either the PHY has + * been strapped or programmed correctly by the boot loader so + * we should stick to our incorrect interpretation since we + * have validated it. + * + * Now when a dedicated PHY driver is in use, we need to + * reverse the meaning of the phy_interface_mode values to + * something that the PHY driver will interpret and act on such + * that we have two mistakes canceling themselves so to speak. + * We only do this for the two modes that GENET driver + * officially supports on Broadcom STB chips: + * PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. + * Other modes are not *officially* supported with the boot + * loader and the scripted environment generating Device Tree + * blobs for those platforms. + * + * Note that internal PHY and fixed-link configurations are not + * affected because they use different phy_interface_t values + * or the Generic PHY driver. + */ + switch (phy_iface) { + case PHY_INTERFACE_MODE_RGMII: + phy_iface = PHY_INTERFACE_MODE_RGMII_ID; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + phy_iface = PHY_INTERFACE_MODE_RGMII_RXID; + break; + default: + break; + } + + if (phy_connect) { + phydev = of_phy_connect(dev, intf->phy_dn, + bcmasp_adj_link, phy_flags, + phy_iface); + if (!phydev) { + ret = -ENODEV; + netdev_err(dev, "could not attach to PHY\n"); + goto err_phy_disable; + } + } else { + ret = phy_resume(dev->phydev); + if (ret) + goto err_phy_disable; + } + + umac_reset(intf); + + umac_init(intf); + + /* Disable the UniMAC RX/TX */ + umac_enable_set(intf, (UMC_CMD_RX_EN | UMC_CMD_TX_EN), 0); + + umac_set_hw_addr(intf, dev->dev_addr); + + intf->old_duplex = -1; + intf->old_link = -1; + intf->old_pause = -1; + + ret = bcmasp_init_tx(intf); + if (ret) + goto err_phy_disconnect; + + /* Turn on asp */ + bcmasp_enable_tx(intf, 1); + + ret = bcmasp_init_rx(intf); + if (ret) + goto err_reclaim_tx; + + bcmasp_enable_rx(intf, 1); + + /* Turn on UniMAC TX/RX */ + umac_enable_set(intf, (UMC_CMD_RX_EN | UMC_CMD_TX_EN), 1); + + intf->crc_fwd = !!(umac_rl(intf, UMC_CMD) & UMC_CMD_CRC_FWD); + + bcmasp_netif_start(dev); + + netif_start_queue(dev); + + return 0; + +err_reclaim_tx: + bcmasp_reclaim_free_all_tx(intf); +err_phy_disconnect: + if (phydev) + phy_disconnect(phydev); +err_phy_disable: + if (intf->internal_phy) + bcmasp_ephy_enable_set(intf, false); + else + bcmasp_rgmii_mode_en_set(intf, false); + return ret; +} + +static int bcmasp_open(struct net_device *dev) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + int ret; + + netif_dbg(intf, ifup, dev, "bcmasp open\n"); + + ret = clk_prepare_enable(intf->parent->clk); + if (ret) + return ret; + + ret = bcmasp_netif_init(dev, true); + if (ret) + clk_disable_unprepare(intf->parent->clk); + + return ret; +} + +static void bcmasp_tx_timeout(struct net_device *dev, unsigned int txqueue) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + netif_dbg(intf, tx_err, dev, "transmit timeout!\n"); +} + +static int bcmasp_get_phys_port_name(struct net_device *dev, + char *name, size_t len) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + if (snprintf(name, len, "p%d", intf->port) >= len) + return -EINVAL; + + return 0; +} + +static void bcmasp_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct bcmasp_intf_stats64 *lstats; + unsigned int start; + + lstats = &intf->stats64; + + do { + start = u64_stats_fetch_begin(&lstats->syncp); + stats->rx_packets = u64_stats_read(&lstats->rx_packets); + stats->rx_bytes = u64_stats_read(&lstats->rx_bytes); + stats->rx_dropped = u64_stats_read(&lstats->rx_dropped); + stats->rx_crc_errors = u64_stats_read(&lstats->rx_crc_errs); + stats->rx_frame_errors = u64_stats_read(&lstats->rx_sym_errs); + stats->rx_errors = stats->rx_crc_errors + stats->rx_frame_errors; + + stats->tx_packets = u64_stats_read(&lstats->tx_packets); + stats->tx_bytes = u64_stats_read(&lstats->tx_bytes); + } while (u64_stats_fetch_retry(&lstats->syncp, start)); +} + +static const struct net_device_ops bcmasp_netdev_ops = { + .ndo_open = bcmasp_open, + .ndo_stop = bcmasp_stop, + .ndo_start_xmit = bcmasp_xmit, + .ndo_tx_timeout = bcmasp_tx_timeout, + .ndo_set_rx_mode = bcmasp_set_rx_mode, + .ndo_get_phys_port_name = bcmasp_get_phys_port_name, + .ndo_eth_ioctl = phy_do_ioctl_running, + .ndo_set_mac_address = eth_mac_addr, + .ndo_get_stats64 = bcmasp_get_stats64, +}; + +static void bcmasp_map_res(struct bcmasp_priv *priv, struct bcmasp_intf *intf) +{ + /* Per port */ + intf->res.umac = priv->base + UMC_OFFSET(intf); + intf->res.umac2fb = priv->base + (priv->hw_info->umac2fb + + (intf->port * 0x4)); + intf->res.rgmii = priv->base + RGMII_OFFSET(intf); + + /* Per ch */ + intf->tx_spb_dma = priv->base + TX_SPB_DMA_OFFSET(intf); + intf->res.tx_spb_ctrl = priv->base + TX_SPB_CTRL_OFFSET(intf); + intf->res.tx_spb_top = priv->base + TX_SPB_TOP_OFFSET(intf); + intf->res.tx_epkt_core = priv->base + TX_EPKT_C_OFFSET(intf); + intf->res.tx_pause_ctrl = priv->base + TX_PAUSE_CTRL_OFFSET(intf); + + intf->rx_edpkt_dma = priv->base + RX_EDPKT_DMA_OFFSET(intf); + intf->rx_edpkt_cfg = priv->base + RX_EDPKT_CFG_OFFSET(intf); +} + +#define MAX_IRQ_STR_LEN 64 +struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + struct device_node *ndev_dn, int i) +{ + struct device *dev = &priv->pdev->dev; + struct bcmasp_intf *intf; + struct net_device *ndev; + int ch, port, ret; + + if (of_property_read_u32(ndev_dn, "reg", &port)) { + dev_warn(dev, "%s: invalid port number\n", ndev_dn->name); + goto err; + } + + if (of_property_read_u32(ndev_dn, "brcm,channel", &ch)) { + dev_warn(dev, "%s: invalid ch number\n", ndev_dn->name); + goto err; + } + + ndev = alloc_etherdev(sizeof(struct bcmasp_intf)); + if (!ndev) { + dev_warn(dev, "%s: unable to alloc ndev\n", ndev_dn->name); + goto err; + } + intf = netdev_priv(ndev); + + intf->parent = priv; + intf->ndev = ndev; + intf->channel = ch; + intf->port = port; + intf->ndev_dn = ndev_dn; + intf->index = i; + + ret = of_get_phy_mode(ndev_dn, &intf->phy_interface); + if (ret < 0) { + dev_err(dev, "invalid PHY mode property\n"); + goto err_free_netdev; + } + + if (intf->phy_interface == PHY_INTERFACE_MODE_INTERNAL) + intf->internal_phy = true; + + intf->phy_dn = of_parse_phandle(ndev_dn, "phy-handle", 0); + if (!intf->phy_dn && of_phy_is_fixed_link(ndev_dn)) { + ret = of_phy_register_fixed_link(ndev_dn); + if (ret) { + dev_warn(dev, "%s: failed to register fixed PHY\n", + ndev_dn->name); + goto err_free_netdev; + } + intf->phy_dn = ndev_dn; + } + + /* Map resource */ + bcmasp_map_res(priv, intf); + + if ((!phy_interface_mode_is_rgmii(intf->phy_interface) && + intf->phy_interface != PHY_INTERFACE_MODE_MII && + intf->phy_interface != PHY_INTERFACE_MODE_INTERNAL) || + (intf->port != 1 && intf->internal_phy)) { + netdev_err(intf->ndev, "invalid PHY mode: %s for port %d\n", + phy_modes(intf->phy_interface), intf->port); + ret = -EINVAL; + goto err_free_netdev; + } + + ret = of_get_ethdev_address(ndev_dn, ndev); + if (ret) { + netdev_warn(ndev, "using random Ethernet MAC\n"); + eth_hw_addr_random(ndev); + } + + SET_NETDEV_DEV(ndev, dev); + intf->ops = &bcmasp_intf_ops; + ndev->netdev_ops = &bcmasp_netdev_ops; + ndev->ethtool_ops = &bcmasp_ethtool_ops; + intf->msg_enable = netif_msg_init(-1, NETIF_MSG_DRV | + NETIF_MSG_PROBE | + NETIF_MSG_LINK); + ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | + NETIF_F_RXCSUM; + ndev->hw_features |= ndev->features; + ndev->needed_headroom += sizeof(struct bcmasp_pkt_offload); + + return intf; + +err_free_netdev: + free_netdev(ndev); +err: + return NULL; +} + +void bcmasp_interface_destroy(struct bcmasp_intf *intf) +{ + if (intf->ndev->reg_state == NETREG_REGISTERED) + unregister_netdev(intf->ndev); + if (of_phy_is_fixed_link(intf->ndev_dn)) + of_phy_deregister_fixed_link(intf->ndev_dn); + free_netdev(intf->ndev); +} + +int bcmasp_interface_suspend(struct bcmasp_intf *intf) +{ + struct net_device *dev = intf->ndev; + int ret = 0; + + if (!netif_running(dev)) + return 0; + + netif_device_detach(dev); + + bcmasp_netif_deinit(dev); + + ret = phy_suspend(dev->phydev); + if (ret) + goto out; + + if (intf->internal_phy) + bcmasp_ephy_enable_set(intf, false); + else + bcmasp_rgmii_mode_en_set(intf, false); + + /* If Wake-on-LAN is disabled, we can safely + * disable the network interface clocks. + */ + bcmasp_core_clock_set_intf(intf, false); + + clk_disable_unprepare(intf->parent->clk); + + return ret; + +out: + bcmasp_netif_init(dev, false); + return ret; +} + +int bcmasp_interface_resume(struct bcmasp_intf *intf) +{ + struct net_device *dev = intf->ndev; + int ret; + + if (!netif_running(dev)) + return 0; + + ret = clk_prepare_enable(intf->parent->clk); + if (ret) + return ret; + + ret = bcmasp_netif_init(dev, false); + if (ret) + goto out; + + netif_device_attach(dev); + + return 0; + +out: + clk_disable_unprepare(intf->parent->clk); + return ret; +} diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h new file mode 100644 index 000000000000..b259a475207f --- /dev/null +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __BCMASP_INTF_DEFS_H +#define __BCMASP_INTF_DEFS_H + +#define UMC_OFFSET(intf) \ + ((((intf)->port) * 0x800) + 0xc000) +#define UMC_CMD 0x008 +#define UMC_CMD_TX_EN BIT(0) +#define UMC_CMD_RX_EN BIT(1) +#define UMC_CMD_SPEED_SHIFT 0x2 +#define UMC_CMD_SPEED_MASK 0x3 +#define UMC_CMD_SPEED_10 0x0 +#define UMC_CMD_SPEED_100 0x1 +#define UMC_CMD_SPEED_1000 0x2 +#define UMC_CMD_SPEED_2500 0x3 +#define UMC_CMD_PROMISC BIT(4) +#define UMC_CMD_PAD_EN BIT(5) +#define UMC_CMD_CRC_FWD BIT(6) +#define UMC_CMD_PAUSE_FWD BIT(7) +#define UMC_CMD_RX_PAUSE_IGNORE BIT(8) +#define UMC_CMD_TX_ADDR_INS BIT(9) +#define UMC_CMD_HD_EN BIT(10) +#define UMC_CMD_SW_RESET BIT(13) +#define UMC_CMD_LCL_LOOP_EN BIT(15) +#define UMC_CMD_AUTO_CONFIG BIT(22) +#define UMC_CMD_CNTL_FRM_EN BIT(23) +#define UMC_CMD_NO_LEN_CHK BIT(24) +#define UMC_CMD_RMT_LOOP_EN BIT(25) +#define UMC_CMD_PRBL_EN BIT(27) +#define UMC_CMD_TX_PAUSE_IGNORE BIT(28) +#define UMC_CMD_TX_RX_EN BIT(29) +#define UMC_CMD_RUNT_FILTER_DIS BIT(30) +#define UMC_MAC0 0x0c +#define UMC_MAC1 0x10 +#define UMC_FRM_LEN 0x14 +#define UMC_EEE_CTRL 0x64 +#define EN_LPI_RX_PAUSE BIT(0) +#define EN_LPI_TX_PFC BIT(1) +#define EN_LPI_TX_PAUSE BIT(2) +#define EEE_EN BIT(3) +#define RX_FIFO_CHECK BIT(4) +#define EEE_TX_CLK_DIS BIT(5) +#define DIS_EEE_10M BIT(6) +#define LP_IDLE_PREDICTION_MODE BIT(7) +#define UMC_EEE_LPI_TIMER 0x68 +#define UMC_PAUSE_CNTRL 0x330 +#define UMC_TX_FLUSH 0x334 +#define UMC_MIB_START 0x400 +#define UMC_MIB_CNTRL 0x580 +#define UMC_MIB_CNTRL_RX_CNT_RST BIT(0) +#define UMC_MIB_CNTRL_RUNT_CNT_RST BIT(1) +#define UMC_MIB_CNTRL_TX_CNT_RST BIT(2) +#define UMC_RX_MAX_PKT_SZ 0x608 +#define UMC_MPD_CTRL 0x620 +#define UMC_MPD_CTRL_MPD_EN BIT(0) +#define UMC_MPD_CTRL_PSW_EN BIT(27) +#define UMC_PSW_MS 0x624 +#define UMC_PSW_LS 0x628 + +#define UMAC2FB_OFFSET_2_1 0x9f044 +#define UMAC2FB_OFFSET 0x9f03c +#define UMAC2FB_CFG 0x0 +#define UMAC2FB_CFG_OPUT_EN BIT(0) +#define UMAC2FB_CFG_VLAN_EN BIT(1) +#define UMAC2FB_CFG_SNAP_EN BIT(2) +#define UMAC2FB_CFG_BCM_TG_EN BIT(3) +#define UMAC2FB_CFG_IPUT_EN BIT(4) +#define UMAC2FB_CFG_CHID_SHIFT 8 +#define UMAC2FB_CFG_OK_SEND_SHIFT 24 +#define UMAC2FB_CFG_DEFAULT_EN \ + (UMAC2FB_CFG_OPUT_EN | UMAC2FB_CFG_VLAN_EN \ + | UMAC2FB_CFG_SNAP_EN | UMAC2FB_CFG_IPUT_EN) + +#define RGMII_OFFSET(intf) \ + ((((intf)->port) * 0x100) + 0xd000) +#define RGMII_EPHY_CNTRL 0x00 +#define RGMII_EPHY_CFG_IDDQ_BIAS BIT(0) +#define RGMII_EPHY_CFG_EXT_PWRDOWN BIT(1) +#define RGMII_EPHY_CFG_FORCE_DLL_EN BIT(2) +#define RGMII_EPHY_CFG_IDDQ_GLOBAL BIT(3) +#define RGMII_EPHY_CK25_DIS BIT(4) +#define RGMII_EPHY_RESET BIT(7) +#define RGMII_OOB_CNTRL 0x0c +#define RGMII_LINK BIT(4) +#define RGMII_OOB_DIS BIT(5) +#define RGMII_MODE_EN BIT(6) +#define RGMII_ID_MODE_DIS BIT(16) + +#define RGMII_PORT_CNTRL 0x60 +#define RGMII_PORT_MODE_EPHY 0 +#define RGMII_PORT_MODE_GPHY 1 +#define RGMII_PORT_MODE_EXT_EPHY 2 +#define RGMII_PORT_MODE_EXT_GPHY 3 +#define RGMII_PORT_MODE_EXT_RVMII 4 +#define RGMII_PORT_MODE_MASK GENMASK(2, 0) + +#define RGMII_SYS_LED_CNTRL 0x74 +#define RGMII_SYS_LED_CNTRL_LINK_OVRD BIT(15) + +#define TX_SPB_DMA_OFFSET(intf) \ + ((((intf)->channel) * 0x30) + 0x48180) +#define TX_SPB_DMA_READ 0x00 +#define TX_SPB_DMA_BASE 0x08 +#define TX_SPB_DMA_END 0x10 +#define TX_SPB_DMA_VALID 0x18 +#define TX_SPB_DMA_FIFO_CTRL 0x20 +#define TX_SPB_DMA_FIFO_FLUSH BIT(0) +#define TX_SPB_DMA_FIFO_STATUS 0x24 + +#define TX_SPB_CTRL_OFFSET(intf) \ + ((((intf)->channel) * 0x68) + 0x49340) +#define TX_SPB_CTRL_ENABLE 0x0 +#define TX_SPB_CTRL_ENABLE_EN BIT(0) +#define TX_SPB_CTRL_XF_CTRL2 0x20 +#define TX_SPB_CTRL_XF_BID_SHIFT 16 + +#define TX_SPB_TOP_OFFSET(intf) \ + ((((intf)->channel) * 0x1c) + 0x4a0e0) +#define TX_SPB_TOP_BLKOUT 0x0 +#define TX_SPB_TOP_SPRE_BW_CTRL 0x4 + +#define TX_EPKT_C_OFFSET(intf) \ + ((((intf)->channel) * 0x120) + 0x40900) +#define TX_EPKT_C_CFG_MISC 0x0 +#define TX_EPKT_C_CFG_MISC_EN BIT(0) +#define TX_EPKT_C_CFG_MISC_PT BIT(1) +#define TX_EPKT_C_CFG_MISC_PS_SHIFT 14 +#define TX_EPKT_C_CFG_MISC_FD_SHIFT 20 + +#define TX_PAUSE_CTRL_OFFSET(intf) \ + ((((intf)->channel * 0xc) + 0x49a20)) +#define TX_PAUSE_MAP_VECTOR 0x8 + +#define RX_EDPKT_DMA_OFFSET(intf) \ + ((((intf)->channel) * 0x38) + 0x9ca00) +#define RX_EDPKT_DMA_WRITE 0x00 +#define RX_EDPKT_DMA_READ 0x08 +#define RX_EDPKT_DMA_BASE 0x10 +#define RX_EDPKT_DMA_END 0x18 +#define RX_EDPKT_DMA_VALID 0x20 +#define RX_EDPKT_DMA_FULLNESS 0x28 +#define RX_EDPKT_DMA_MIN_THRES 0x2c +#define RX_EDPKT_DMA_CH_XONOFF 0x30 + +#define RX_EDPKT_CFG_OFFSET(intf) \ + ((((intf)->channel) * 0x70) + 0x9c600) +#define RX_EDPKT_CFG_CFG0 0x0 +#define RX_EDPKT_CFG_CFG0_DBUF_SHIFT 9 +#define RX_EDPKT_CFG_CFG0_RBUF 0x0 +#define RX_EDPKT_CFG_CFG0_RBUF_4K 0x1 +#define RX_EDPKT_CFG_CFG0_BUF_4K 0x2 +/* EFRM STUFF, 0 = no byte stuff, 1 = two byte stuff */ +#define RX_EDPKT_CFG_CFG0_EFRM_STUF BIT(11) +#define RX_EDPKT_CFG_CFG0_BALN_SHIFT 12 +#define RX_EDPKT_CFG_CFG0_NO_ALN 0 +#define RX_EDPKT_CFG_CFG0_4_ALN 2 +#define RX_EDPKT_CFG_CFG0_64_ALN 6 +#define RX_EDPKT_RING_BUFFER_WRITE 0x38 +#define RX_EDPKT_RING_BUFFER_READ 0x40 +#define RX_EDPKT_RING_BUFFER_BASE 0x48 +#define RX_EDPKT_RING_BUFFER_END 0x50 +#define RX_EDPKT_RING_BUFFER_VALID 0x58 +#define RX_EDPKT_CFG_ENABLE 0x6c +#define RX_EDPKT_CFG_ENABLE_EN BIT(0) + +#define RX_SPB_DMA_OFFSET(intf) \ + ((((intf)->channel) * 0x30) + 0xa0000) +#define RX_SPB_DMA_READ 0x00 +#define RX_SPB_DMA_BASE 0x08 +#define RX_SPB_DMA_END 0x10 +#define RX_SPB_DMA_VALID 0x18 +#define RX_SPB_DMA_FIFO_CTRL 0x20 +#define RX_SPB_DMA_FIFO_FLUSH BIT(0) +#define RX_SPB_DMA_FIFO_STATUS 0x24 + +#define RX_SPB_CTRL_OFFSET(intf) \ + ((((intf)->channel - 6) * 0x68) + 0xa1000) +#define RX_SPB_CTRL_ENABLE 0x00 +#define RX_SPB_CTRL_ENABLE_EN BIT(0) + +#define RX_PAUSE_CTRL_OFFSET(intf) \ + ((((intf)->channel - 6) * 0x4) + 0xa1138) +#define RX_PAUSE_MAP_VECTOR 0x00 + +#define RX_SPB_TOP_CTRL_OFFSET(intf) \ + ((((intf)->channel - 6) * 0x14) + 0xa2000) +#define RX_SPB_TOP_BLKOUT 0x00 + +#define NUM_4K_BUFFERS 32 +#define RING_BUFFER_SIZE (PAGE_SIZE * NUM_4K_BUFFERS) + +#define DESC_RING_COUNT (64 * NUM_4K_BUFFERS) +#define DESC_SIZE 16 +#define DESC_RING_SIZE (DESC_RING_COUNT * DESC_SIZE) + +#endif -- cgit From a2f0751206b03374f6d02f89c18a60f1bb238fea Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:18:59 -0700 Subject: net: bcmasp: Add support for WoL magic packet Add support for Wake-On-Lan magic packet and magic packet with password. Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 144 +++++++++++++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp.h | 18 +++ .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 36 ++++++ drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 76 +++++++++-- 4 files changed, 262 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 83494641b545..894c14dca911 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -436,6 +436,135 @@ void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en) spin_unlock_irqrestore(&priv->clk_lock, flags); } +static irqreturn_t bcmasp_isr_wol(int irq, void *data) +{ + struct bcmasp_priv *priv = data; + u32 status; + + /* No L3 IRQ, so we good */ + if (priv->wol_irq <= 0) + goto irq_handled; + + status = wakeup_intr2_core_rl(priv, ASP_WAKEUP_INTR2_STATUS) & + ~wakeup_intr2_core_rl(priv, ASP_WAKEUP_INTR2_MASK_STATUS); + wakeup_intr2_core_wl(priv, status, ASP_WAKEUP_INTR2_CLEAR); + +irq_handled: + pm_wakeup_event(&priv->pdev->dev, 0); + return IRQ_HANDLED; +} + +static int bcmasp_get_and_request_irq(struct bcmasp_priv *priv, int i) +{ + struct platform_device *pdev = priv->pdev; + int irq, ret; + + irq = platform_get_irq_optional(pdev, i); + if (irq < 0) + return irq; + + ret = devm_request_irq(&pdev->dev, irq, bcmasp_isr_wol, 0, + pdev->name, priv); + if (ret) + return ret; + + return irq; +} + +static void bcmasp_init_wol_shared(struct bcmasp_priv *priv) +{ + struct platform_device *pdev = priv->pdev; + struct device *dev = &pdev->dev; + int irq; + + irq = bcmasp_get_and_request_irq(priv, 1); + if (irq < 0) { + dev_warn(dev, "Failed to init WoL irq: %d\n", irq); + return; + } + + priv->wol_irq = irq; + priv->wol_irq_enabled_mask = 0; + device_set_wakeup_capable(&pdev->dev, 1); +} + +static void bcmasp_enable_wol_shared(struct bcmasp_intf *intf, bool en) +{ + struct bcmasp_priv *priv = intf->parent; + struct device *dev = &priv->pdev->dev; + + if (en) { + if (priv->wol_irq_enabled_mask) { + set_bit(intf->port, &priv->wol_irq_enabled_mask); + return; + } + + /* First enable */ + set_bit(intf->port, &priv->wol_irq_enabled_mask); + enable_irq_wake(priv->wol_irq); + device_set_wakeup_enable(dev, 1); + } else { + if (!priv->wol_irq_enabled_mask) + return; + + clear_bit(intf->port, &priv->wol_irq_enabled_mask); + if (priv->wol_irq_enabled_mask) + return; + + /* Last disable */ + disable_irq_wake(priv->wol_irq); + device_set_wakeup_enable(dev, 0); + } +} + +static void bcmasp_wol_irq_destroy_shared(struct bcmasp_priv *priv) +{ + if (priv->wol_irq > 0) + free_irq(priv->wol_irq, priv); +} + +static void bcmasp_init_wol_per_intf(struct bcmasp_priv *priv) +{ + struct platform_device *pdev = priv->pdev; + struct device *dev = &pdev->dev; + struct bcmasp_intf *intf; + int irq; + + list_for_each_entry(intf, &priv->intfs, list) { + irq = bcmasp_get_and_request_irq(priv, intf->port + 1); + if (irq < 0) { + dev_warn(dev, "Failed to init WoL irq(port %d): %d\n", + intf->port, irq); + continue; + } + + intf->wol_irq = irq; + intf->wol_irq_enabled = false; + device_set_wakeup_capable(&pdev->dev, 1); + } +} + +static void bcmasp_enable_wol_per_intf(struct bcmasp_intf *intf, bool en) +{ + struct device *dev = &intf->parent->pdev->dev; + + if (en ^ intf->wol_irq_enabled) + irq_set_irq_wake(intf->wol_irq, en); + + intf->wol_irq_enabled = en; + device_set_wakeup_enable(dev, en); +} + +static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv) +{ + struct bcmasp_intf *intf; + + list_for_each_entry(intf, &priv->intfs, list) { + if (intf->wol_irq > 0) + free_irq(intf->wol_irq, priv); + } +} + static struct bcmasp_hw_info v20_hw_info = { .rx_ctrl_flush = ASP_RX_CTRL_FLUSH, .umac2fb = UMAC2FB_OFFSET, @@ -445,6 +574,9 @@ static struct bcmasp_hw_info v20_hw_info = { }; static const struct bcmasp_plat_data v20_plat_data = { + .init_wol = bcmasp_init_wol_per_intf, + .enable_wol = bcmasp_enable_wol_per_intf, + .destroy_wol = bcmasp_wol_irq_destroy_per_intf, .hw_info = &v20_hw_info, }; @@ -458,6 +590,9 @@ static struct bcmasp_hw_info v21_hw_info = { }; static const struct bcmasp_plat_data v21_plat_data = { + .init_wol = bcmasp_init_wol_shared, + .enable_wol = bcmasp_enable_wol_shared, + .destroy_wol = bcmasp_wol_irq_destroy_shared, .hw_info = &v21_hw_info, }; @@ -521,12 +656,16 @@ static int bcmasp_probe(struct platform_device *pdev) priv->pdev = pdev; spin_lock_init(&priv->mda_lock); spin_lock_init(&priv->clk_lock); + mutex_init(&priv->wol_lock); INIT_LIST_HEAD(&priv->intfs); pdata = device_get_match_data(&pdev->dev); if (!pdata) return dev_err_probe(dev, -EINVAL, "unable to find platform data\n"); + priv->init_wol = pdata->init_wol; + priv->enable_wol = pdata->enable_wol; + priv->destroy_wol = pdata->destroy_wol; priv->hw_info = pdata->hw_info; /* Enable all clocks to ensure successful probing */ @@ -570,6 +709,9 @@ static int bcmasp_probe(struct platform_device *pdev) i++; } + /* Check and enable WoL */ + priv->init_wol(priv); + /* Drop the clock reference count now and let ndo_open()/ndo_close() * manage it for us from now on. */ @@ -585,6 +727,7 @@ static int bcmasp_probe(struct platform_device *pdev) if (ret) { netdev_err(intf->ndev, "failed to register net_device: %d\n", ret); + priv->destroy_wol(priv); bcmasp_remove_intfs(priv); goto of_put_exit; } @@ -605,6 +748,7 @@ static int bcmasp_remove(struct platform_device *pdev) if (!priv) return 0; + priv->destroy_wol(priv); bcmasp_remove_intfs(priv); return 0; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index 4fe84d26251d..2cdf22732f4c 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -301,6 +301,12 @@ struct bcmasp_intf { /* Statistics */ struct bcmasp_intf_stats64 stats64; + + u32 wolopts; + u8 sopass[SOPASS_MAX]; + /* Used if per intf wol irq */ + int wol_irq; + unsigned int wol_irq_enabled:1; }; #define NUM_MDA_FILTERS 32 @@ -321,6 +327,9 @@ struct bcmasp_hw_info { }; struct bcmasp_plat_data { + void (*init_wol)(struct bcmasp_priv *priv); + void (*enable_wol)(struct bcmasp_intf *intf, bool en); + void (*destroy_wol)(struct bcmasp_priv *priv); struct bcmasp_hw_info *hw_info; }; @@ -331,6 +340,15 @@ struct bcmasp_priv { int irq; u32 irq_mask; + /* Used if shared wol irq */ + struct mutex wol_lock; + int wol_irq; + unsigned long wol_irq_enabled_mask; + + void (*init_wol)(struct bcmasp_priv *priv); + void (*enable_wol)(struct bcmasp_intf *intf, bool en); + void (*destroy_wol)(struct bcmasp_priv *priv); + void __iomem *base; struct bcmasp_hw_info *hw_info; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index 394c0e1cb026..ae24a1f74d49 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -30,6 +30,40 @@ static void bcmasp_set_msglevel(struct net_device *dev, u32 level) intf->msg_enable = level; } +#define BCMASP_SUPPORTED_WAKE (WAKE_MAGIC | WAKE_MAGICSECURE) +static void bcmasp_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + wol->supported = BCMASP_SUPPORTED_WAKE; + wol->wolopts = intf->wolopts; + memset(wol->sopass, 0, sizeof(wol->sopass)); + + if (wol->wolopts & WAKE_MAGICSECURE) + memcpy(wol->sopass, intf->sopass, sizeof(intf->sopass)); +} + +static int bcmasp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct bcmasp_priv *priv = intf->parent; + struct device *kdev = &priv->pdev->dev; + + if (!device_can_wakeup(kdev)) + return -EOPNOTSUPP; + + /* Interface Specific */ + intf->wolopts = wol->wolopts; + if (intf->wolopts & WAKE_MAGICSECURE) + memcpy(intf->sopass, wol->sopass, sizeof(wol->sopass)); + + mutex_lock(&priv->wol_lock); + priv->enable_wol(intf, !!intf->wolopts); + mutex_unlock(&priv->wol_lock); + + return 0; +} + const struct ethtool_ops bcmasp_ethtool_ops = { .get_drvinfo = bcmasp_get_drvinfo, .get_link = ethtool_op_get_link, @@ -37,4 +71,6 @@ const struct ethtool_ops bcmasp_ethtool_ops = { .set_link_ksettings = phy_ethtool_set_link_ksettings, .get_msglevel = bcmasp_get_msglevel, .set_msglevel = bcmasp_set_msglevel, + .get_wol = bcmasp_get_wol, + .set_wol = bcmasp_set_wol, }; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index 0232f5cf8909..21a8d15a47d8 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -1034,7 +1034,7 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) netdev_err(dev, "could not attach to PHY\n"); goto err_phy_disable; } - } else { + } else if (!intf->wolopts) { ret = phy_resume(dev->phydev); if (ret) goto err_phy_disable; @@ -1281,8 +1281,39 @@ void bcmasp_interface_destroy(struct bcmasp_intf *intf) free_netdev(intf->ndev); } +static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf) +{ + struct net_device *ndev = intf->ndev; + u32 reg; + + reg = umac_rl(intf, UMC_MPD_CTRL); + if (intf->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) + reg |= UMC_MPD_CTRL_MPD_EN; + reg &= ~UMC_MPD_CTRL_PSW_EN; + if (intf->wolopts & WAKE_MAGICSECURE) { + /* Program the SecureOn password */ + umac_wl(intf, get_unaligned_be16(&intf->sopass[0]), + UMC_PSW_MS); + umac_wl(intf, get_unaligned_be32(&intf->sopass[2]), + UMC_PSW_LS); + reg |= UMC_MPD_CTRL_PSW_EN; + } + umac_wl(intf, reg, UMC_MPD_CTRL); + + /* UniMAC receive needs to be turned on */ + umac_enable_set(intf, UMC_CMD_RX_EN, 1); + + if (intf->parent->wol_irq > 0) { + wakeup_intr2_core_wl(intf->parent, 0xffffffff, + ASP_WAKEUP_INTR2_MASK_CLEAR); + } + + netif_dbg(intf, wol, ndev, "entered WOL mode\n"); +} + int bcmasp_interface_suspend(struct bcmasp_intf *intf) { + struct device *kdev = &intf->parent->pdev->dev; struct net_device *dev = intf->ndev; int ret = 0; @@ -1293,19 +1324,24 @@ int bcmasp_interface_suspend(struct bcmasp_intf *intf) bcmasp_netif_deinit(dev); - ret = phy_suspend(dev->phydev); - if (ret) - goto out; + if (!intf->wolopts) { + ret = phy_suspend(dev->phydev); + if (ret) + goto out; - if (intf->internal_phy) - bcmasp_ephy_enable_set(intf, false); - else - bcmasp_rgmii_mode_en_set(intf, false); + if (intf->internal_phy) + bcmasp_ephy_enable_set(intf, false); + else + bcmasp_rgmii_mode_en_set(intf, false); - /* If Wake-on-LAN is disabled, we can safely - * disable the network interface clocks. - */ - bcmasp_core_clock_set_intf(intf, false); + /* If Wake-on-LAN is disabled, we can safely + * disable the network interface clocks. + */ + bcmasp_core_clock_set_intf(intf, false); + } + + if (device_may_wakeup(kdev) && intf->wolopts) + bcmasp_suspend_to_wol(intf); clk_disable_unprepare(intf->parent->clk); @@ -1316,6 +1352,20 @@ out: return ret; } +static void bcmasp_resume_from_wol(struct bcmasp_intf *intf) +{ + u32 reg; + + reg = umac_rl(intf, UMC_MPD_CTRL); + reg &= ~UMC_MPD_CTRL_MPD_EN; + umac_wl(intf, reg, UMC_MPD_CTRL); + + if (intf->parent->wol_irq > 0) { + wakeup_intr2_core_wl(intf->parent, 0xffffffff, + ASP_WAKEUP_INTR2_MASK_SET); + } +} + int bcmasp_interface_resume(struct bcmasp_intf *intf) { struct net_device *dev = intf->ndev; @@ -1332,6 +1382,8 @@ int bcmasp_interface_resume(struct bcmasp_intf *intf) if (ret) goto out; + bcmasp_resume_from_wol(intf); + netif_device_attach(dev); return 0; -- cgit From c5d511c4958780338ac93f3e728012d5e17de710 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:19:00 -0700 Subject: net: bcmasp: Add support for wake on net filters Add support for wake on network filters. The max match is 256 bytes. Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 595 +++++++++++++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp.h | 40 ++ .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 131 ++++- drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 3 + 4 files changed, 768 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 894c14dca911..92dfea961add 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -127,6 +127,597 @@ void bcmasp_flush_rx_port(struct bcmasp_intf *intf) rx_ctrl_core_wl(priv, mask, priv->hw_info->rx_ctrl_flush); } +static void bcmasp_netfilt_hw_en_wake(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt) +{ + rx_filter_core_wl(priv, ASP_RX_FILTER_NET_OFFSET_L3_1(64), + ASP_RX_FILTER_NET_OFFSET(nfilt->hw_index)); + + rx_filter_core_wl(priv, ASP_RX_FILTER_NET_OFFSET_L2(32) | + ASP_RX_FILTER_NET_OFFSET_L3_0(32) | + ASP_RX_FILTER_NET_OFFSET_L3_1(96) | + ASP_RX_FILTER_NET_OFFSET_L4(32), + ASP_RX_FILTER_NET_OFFSET(nfilt->hw_index + 1)); + + rx_filter_core_wl(priv, ASP_RX_FILTER_NET_CFG_CH(nfilt->port + 8) | + ASP_RX_FILTER_NET_CFG_EN | + ASP_RX_FILTER_NET_CFG_L2_EN | + ASP_RX_FILTER_NET_CFG_L3_EN | + ASP_RX_FILTER_NET_CFG_L4_EN | + ASP_RX_FILTER_NET_CFG_L3_FRM(2) | + ASP_RX_FILTER_NET_CFG_L4_FRM(2) | + ASP_RX_FILTER_NET_CFG_UMC(nfilt->port), + ASP_RX_FILTER_NET_CFG(nfilt->hw_index)); + + rx_filter_core_wl(priv, ASP_RX_FILTER_NET_CFG_CH(nfilt->port + 8) | + ASP_RX_FILTER_NET_CFG_EN | + ASP_RX_FILTER_NET_CFG_L2_EN | + ASP_RX_FILTER_NET_CFG_L3_EN | + ASP_RX_FILTER_NET_CFG_L4_EN | + ASP_RX_FILTER_NET_CFG_L3_FRM(2) | + ASP_RX_FILTER_NET_CFG_L4_FRM(2) | + ASP_RX_FILTER_NET_CFG_UMC(nfilt->port), + ASP_RX_FILTER_NET_CFG(nfilt->hw_index + 1)); +} + +#define MAX_WAKE_FILTER_SIZE 256 +enum asp_netfilt_reg_type { + ASP_NETFILT_MATCH = 0, + ASP_NETFILT_MASK, + ASP_NETFILT_MAX +}; + +static int bcmasp_netfilt_get_reg_offset(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + enum asp_netfilt_reg_type reg_type, + u32 offset) +{ + u32 block_index, filter_sel; + + if (offset < 32) { + block_index = ASP_RX_FILTER_NET_L2; + filter_sel = nfilt->hw_index; + } else if (offset < 64) { + block_index = ASP_RX_FILTER_NET_L2; + filter_sel = nfilt->hw_index + 1; + } else if (offset < 96) { + block_index = ASP_RX_FILTER_NET_L3_0; + filter_sel = nfilt->hw_index; + } else if (offset < 128) { + block_index = ASP_RX_FILTER_NET_L3_0; + filter_sel = nfilt->hw_index + 1; + } else if (offset < 160) { + block_index = ASP_RX_FILTER_NET_L3_1; + filter_sel = nfilt->hw_index; + } else if (offset < 192) { + block_index = ASP_RX_FILTER_NET_L3_1; + filter_sel = nfilt->hw_index + 1; + } else if (offset < 224) { + block_index = ASP_RX_FILTER_NET_L4; + filter_sel = nfilt->hw_index; + } else if (offset < 256) { + block_index = ASP_RX_FILTER_NET_L4; + filter_sel = nfilt->hw_index + 1; + } else { + return -EINVAL; + } + + switch (reg_type) { + case ASP_NETFILT_MATCH: + return ASP_RX_FILTER_NET_PAT(filter_sel, block_index, + (offset % 32)); + case ASP_NETFILT_MASK: + return ASP_RX_FILTER_NET_MASK(filter_sel, block_index, + (offset % 32)); + default: + return -EINVAL; + } +} + +static void bcmasp_netfilt_wr(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + enum asp_netfilt_reg_type reg_type, + u32 val, u32 offset) +{ + int reg_offset; + + /* HW only accepts 4 byte aligned writes */ + if (!IS_ALIGNED(offset, 4) || offset > MAX_WAKE_FILTER_SIZE) + return; + + reg_offset = bcmasp_netfilt_get_reg_offset(priv, nfilt, reg_type, + offset); + + rx_filter_core_wl(priv, val, reg_offset); +} + +static u32 bcmasp_netfilt_rd(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + enum asp_netfilt_reg_type reg_type, + u32 offset) +{ + int reg_offset; + + /* HW only accepts 4 byte aligned writes */ + if (!IS_ALIGNED(offset, 4) || offset > MAX_WAKE_FILTER_SIZE) + return 0; + + reg_offset = bcmasp_netfilt_get_reg_offset(priv, nfilt, reg_type, + offset); + + return rx_filter_core_rl(priv, reg_offset); +} + +static int bcmasp_netfilt_wr_m_wake(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + u32 offset, void *match, void *mask, + size_t size) +{ + u32 shift, mask_val = 0, match_val = 0; + bool first_byte = true; + + if ((offset + size) > MAX_WAKE_FILTER_SIZE) + return -EINVAL; + + while (size--) { + /* The HW only accepts 4 byte aligned writes, so if we + * begin unaligned or if remaining bytes less than 4, + * we need to read then write to avoid losing current + * register state + */ + if (first_byte && (!IS_ALIGNED(offset, 4) || size < 3)) { + match_val = bcmasp_netfilt_rd(priv, nfilt, + ASP_NETFILT_MATCH, + ALIGN_DOWN(offset, 4)); + mask_val = bcmasp_netfilt_rd(priv, nfilt, + ASP_NETFILT_MASK, + ALIGN_DOWN(offset, 4)); + } + + shift = (3 - (offset % 4)) * 8; + match_val &= ~GENMASK(shift + 7, shift); + mask_val &= ~GENMASK(shift + 7, shift); + match_val |= (u32)(*((u8 *)match) << shift); + mask_val |= (u32)(*((u8 *)mask) << shift); + + /* If last byte or last byte of word, write to reg */ + if (!size || ((offset % 4) == 3)) { + bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MATCH, + match_val, ALIGN_DOWN(offset, 4)); + bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MASK, + mask_val, ALIGN_DOWN(offset, 4)); + first_byte = true; + } else { + first_byte = false; + } + + offset++; + match++; + mask++; + } + + return 0; +} + +static void bcmasp_netfilt_reset_hw(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt) +{ + int i; + + for (i = 0; i < MAX_WAKE_FILTER_SIZE; i += 4) { + bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MATCH, 0, i); + bcmasp_netfilt_wr(priv, nfilt, ASP_NETFILT_MASK, 0, i); + } +} + +static void bcmasp_netfilt_tcpip4_wr(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + struct ethtool_tcpip4_spec *match, + struct ethtool_tcpip4_spec *mask, + u32 offset) +{ + __be16 val_16, mask_16; + + val_16 = htons(ETH_P_IP); + mask_16 = htons(0xFFFF); + bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset, + &val_16, &mask_16, sizeof(val_16)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 1, + &match->tos, &mask->tos, + sizeof(match->tos)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 12, + &match->ip4src, &mask->ip4src, + sizeof(match->ip4src)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 16, + &match->ip4dst, &mask->ip4dst, + sizeof(match->ip4dst)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 20, + &match->psrc, &mask->psrc, + sizeof(match->psrc)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 22, + &match->pdst, &mask->pdst, + sizeof(match->pdst)); +} + +static void bcmasp_netfilt_tcpip6_wr(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt, + struct ethtool_tcpip6_spec *match, + struct ethtool_tcpip6_spec *mask, + u32 offset) +{ + __be16 val_16, mask_16; + + val_16 = htons(ETH_P_IPV6); + mask_16 = htons(0xFFFF); + bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset, + &val_16, &mask_16, sizeof(val_16)); + val_16 = htons(match->tclass << 4); + mask_16 = htons(mask->tclass << 4); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset, + &val_16, &mask_16, sizeof(val_16)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 8, + &match->ip6src, &mask->ip6src, + sizeof(match->ip6src)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 24, + &match->ip6dst, &mask->ip6dst, + sizeof(match->ip6dst)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 40, + &match->psrc, &mask->psrc, + sizeof(match->psrc)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 42, + &match->pdst, &mask->pdst, + sizeof(match->pdst)); +} + +static int bcmasp_netfilt_wr_to_hw(struct bcmasp_priv *priv, + struct bcmasp_net_filter *nfilt) +{ + struct ethtool_rx_flow_spec *fs = &nfilt->fs; + unsigned int offset = 0; + __be16 val_16, mask_16; + u8 val_8, mask_8; + + /* Currently only supports wake filters */ + if (!nfilt->wake_filter) + return -EINVAL; + + bcmasp_netfilt_reset_hw(priv, nfilt); + + if (fs->flow_type & FLOW_MAC_EXT) { + bcmasp_netfilt_wr_m_wake(priv, nfilt, 0, &fs->h_ext.h_dest, + &fs->m_ext.h_dest, + sizeof(fs->h_ext.h_dest)); + } + + if ((fs->flow_type & FLOW_EXT) && + (fs->m_ext.vlan_etype || fs->m_ext.vlan_tci)) { + bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2), + &fs->h_ext.vlan_etype, + &fs->m_ext.vlan_etype, + sizeof(fs->h_ext.vlan_etype)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ((ETH_ALEN * 2) + 2), + &fs->h_ext.vlan_tci, + &fs->m_ext.vlan_tci, + sizeof(fs->h_ext.vlan_tci)); + offset += VLAN_HLEN; + } + + switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { + case ETHER_FLOW: + bcmasp_netfilt_wr_m_wake(priv, nfilt, 0, + &fs->h_u.ether_spec.h_dest, + &fs->m_u.ether_spec.h_dest, + sizeof(fs->h_u.ether_spec.h_dest)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_ALEN, + &fs->h_u.ether_spec.h_source, + &fs->m_u.ether_spec.h_source, + sizeof(fs->h_u.ether_spec.h_source)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset, + &fs->h_u.ether_spec.h_proto, + &fs->m_u.ether_spec.h_proto, + sizeof(fs->h_u.ether_spec.h_proto)); + + break; + case IP_USER_FLOW: + val_16 = htons(ETH_P_IP); + mask_16 = htons(0xFFFF); + bcmasp_netfilt_wr_m_wake(priv, nfilt, (ETH_ALEN * 2) + offset, + &val_16, &mask_16, sizeof(val_16)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 1, + &fs->h_u.usr_ip4_spec.tos, + &fs->m_u.usr_ip4_spec.tos, + sizeof(fs->h_u.usr_ip4_spec.tos)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9, + &fs->h_u.usr_ip4_spec.proto, + &fs->m_u.usr_ip4_spec.proto, + sizeof(fs->h_u.usr_ip4_spec.proto)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 12, + &fs->h_u.usr_ip4_spec.ip4src, + &fs->m_u.usr_ip4_spec.ip4src, + sizeof(fs->h_u.usr_ip4_spec.ip4src)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 16, + &fs->h_u.usr_ip4_spec.ip4dst, + &fs->m_u.usr_ip4_spec.ip4dst, + sizeof(fs->h_u.usr_ip4_spec.ip4dst)); + if (!fs->m_u.usr_ip4_spec.l4_4_bytes) + break; + + /* Only supports 20 byte IPv4 header */ + val_8 = 0x45; + mask_8 = 0xFF; + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset, + &val_8, &mask_8, sizeof(val_8)); + bcmasp_netfilt_wr_m_wake(priv, nfilt, + ETH_HLEN + 20 + offset, + &fs->h_u.usr_ip4_spec.l4_4_bytes, + &fs->m_u.usr_ip4_spec.l4_4_bytes, + sizeof(fs->h_u.usr_ip4_spec.l4_4_bytes) + ); + break; + case TCP_V4_FLOW: + val_8 = IPPROTO_TCP; + mask_8 = 0xFF; + bcmasp_netfilt_tcpip4_wr(priv, nfilt, &fs->h_u.tcp_ip4_spec, + &fs->m_u.tcp_ip4_spec, offset); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9, + &val_8, &mask_8, sizeof(val_8)); + break; + case UDP_V4_FLOW: + val_8 = IPPROTO_UDP; + mask_8 = 0xFF; + bcmasp_netfilt_tcpip4_wr(priv, nfilt, &fs->h_u.udp_ip4_spec, + &fs->m_u.udp_ip4_spec, offset); + + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 9, + &val_8, &mask_8, sizeof(val_8)); + break; + case TCP_V6_FLOW: + val_8 = IPPROTO_TCP; + mask_8 = 0xFF; + bcmasp_netfilt_tcpip6_wr(priv, nfilt, &fs->h_u.tcp_ip6_spec, + &fs->m_u.tcp_ip6_spec, offset); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 6, + &val_8, &mask_8, sizeof(val_8)); + break; + case UDP_V6_FLOW: + val_8 = IPPROTO_UDP; + mask_8 = 0xFF; + bcmasp_netfilt_tcpip6_wr(priv, nfilt, &fs->h_u.udp_ip6_spec, + &fs->m_u.udp_ip6_spec, offset); + bcmasp_netfilt_wr_m_wake(priv, nfilt, ETH_HLEN + offset + 6, + &val_8, &mask_8, sizeof(val_8)); + break; + } + + bcmasp_netfilt_hw_en_wake(priv, nfilt); + + return 0; +} + +void bcmasp_netfilt_suspend(struct bcmasp_intf *intf) +{ + struct bcmasp_priv *priv = intf->parent; + bool write = false; + int ret, i; + + /* Write all filters to HW */ + for (i = 0; i < NUM_NET_FILTERS; i++) { + /* If the filter does not match the port, skip programming. */ + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; + + if (i > 0 && (i % 2) && + priv->net_filters[i].wake_filter && + priv->net_filters[i - 1].wake_filter) + continue; + + ret = bcmasp_netfilt_wr_to_hw(priv, &priv->net_filters[i]); + if (!ret) + write = true; + } + + /* Successfully programmed at least one wake filter + * so enable top level wake config + */ + if (write) + rx_filter_core_wl(priv, (ASP_RX_FILTER_OPUT_EN | + ASP_RX_FILTER_LNR_MD | + ASP_RX_FILTER_GEN_WK_EN | + ASP_RX_FILTER_NT_FLT_EN), + ASP_RX_FILTER_BLK_CTRL); +} + +void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + u32 *rule_cnt) +{ + struct bcmasp_priv *priv = intf->parent; + int j = 0, i; + + for (i = 0; i < NUM_NET_FILTERS; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; + + if (i > 0 && (i % 2) && + priv->net_filters[i].wake_filter && + priv->net_filters[i - 1].wake_filter) + continue; + + rule_locs[j++] = priv->net_filters[i].fs.location; + } + + *rule_cnt = j; +} + +int bcmasp_netfilt_get_active(struct bcmasp_intf *intf) +{ + struct bcmasp_priv *priv = intf->parent; + int cnt = 0, i; + + for (i = 0; i < NUM_NET_FILTERS; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; + + /* Skip over a wake filter pair */ + if (i > 0 && (i % 2) && + priv->net_filters[i].wake_filter && + priv->net_filters[i - 1].wake_filter) + continue; + + cnt++; + } + + return cnt; +} + +bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf, + struct ethtool_rx_flow_spec *fs) +{ + struct bcmasp_priv *priv = intf->parent; + struct ethtool_rx_flow_spec *cur; + size_t fs_size = 0; + int i; + + for (i = 0; i < NUM_NET_FILTERS; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; + + cur = &priv->net_filters[i].fs; + + if (cur->flow_type != fs->flow_type || + cur->ring_cookie != fs->ring_cookie) + continue; + + switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { + case ETHER_FLOW: + fs_size = sizeof(struct ethhdr); + break; + case IP_USER_FLOW: + fs_size = sizeof(struct ethtool_usrip4_spec); + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + fs_size = sizeof(struct ethtool_tcpip6_spec); + break; + case TCP_V4_FLOW: + case UDP_V4_FLOW: + fs_size = sizeof(struct ethtool_tcpip4_spec); + break; + default: + continue; + } + + if (memcmp(&cur->h_u, &fs->h_u, fs_size) || + memcmp(&cur->m_u, &fs->m_u, fs_size)) + continue; + + if (cur->flow_type & FLOW_EXT) { + if (cur->h_ext.vlan_etype != fs->h_ext.vlan_etype || + cur->m_ext.vlan_etype != fs->m_ext.vlan_etype || + cur->h_ext.vlan_tci != fs->h_ext.vlan_tci || + cur->m_ext.vlan_tci != fs->m_ext.vlan_tci || + cur->h_ext.data[0] != fs->h_ext.data[0]) + continue; + } + if (cur->flow_type & FLOW_MAC_EXT) { + if (memcmp(&cur->h_ext.h_dest, + &fs->h_ext.h_dest, ETH_ALEN) || + memcmp(&cur->m_ext.h_dest, + &fs->m_ext.h_dest, ETH_ALEN)) + continue; + } + + return true; + } + + return false; +} + +/* If no network filter found, return open filter. + * If no more open filters return NULL + */ +struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, + int loc, bool wake_filter, + bool init) +{ + struct bcmasp_net_filter *nfilter = NULL; + struct bcmasp_priv *priv = intf->parent; + int i, open_index = -1; + + /* Check whether we exceed the filter table capacity */ + if (loc != RX_CLS_LOC_ANY && loc >= NUM_NET_FILTERS) + return ERR_PTR(-EINVAL); + + /* If the filter location is busy (already claimed) and we are initializing + * the filter (insertion), return a busy error code. + */ + if (loc != RX_CLS_LOC_ANY && init && priv->net_filters[loc].claimed) + return ERR_PTR(-EBUSY); + + /* We need two filters for wake-up, so we cannot use an odd filter */ + if (wake_filter && loc != RX_CLS_LOC_ANY && (loc % 2)) + return ERR_PTR(-EINVAL); + + /* Initialize the loop index based on the desired location or from 0 */ + i = loc == RX_CLS_LOC_ANY ? 0 : loc; + + for ( ; i < NUM_NET_FILTERS; i++) { + /* Found matching network filter */ + if (!init && + priv->net_filters[i].claimed && + priv->net_filters[i].hw_index == i && + priv->net_filters[i].port == intf->port) + return &priv->net_filters[i]; + + /* If we don't need a new filter or new filter already found */ + if (!init || open_index >= 0) + continue; + + /* Wake filter conslidates two filters to cover more bytes + * Wake filter is open if... + * 1. It is an even filter + * 2. The current and next filter is not claimed + */ + if (wake_filter && !(i % 2) && !priv->net_filters[i].claimed && + !priv->net_filters[i + 1].claimed) + open_index = i; + else if (!priv->net_filters[i].claimed) + open_index = i; + } + + if (open_index >= 0) { + nfilter = &priv->net_filters[open_index]; + nfilter->claimed = true; + nfilter->port = intf->port; + nfilter->hw_index = open_index; + } + + if (wake_filter && open_index >= 0) { + /* Claim next filter */ + priv->net_filters[open_index + 1].claimed = true; + priv->net_filters[open_index + 1].wake_filter = true; + nfilter->wake_filter = true; + } + + return nfilter ? nfilter : ERR_PTR(-EINVAL); +} + +void bcmasp_netfilt_release(struct bcmasp_intf *intf, + struct bcmasp_net_filter *nfilt) +{ + struct bcmasp_priv *priv = intf->parent; + + if (nfilt->wake_filter) { + memset(&priv->net_filters[nfilt->hw_index + 1], 0, + sizeof(struct bcmasp_net_filter)); + } + + memset(nfilt, 0, sizeof(struct bcmasp_net_filter)); +} + static void bcmasp_addr_to_uint(unsigned char *addr, u32 *high, u32 *low) { *high = (u32)(addr[0] << 8 | addr[1]); @@ -334,6 +925,9 @@ static void bcmasp_core_init_filters(struct bcmasp_priv *priv) priv->mda_filters[i].en = 0; } + for (i = 0; i < NUM_NET_FILTERS; i++) + rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_NET_CFG(i)); + /* Top level filter enable bit should be enabled at all times, set * GEN_WAKE_CLEAR to clear the network filter wake-up which would * otherwise be sticky @@ -657,6 +1251,7 @@ static int bcmasp_probe(struct platform_device *pdev) spin_lock_init(&priv->mda_lock); spin_lock_init(&priv->clk_lock); mutex_init(&priv->wol_lock); + mutex_init(&priv->net_lock); INIT_LIST_HEAD(&priv->intfs); pdata = device_get_match_data(&pdev->dev); diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index 2cdf22732f4c..fbbde04a0eab 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -106,6 +106,14 @@ #define ASP_RX_FILTER_NET_OFFSET_L3_1(val) ((val) << 16) #define ASP_RX_FILTER_NET_OFFSET_L4(val) ((val) << 24) +enum asp_rx_net_filter_block { + ASP_RX_FILTER_NET_L2 = 0, + ASP_RX_FILTER_NET_L3_0, + ASP_RX_FILTER_NET_L3_1, + ASP_RX_FILTER_NET_L4, + ASP_RX_FILTER_NET_BLOCK_MAX +}; + #define ASP_EDPKT_OFFSET 0x9c000 #define ASP_EDPKT_ENABLE 0x4 #define ASP_EDPKT_ENABLE_EN BIT(0) @@ -309,6 +317,17 @@ struct bcmasp_intf { unsigned int wol_irq_enabled:1; }; +#define NUM_NET_FILTERS 32 +struct bcmasp_net_filter { + struct ethtool_rx_flow_spec fs; + + bool claimed; + bool wake_filter; + + int port; + unsigned int hw_index; +}; + #define NUM_MDA_FILTERS 32 struct bcmasp_mda_filter { /* Current owner of this filter */ @@ -361,6 +380,11 @@ struct bcmasp_priv { /* Protects accesses to ASP_CTRL_CLOCK_CTRL */ spinlock_t clk_lock; + + struct bcmasp_net_filter net_filters[NUM_NET_FILTERS]; + + /* Network filter lock */ + struct mutex net_lock; }; static inline unsigned long bcmasp_intf_rx_desc_read(struct bcmasp_intf *intf) @@ -518,4 +542,20 @@ void bcmasp_disable_all_filters(struct bcmasp_intf *intf); void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en); +struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, + int loc, bool wake_filter, + bool init); + +bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf, + struct ethtool_rx_flow_spec *fs); + +void bcmasp_netfilt_release(struct bcmasp_intf *intf, + struct bcmasp_net_filter *nfilt); + +int bcmasp_netfilt_get_active(struct bcmasp_intf *intf); + +void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + u32 *rule_cnt); + +void bcmasp_netfilt_suspend(struct bcmasp_intf *intf); #endif diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index ae24a1f74d49..eddd1c43f00e 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -30,7 +30,7 @@ static void bcmasp_set_msglevel(struct net_device *dev, u32 level) intf->msg_enable = level; } -#define BCMASP_SUPPORTED_WAKE (WAKE_MAGIC | WAKE_MAGICSECURE) +#define BCMASP_SUPPORTED_WAKE (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER) static void bcmasp_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bcmasp_intf *intf = netdev_priv(dev); @@ -64,6 +64,133 @@ static int bcmasp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } +static int bcmasp_flow_insert(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct bcmasp_net_filter *nfilter; + u32 loc = cmd->fs.location; + bool wake = false; + + if (cmd->fs.ring_cookie == RX_CLS_FLOW_WAKE) + wake = true; + + /* Currently only supports WAKE filters */ + if (!wake) + return -EOPNOTSUPP; + + switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { + case ETHER_FLOW: + case IP_USER_FLOW: + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case TCP_V6_FLOW: + case UDP_V6_FLOW: + break; + default: + return -EOPNOTSUPP; + } + + /* Check if filter already exists */ + if (bcmasp_netfilt_check_dup(intf, &cmd->fs)) + return -EINVAL; + + nfilter = bcmasp_netfilt_get_init(intf, loc, wake, true); + if (IS_ERR(nfilter)) + return PTR_ERR(nfilter); + + /* Return the location where we did insert the filter */ + cmd->fs.location = nfilter->hw_index; + memcpy(&nfilter->fs, &cmd->fs, sizeof(struct ethtool_rx_flow_spec)); + + /* Since we only support wake filters, defer register programming till + * suspend time. + */ + return 0; +} + +static int bcmasp_flow_delete(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct bcmasp_net_filter *nfilter; + + nfilter = bcmasp_netfilt_get_init(intf, cmd->fs.location, false, false); + if (IS_ERR(nfilter)) + return PTR_ERR(nfilter); + + bcmasp_netfilt_release(intf, nfilter); + + return 0; +} + +static int bcmasp_flow_get(struct bcmasp_intf *intf, struct ethtool_rxnfc *cmd) +{ + struct bcmasp_net_filter *nfilter; + + nfilter = bcmasp_netfilt_get_init(intf, cmd->fs.location, false, false); + if (IS_ERR(nfilter)) + return PTR_ERR(nfilter); + + memcpy(&cmd->fs, &nfilter->fs, sizeof(nfilter->fs)); + + cmd->data = NUM_NET_FILTERS; + + return 0; +} + +static int bcmasp_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + mutex_lock(&intf->parent->net_lock); + + switch (cmd->cmd) { + case ETHTOOL_SRXCLSRLINS: + ret = bcmasp_flow_insert(dev, cmd); + break; + case ETHTOOL_SRXCLSRLDEL: + ret = bcmasp_flow_delete(dev, cmd); + break; + default: + break; + } + + mutex_unlock(&intf->parent->net_lock); + + return ret; +} + +static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + int err = 0; + + mutex_lock(&intf->parent->net_lock); + + switch (cmd->cmd) { + case ETHTOOL_GRXCLSRLCNT: + cmd->rule_cnt = bcmasp_netfilt_get_active(intf); + /* We support specifying rule locations */ + cmd->data |= RX_CLS_LOC_SPECIAL; + break; + case ETHTOOL_GRXCLSRULE: + err = bcmasp_flow_get(intf, cmd); + break; + case ETHTOOL_GRXCLSRLALL: + bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt); + cmd->data = NUM_NET_FILTERS; + break; + default: + err = -EOPNOTSUPP; + break; + } + + mutex_unlock(&intf->parent->net_lock); + + return err; +} + const struct ethtool_ops bcmasp_ethtool_ops = { .get_drvinfo = bcmasp_get_drvinfo, .get_link = ethtool_op_get_link, @@ -73,4 +200,6 @@ const struct ethtool_ops bcmasp_ethtool_ops = { .set_msglevel = bcmasp_set_msglevel, .get_wol = bcmasp_get_wol, .set_wol = bcmasp_set_wol, + .get_rxnfc = bcmasp_get_rxnfc, + .set_rxnfc = bcmasp_set_rxnfc, }; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index 21a8d15a47d8..ad8422334f38 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -1300,6 +1300,9 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf) } umac_wl(intf, reg, UMC_MPD_CTRL); + if (intf->wolopts & WAKE_FILTER) + bcmasp_netfilt_suspend(intf); + /* UniMAC receive needs to be turned on */ umac_enable_set(intf, UMC_CMD_RX_EN, 1); -- cgit From 550e6f345687253083b289b167651deb42869032 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:19:01 -0700 Subject: net: bcmasp: Add support for eee mode Add support for eee mode. Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.h | 4 ++ .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 61 ++++++++++++++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 6 +++ 3 files changed, 71 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index fbbde04a0eab..18a44044ad93 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -315,6 +315,8 @@ struct bcmasp_intf { /* Used if per intf wol irq */ int wol_irq; unsigned int wol_irq_enabled:1; + + struct ethtool_eee eee; }; #define NUM_NET_FILTERS 32 @@ -558,4 +560,6 @@ void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, u32 *rule_cnt); void bcmasp_netfilt_suspend(struct bcmasp_intf *intf); + +void bcmasp_eee_enable_set(struct bcmasp_intf *intf, bool enable); #endif diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index eddd1c43f00e..1e96a69043f3 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -191,6 +191,65 @@ static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, return err; } +void bcmasp_eee_enable_set(struct bcmasp_intf *intf, bool enable) +{ + u32 reg; + + reg = umac_rl(intf, UMC_EEE_CTRL); + if (enable) + reg |= EEE_EN; + else + reg &= ~EEE_EN; + umac_wl(intf, reg, UMC_EEE_CTRL); + + intf->eee.eee_enabled = enable; + intf->eee.eee_active = enable; +} + +static int bcmasp_get_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct ethtool_eee *p = &intf->eee; + + if (!dev->phydev) + return -ENODEV; + + e->eee_enabled = p->eee_enabled; + e->eee_active = p->eee_active; + e->tx_lpi_enabled = p->tx_lpi_enabled; + e->tx_lpi_timer = umac_rl(intf, UMC_EEE_LPI_TIMER); + + return phy_ethtool_get_eee(dev->phydev, e); +} + +static int bcmasp_set_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + struct ethtool_eee *p = &intf->eee; + int ret; + + if (!dev->phydev) + return -ENODEV; + + if (!p->eee_enabled) { + bcmasp_eee_enable_set(intf, false); + } else { + ret = phy_init_eee(dev->phydev, 0); + if (ret) { + netif_err(intf, hw, dev, + "EEE initialization failed: %d\n", ret); + return ret; + } + + umac_wl(intf, e->tx_lpi_timer, UMC_EEE_LPI_TIMER); + intf->eee.eee_active = ret >= 0; + intf->eee.tx_lpi_enabled = e->tx_lpi_enabled; + bcmasp_eee_enable_set(intf, true); + } + + return phy_ethtool_set_eee(dev->phydev, e); +} + const struct ethtool_ops bcmasp_ethtool_ops = { .get_drvinfo = bcmasp_get_drvinfo, .get_link = ethtool_op_get_link, @@ -202,4 +261,6 @@ const struct ethtool_ops bcmasp_ethtool_ops = { .set_wol = bcmasp_set_wol, .get_rxnfc = bcmasp_get_rxnfc, .set_rxnfc = bcmasp_set_rxnfc, + .set_eee = bcmasp_set_eee, + .get_eee = bcmasp_get_eee, }; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index ad8422334f38..051f882b2766 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -646,6 +646,9 @@ static void bcmasp_adj_link(struct net_device *dev) UMC_CMD_TX_PAUSE_IGNORE); reg |= cmd_bits; umac_wl(intf, reg, UMC_CMD); + + intf->eee.eee_active = phy_init_eee(phydev, 0) >= 0; + bcmasp_eee_enable_set(intf, intf->eee.eee_active); } reg = rgmii_rl(intf, RGMII_OOB_CNTRL); @@ -1387,6 +1390,9 @@ int bcmasp_interface_resume(struct bcmasp_intf *intf) bcmasp_resume_from_wol(intf); + if (intf->eee.eee_enabled) + bcmasp_eee_enable_set(intf, true); + netif_device_attach(dev); return 0; -- cgit From 6493153467298877e05fe8faa1602588d0ef25b8 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:19:02 -0700 Subject: net: bcmasp: Add support for ethtool standard stats Add support for eth_mac_stats, rmon_stats, and eth_ctrl_stats. Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 77 ++++++++++++++++++++++ .../net/ethernet/broadcom/asp2/bcmasp_intf_defs.h | 63 +++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index 1e96a69043f3..59d853c2293c 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -250,6 +250,80 @@ static int bcmasp_set_eee(struct net_device *dev, struct ethtool_eee *e) return phy_ethtool_set_eee(dev->phydev, e); } +static void bcmasp_get_eth_mac_stats(struct net_device *dev, + struct ethtool_eth_mac_stats *mac_stats) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + mac_stats->FramesTransmittedOK = umac_rl(intf, UMC_GTPOK); + mac_stats->SingleCollisionFrames = umac_rl(intf, UMC_GTSCL); + mac_stats->MultipleCollisionFrames = umac_rl(intf, UMC_GTMCL); + mac_stats->FramesReceivedOK = umac_rl(intf, UMC_GRPOK); + mac_stats->FrameCheckSequenceErrors = umac_rl(intf, UMC_GRFCS); + mac_stats->AlignmentErrors = umac_rl(intf, UMC_GRALN); + mac_stats->OctetsTransmittedOK = umac_rl(intf, UMC_GTBYT); + mac_stats->FramesWithDeferredXmissions = umac_rl(intf, UMC_GTDRF); + mac_stats->LateCollisions = umac_rl(intf, UMC_GTLCL); + mac_stats->FramesAbortedDueToXSColls = umac_rl(intf, UMC_GTXCL); + mac_stats->OctetsReceivedOK = umac_rl(intf, UMC_GRBYT); + mac_stats->MulticastFramesXmittedOK = umac_rl(intf, UMC_GTMCA); + mac_stats->BroadcastFramesXmittedOK = umac_rl(intf, UMC_GTBCA); + mac_stats->FramesWithExcessiveDeferral = umac_rl(intf, UMC_GTEDF); + mac_stats->MulticastFramesReceivedOK = umac_rl(intf, UMC_GRMCA); + mac_stats->BroadcastFramesReceivedOK = umac_rl(intf, UMC_GRBCA); +} + +static const struct ethtool_rmon_hist_range bcmasp_rmon_ranges[] = { + { 0, 64}, + { 65, 127}, + { 128, 255}, + { 256, 511}, + { 512, 1023}, + { 1024, 1518}, + { 1519, 1522}, + {} +}; + +static void bcmasp_get_rmon_stats(struct net_device *dev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + *ranges = bcmasp_rmon_ranges; + + rmon_stats->undersize_pkts = umac_rl(intf, UMC_RRUND); + rmon_stats->oversize_pkts = umac_rl(intf, UMC_GROVR); + rmon_stats->fragments = umac_rl(intf, UMC_RRFRG); + rmon_stats->jabbers = umac_rl(intf, UMC_GRJBR); + + rmon_stats->hist[0] = umac_rl(intf, UMC_GR64); + rmon_stats->hist[1] = umac_rl(intf, UMC_GR127); + rmon_stats->hist[2] = umac_rl(intf, UMC_GR255); + rmon_stats->hist[3] = umac_rl(intf, UMC_GR511); + rmon_stats->hist[4] = umac_rl(intf, UMC_GR1023); + rmon_stats->hist[5] = umac_rl(intf, UMC_GR1518); + rmon_stats->hist[6] = umac_rl(intf, UMC_GRMGV); + + rmon_stats->hist_tx[0] = umac_rl(intf, UMC_TR64); + rmon_stats->hist_tx[1] = umac_rl(intf, UMC_TR127); + rmon_stats->hist_tx[2] = umac_rl(intf, UMC_TR255); + rmon_stats->hist_tx[3] = umac_rl(intf, UMC_TR511); + rmon_stats->hist_tx[4] = umac_rl(intf, UMC_TR1023); + rmon_stats->hist_tx[5] = umac_rl(intf, UMC_TR1518); + rmon_stats->hist_tx[6] = umac_rl(intf, UMC_TRMGV); +} + +static void bcmasp_get_eth_ctrl_stats(struct net_device *dev, + struct ethtool_eth_ctrl_stats *ctrl_stats) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + + ctrl_stats->MACControlFramesTransmitted = umac_rl(intf, UMC_GTXCF); + ctrl_stats->MACControlFramesReceived = umac_rl(intf, UMC_GRXCF); + ctrl_stats->UnsupportedOpcodesReceived = umac_rl(intf, UMC_GRXUO); +} + const struct ethtool_ops bcmasp_ethtool_ops = { .get_drvinfo = bcmasp_get_drvinfo, .get_link = ethtool_op_get_link, @@ -263,4 +337,7 @@ const struct ethtool_ops bcmasp_ethtool_ops = { .set_rxnfc = bcmasp_set_rxnfc, .set_eee = bcmasp_set_eee, .get_eee = bcmasp_get_eee, + .get_eth_mac_stats = bcmasp_get_eth_mac_stats, + .get_rmon_stats = bcmasp_get_rmon_stats, + .get_eth_ctrl_stats = bcmasp_get_eth_ctrl_stats, }; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h index b259a475207f..ad742612895f 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h @@ -45,7 +45,68 @@ #define UMC_EEE_LPI_TIMER 0x68 #define UMC_PAUSE_CNTRL 0x330 #define UMC_TX_FLUSH 0x334 -#define UMC_MIB_START 0x400 +#define UMC_GR64 0x400 +#define UMC_GR127 0x404 +#define UMC_GR255 0x408 +#define UMC_GR511 0x40c +#define UMC_GR1023 0x410 +#define UMC_GR1518 0x414 +#define UMC_GRMGV 0x418 +#define UMC_GR2047 0x41c +#define UMC_GR4095 0x420 +#define UMC_GR9216 0x424 +#define UMC_GRPKT 0x428 +#define UMC_GRBYT 0x42c +#define UMC_GRMCA 0x430 +#define UMC_GRBCA 0x434 +#define UMC_GRFCS 0x438 +#define UMC_GRXCF 0x43c +#define UMC_GRXPF 0x440 +#define UMC_GRXUO 0x444 +#define UMC_GRALN 0x448 +#define UMC_GRFLR 0x44c +#define UMC_GRCDE 0x450 +#define UMC_GRFCR 0x454 +#define UMC_GROVR 0x458 +#define UMC_GRJBR 0x45c +#define UMC_GRMTUE 0x460 +#define UMC_GRPOK 0x464 +#define UMC_GRUC 0x468 +#define UMC_GRPPP 0x46c +#define UMC_GRMCRC 0x470 +#define UMC_TR64 0x480 +#define UMC_TR127 0x484 +#define UMC_TR255 0x488 +#define UMC_TR511 0x48c +#define UMC_TR1023 0x490 +#define UMC_TR1518 0x494 +#define UMC_TRMGV 0x498 +#define UMC_TR2047 0x49c +#define UMC_TR4095 0x4a0 +#define UMC_TR9216 0x4a4 +#define UMC_GTPKT 0x4a8 +#define UMC_GTMCA 0x4ac +#define UMC_GTBCA 0x4b0 +#define UMC_GTXPF 0x4b4 +#define UMC_GTXCF 0x4b8 +#define UMC_GTFCS 0x4bc +#define UMC_GTOVR 0x4c0 +#define UMC_GTDRF 0x4c4 +#define UMC_GTEDF 0x4c8 +#define UMC_GTSCL 0x4cc +#define UMC_GTMCL 0x4d0 +#define UMC_GTLCL 0x4d4 +#define UMC_GTXCL 0x4d8 +#define UMC_GTFRG 0x4dc +#define UMC_GTNCL 0x4e0 +#define UMC_GTJBR 0x4e4 +#define UMC_GTBYT 0x4e8 +#define UMC_GTPOK 0x4ec +#define UMC_GTUC 0x4f0 +#define UMC_RRPKT 0x500 +#define UMC_RRUND 0x504 +#define UMC_RRFRG 0x508 +#define UMC_RRBYT 0x50c #define UMC_MIB_CNTRL 0x580 #define UMC_MIB_CNTRL_RX_CNT_RST BIT(0) #define UMC_MIB_CNTRL_RUNT_CNT_RST BIT(1) -- cgit From 7c10691e1f5e2c2b358340aaed5eefccc1df17c5 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:19:03 -0700 Subject: net: bcmasp: Add support for ethtool driver stats Add support for ethernet driver specific stats. Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 4 +- drivers/net/ethernet/broadcom/asp2/bcmasp.h | 21 +++ .../net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 160 +++++++++++++++++++++ drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 18 ++- 4 files changed, 199 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 92dfea961add..a9984efff6d1 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -895,8 +895,10 @@ int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr, /* Attempt to combine filters */ ret = bcmasp_combine_set_filter(intf, addr, mask, i); - if (!ret) + if (!ret) { + intf->mib.filters_combine_cnt++; return 0; + } } /* Create new filter if possible */ diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index 18a44044ad93..6bfcaa7f95a8 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -244,6 +244,26 @@ struct bcmasp_intf_stats64 { struct u64_stats_sync syncp; }; +struct bcmasp_mib_counters { + u32 edpkt_ts; + u32 edpkt_rx_pkt_cnt; + u32 edpkt_hdr_ext_cnt; + u32 edpkt_hdr_out_cnt; + u32 umac_frm_cnt; + u32 fb_frm_cnt; + u32 fb_rx_fifo_depth; + u32 fb_out_frm_cnt; + u32 fb_filt_out_frm_cnt; + u32 alloc_rx_skb_failed; + u32 tx_dma_failed; + u32 mc_filters_full_cnt; + u32 uc_filters_full_cnt; + u32 filters_combine_cnt; + u32 promisc_filters_cnt; + u32 tx_realloc_offload_failed; + u32 tx_timeout_cnt; +}; + struct bcmasp_intf_ops { unsigned long (*rx_desc_read)(struct bcmasp_intf *intf); void (*rx_buffer_write)(struct bcmasp_intf *intf, dma_addr_t addr); @@ -309,6 +329,7 @@ struct bcmasp_intf { /* Statistics */ struct bcmasp_intf_stats64 stats64; + struct bcmasp_mib_counters mib; u32 wolopts; u8 sopass[SOPASS_MAX]; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index 59d853c2293c..c4f1604d5ab3 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #define pr_fmt(fmt) "bcmasp_ethtool: " fmt +#include #include #include #include @@ -8,6 +9,162 @@ #include "bcmasp.h" #include "bcmasp_intf_defs.h" +enum bcmasp_stat_type { + BCMASP_STAT_RX_EDPKT, + BCMASP_STAT_RX_CTRL, + BCMASP_STAT_RX_CTRL_PER_INTF, + BCMASP_STAT_SOFT, +}; + +struct bcmasp_stats { + char stat_string[ETH_GSTRING_LEN]; + enum bcmasp_stat_type type; + u32 reg_offset; +}; + +#define STAT_BCMASP_SOFT_MIB(str) { \ + .stat_string = str, \ + .type = BCMASP_STAT_SOFT, \ +} + +#define STAT_BCMASP_OFFSET(str, _type, offset) { \ + .stat_string = str, \ + .type = _type, \ + .reg_offset = offset, \ +} + +#define STAT_BCMASP_RX_EDPKT(str, offset) \ + STAT_BCMASP_OFFSET(str, BCMASP_STAT_RX_EDPKT, offset) +#define STAT_BCMASP_RX_CTRL(str, offset) \ + STAT_BCMASP_OFFSET(str, BCMASP_STAT_RX_CTRL, offset) +#define STAT_BCMASP_RX_CTRL_PER_INTF(str, offset) \ + STAT_BCMASP_OFFSET(str, BCMASP_STAT_RX_CTRL_PER_INTF, offset) + +/* Must match the order of struct bcmasp_mib_counters */ +static const struct bcmasp_stats bcmasp_gstrings_stats[] = { + /* EDPKT counters */ + STAT_BCMASP_RX_EDPKT("RX Time Stamp", ASP_EDPKT_RX_TS_COUNTER), + STAT_BCMASP_RX_EDPKT("RX PKT Count", ASP_EDPKT_RX_PKT_CNT), + STAT_BCMASP_RX_EDPKT("RX PKT Buffered", ASP_EDPKT_HDR_EXTR_CNT), + STAT_BCMASP_RX_EDPKT("RX PKT Pushed to DRAM", ASP_EDPKT_HDR_OUT_CNT), + /* ASP RX control */ + STAT_BCMASP_RX_CTRL_PER_INTF("Frames From Unimac", + ASP_RX_CTRL_UMAC_0_FRAME_COUNT), + STAT_BCMASP_RX_CTRL_PER_INTF("Frames From Port", + ASP_RX_CTRL_FB_0_FRAME_COUNT), + STAT_BCMASP_RX_CTRL_PER_INTF("RX Buffer FIFO Depth", + ASP_RX_CTRL_FB_RX_FIFO_DEPTH), + STAT_BCMASP_RX_CTRL("Frames Out(Buffer)", + ASP_RX_CTRL_FB_OUT_FRAME_COUNT), + STAT_BCMASP_RX_CTRL("Frames Out(Filters)", + ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT), + /* Software maintained statistics */ + STAT_BCMASP_SOFT_MIB("RX SKB Alloc Failed"), + STAT_BCMASP_SOFT_MIB("TX DMA Failed"), + STAT_BCMASP_SOFT_MIB("Multicast Filters Full"), + STAT_BCMASP_SOFT_MIB("Unicast Filters Full"), + STAT_BCMASP_SOFT_MIB("MDA Filters Combined"), + STAT_BCMASP_SOFT_MIB("Promisc Filter Set"), + STAT_BCMASP_SOFT_MIB("TX Realloc For Offload Failed"), + STAT_BCMASP_SOFT_MIB("Tx Timeout Count"), +}; + +#define BCMASP_STATS_LEN ARRAY_SIZE(bcmasp_gstrings_stats) + +static u16 bcmasp_stat_fixup_offset(struct bcmasp_intf *intf, + const struct bcmasp_stats *s) +{ + struct bcmasp_priv *priv = intf->parent; + + if (!strcmp("Frames Out(Buffer)", s->stat_string)) + return priv->hw_info->rx_ctrl_fb_out_frame_count; + + if (!strcmp("Frames Out(Filters)", s->stat_string)) + return priv->hw_info->rx_ctrl_fb_filt_out_frame_count; + + if (!strcmp("RX Buffer FIFO Depth", s->stat_string)) + return priv->hw_info->rx_ctrl_fb_rx_fifo_depth; + + return s->reg_offset; +} + +static int bcmasp_get_sset_count(struct net_device *dev, int string_set) +{ + switch (string_set) { + case ETH_SS_STATS: + return BCMASP_STATS_LEN; + default: + return -EOPNOTSUPP; + } +} + +static void bcmasp_get_strings(struct net_device *dev, u32 stringset, + u8 *data) +{ + unsigned int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < BCMASP_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + bcmasp_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + } + break; + default: + return; + } +} + +static void bcmasp_update_mib_counters(struct bcmasp_intf *intf) +{ + unsigned int i; + + for (i = 0; i < BCMASP_STATS_LEN; i++) { + const struct bcmasp_stats *s; + u32 offset, val; + char *p; + + s = &bcmasp_gstrings_stats[i]; + offset = bcmasp_stat_fixup_offset(intf, s); + switch (s->type) { + case BCMASP_STAT_SOFT: + continue; + case BCMASP_STAT_RX_EDPKT: + val = rx_edpkt_core_rl(intf->parent, offset); + break; + case BCMASP_STAT_RX_CTRL: + val = rx_ctrl_core_rl(intf->parent, offset); + break; + case BCMASP_STAT_RX_CTRL_PER_INTF: + offset += sizeof(u32) * intf->port; + val = rx_ctrl_core_rl(intf->parent, offset); + break; + default: + continue; + } + p = (char *)(&intf->mib) + (i * sizeof(u32)); + put_unaligned(val, (u32 *)p); + } +} + +static void bcmasp_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct bcmasp_intf *intf = netdev_priv(dev); + unsigned int i; + char *p; + + if (netif_running(dev)) + bcmasp_update_mib_counters(intf); + + for (i = 0; i < BCMASP_STATS_LEN; i++) { + p = (char *)(&intf->mib) + (i * sizeof(u32)); + data[i] = *(u32 *)p; + } +} + static void bcmasp_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -340,4 +497,7 @@ const struct ethtool_ops bcmasp_ethtool_ops = { .get_eth_mac_stats = bcmasp_get_eth_mac_stats, .get_rmon_stats = bcmasp_get_rmon_stats, .get_eth_ctrl_stats = bcmasp_get_eth_ctrl_stats, + .get_strings = bcmasp_get_strings, + .get_ethtool_stats = bcmasp_get_ethtool_stats, + .get_sset_count = bcmasp_get_sset_count, }; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index 051f882b2766..53e542881255 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -104,15 +104,19 @@ static void bcmasp_set_rx_mode(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { ret = bcmasp_set_en_mda_filter(intf, ha->addr, mask); - if (ret) + if (ret) { + intf->mib.mc_filters_full_cnt++; goto set_promisc; + } } } netdev_for_each_uc_addr(ha, dev) { ret = bcmasp_set_en_mda_filter(intf, ha->addr, mask); - if (ret) + if (ret) { + intf->mib.uc_filters_full_cnt++; goto set_promisc; + } } spin_unlock_bh(&intf->parent->mda_lock); @@ -120,6 +124,7 @@ static void bcmasp_set_rx_mode(struct net_device *dev) set_promisc: bcmasp_set_promisc(intf, 1); + intf->mib.promisc_filters_cnt++; /* disable all filters used by this port */ bcmasp_disable_all_filters(intf); @@ -155,6 +160,7 @@ static struct sk_buff *bcmasp_csum_offload(struct net_device *dev, struct sk_buff *skb, bool *csum_hw) { + struct bcmasp_intf *intf = netdev_priv(dev); u32 header = 0, header2 = 0, epkt = 0; struct bcmasp_pkt_offload *offload; unsigned int header_cnt = 0; @@ -165,8 +171,10 @@ static struct sk_buff *bcmasp_csum_offload(struct net_device *dev, return skb; ret = skb_cow_head(skb, sizeof(*offload)); - if (ret < 0) + if (ret < 0) { + intf->mib.tx_realloc_offload_failed++; goto help; + } switch (skb->protocol) { case htons(ETH_P_IP): @@ -305,6 +313,7 @@ static netdev_tx_t bcmasp_xmit(struct sk_buff *skb, struct net_device *dev) } if (dma_mapping_error(kdev, mapping)) { + intf->mib.tx_dma_failed++; spb_index = intf->tx_spb_index; for (j = 0; j < i; j++) { bcmasp_clean_txcb(intf, spb_index); @@ -541,6 +550,8 @@ static int bcmasp_rx_poll(struct napi_struct *napi, int budget) u64_stats_update_begin(&stats->syncp); u64_stats_inc(&stats->rx_dropped); u64_stats_update_end(&stats->syncp); + intf->mib.alloc_rx_skb_failed++; + goto next; } @@ -1116,6 +1127,7 @@ static void bcmasp_tx_timeout(struct net_device *dev, unsigned int txqueue) struct bcmasp_intf *intf = netdev_priv(dev); netif_dbg(intf, tx_err, dev, "transmit timeout!\n"); + intf->mib.tx_timeout_cnt++; } static int bcmasp_get_phys_port_name(struct net_device *dev, -- cgit From 9de2b402d818fcb257e61308b190661f30d36c33 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 13 Jul 2023 15:19:04 -0700 Subject: net: phy: mdio-bcm-unimac: Add asp v2.0 support Add mdio compat string for ASP 2.0 ethernet driver. Reviewed-by: Simon Horman Reviewed-by: Andrew Lunn Signed-off-by: Florian Fainelli Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/mdio/mdio-bcm-unimac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/mdio/mdio-bcm-unimac.c b/drivers/net/mdio/mdio-bcm-unimac.c index bfc9be23c973..6b26a0803696 100644 --- a/drivers/net/mdio/mdio-bcm-unimac.c +++ b/drivers/net/mdio/mdio-bcm-unimac.c @@ -334,6 +334,8 @@ static SIMPLE_DEV_PM_OPS(unimac_mdio_pm_ops, unimac_mdio_suspend, unimac_mdio_resume); static const struct of_device_id unimac_mdio_ids[] = { + { .compatible = "brcm,asp-v2.1-mdio", }, + { .compatible = "brcm,asp-v2.0-mdio", }, { .compatible = "brcm,genet-mdio-v5", }, { .compatible = "brcm,genet-mdio-v4", }, { .compatible = "brcm,genet-mdio-v3", }, -- cgit From 9fa0bba012c2dd6d2b0db893314a4cc252a91b5f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 13 Jul 2023 15:19:05 -0700 Subject: net: phy: bcm7xxx: Add EPHY entry for 74165 74165 is a 16nm process SoC with a 10/100 integrated Ethernet PHY, utilize the recently defined 16nm EPHY macro to configure that PHY. Reviewed-by: Simon Horman Reviewed-by: Andrew Lunn Signed-off-by: Florian Fainelli Signed-off-by: Justin Chen Signed-off-by: David S. Miller --- drivers/net/phy/bcm7xxx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index f8c17a253f8b..8478b081c058 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -913,6 +913,7 @@ static struct phy_driver bcm7xxx_driver[] = { BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"), + BCM7XXX_16NM_EPHY(PHY_ID_BCM74165, "Broadcom BCM74165"), BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"), -- cgit From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:19 +0800 Subject: net: phy: at803x: support qca8081 genphy_c45_pma_read_abilities qca8081 PHY supports to use genphy_c45_pma_read_abilities for getting the PHY features supported except for the autoneg ability but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it manually after calling genphy_c45_pma_read_abilities. Signed-off-by: Luo Jie Reviewed-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index c1f307d90518..11388ef3f7ef 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -897,15 +897,6 @@ static int at803x_get_features(struct phy_device *phydev) if (err) return err; - if (phydev->drv->phy_id == QCA8081_PHY_ID) { - err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); - if (err < 0) - return err; - - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, - err & MDIO_PMA_NG_EXTABLE_2_5GBT); - } - if (phydev->drv->phy_id != ATH8031_PHY_ID) return 0; @@ -1991,6 +1982,23 @@ static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finish return 0; } +static int qca808x_get_features(struct phy_device *phydev) +{ + int ret; + + ret = genphy_c45_pma_read_abilities(phydev); + if (ret) + return ret; + + /* The autoneg ability is not existed in bit3 of MMD7.1, + * but it is supported by qca808x PHY, so we add it here + * manually. + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + + return 0; +} + static struct phy_driver at803x_driver[] = { { /* Qualcomm Atheros AR8035 */ @@ -2160,7 +2168,7 @@ static struct phy_driver at803x_driver[] = { .set_tunable = at803x_set_tunable, .set_wol = at803x_set_wol, .get_wol = at803x_get_wol, - .get_features = at803x_get_features, + .get_features = qca808x_get_features, .config_aneg = at803x_config_aneg, .suspend = genphy_suspend, .resume = genphy_resume, -- cgit From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:20 +0800 Subject: net: phy: at803x: merge qca8081 slave seed function merge the seed enablement and seed value configuration into one function, since the random seed value is needed to be configured when the seed is enabled. Signed-off-by: Luo Jie Reviewed-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 11388ef3f7ef..1d4aef60d51a 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -1725,24 +1725,19 @@ static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) return 0; } -static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) -{ - u16 seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); - - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_CFG, - FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); -} - static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) { - u16 seed_enable = 0; + u16 seed_value; - if (enable) - seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; + if (!enable) + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); + QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, + FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | + QCA808X_MASTER_SLAVE_SEED_ENABLE); } static int qca808x_config_init(struct phy_device *phydev) @@ -1766,12 +1761,7 @@ static int qca808x_config_init(struct phy_device *phydev) if (ret) return ret; - /* Configure lower ramdom seed to make phy linked as slave mode */ - ret = qca808x_phy_ms_random_seed_set(phydev); - if (ret) - return ret; - - /* Enable seed */ + /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ ret = qca808x_phy_ms_seed_enable(phydev, true); if (ret) return ret; @@ -1816,7 +1806,6 @@ static int qca808x_read_status(struct phy_device *phydev) if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { qca808x_phy_ms_seed_enable(phydev, false); } else { - qca808x_phy_ms_random_seed_set(phydev); qca808x_phy_ms_seed_enable(phydev, true); } } -- cgit From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:21 +0800 Subject: net: phy: at803x: enable qca8081 slave seed conditionally qca8081 is the single port PHY, the slave prefer mode is used by default. if the phy master perfer mode is configured, the slave seed configuration should not be enabled, since the slave seed enablement is for making PHY linked as slave mode easily. disable slave seed if the master mode is preferred. Signed-off-by: Luo Jie Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 1d4aef60d51a..6cdc1b8f8c4d 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -1740,6 +1740,12 @@ static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) QCA808X_MASTER_SLAVE_SEED_ENABLE); } +static bool qca808x_is_prefer_master(struct phy_device *phydev) +{ + return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || + (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); +} + static int qca808x_config_init(struct phy_device *phydev) { int ret; @@ -1761,11 +1767,17 @@ static int qca808x_config_init(struct phy_device *phydev) if (ret) return ret; - /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ - ret = qca808x_phy_ms_seed_enable(phydev, true); - if (ret) + ret = genphy_read_master_slave(phydev); + if (ret < 0) return ret; + if (!qca808x_is_prefer_master(phydev)) { + /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; + } + /* Configure adc threshold as 100mv for the link 10M */ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); @@ -1797,13 +1809,16 @@ static int qca808x_read_status(struct phy_device *phydev) phydev->interface = PHY_INTERFACE_MODE_SGMII; } else { /* generate seed as a lower random value to make PHY linked as SLAVE easily, - * except for master/slave configuration fault detected. + * except for master/slave configuration fault detected or the master mode + * preferred. + * * the reason for not putting this code into the function link_change_notify is * the corner case where the link partner is also the qca8081 PHY and the seed * value is configured as the same value, the link can't be up and no link change * occurs. */ - if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || + qca808x_is_prefer_master(phydev)) { qca808x_phy_ms_seed_enable(phydev, false); } else { qca808x_phy_ms_seed_enable(phydev, true); -- cgit From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:22 +0800 Subject: net: phy: at803x: support qca8081 1G chip type The qca8081 1G chip version does not support 2.5 capability, which is distinguished from qca8081 2.5G chip according to the bit0 of register mmd7.0x901d, the 1G version chip also has the same PHY ID as the normal qca8081 2.5G chip. Signed-off-by: Luo Jie Reviewed-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 6cdc1b8f8c4d..cb4c45c81a85 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -272,6 +272,10 @@ #define QCA808X_CDT_STATUS_STAT_OPEN 2 #define QCA808X_CDT_STATUS_STAT_SHORT 3 +/* QCA808X 1G chip type */ +#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); MODULE_LICENSE("GPL"); @@ -2000,6 +2004,17 @@ static int qca808x_get_features(struct phy_device *phydev) */ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + /* As for the qca8081 1G version chip, the 2500baseT ability is also + * existed in the bit0 of MMD1.21, we need to remove it manually if + * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. + */ + ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); + if (ret < 0) + return ret; + + if (QCA808X_PHY_CHIP_TYPE_1G & ret) + linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + return 0; } -- cgit From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:23 +0800 Subject: net: phy: at803x: remove qca8081 1G fast retrain and slave seed config The fast retrain and slave seed configs are only applicable when the 2.5G ability is supported. Signed-off-by: Luo Jie Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index cb4c45c81a85..a141f133b8aa 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -1750,6 +1750,11 @@ static bool qca808x_is_prefer_master(struct phy_device *phydev) (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); } +static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) +{ + return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +} + static int qca808x_config_init(struct phy_device *phydev) { int ret; @@ -1766,20 +1771,24 @@ static int qca808x_config_init(struct phy_device *phydev) if (ret) return ret; - /* Config the fast retrain for the link 2500M */ - ret = qca808x_phy_fast_retrain_config(phydev); - if (ret) - return ret; - - ret = genphy_read_master_slave(phydev); - if (ret < 0) - return ret; - - if (!qca808x_is_prefer_master(phydev)) { - /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ - ret = qca808x_phy_ms_seed_enable(phydev, true); + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + /* Config the fast retrain for the link 2500M */ + ret = qca808x_phy_fast_retrain_config(phydev); if (ret) return ret; + + ret = genphy_read_master_slave(phydev); + if (ret < 0) + return ret; + + if (!qca808x_is_prefer_master(phydev)) { + /* Enable seed and configure lower ramdom seed to make phy + * linked as slave mode. + */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; + } } /* Configure adc threshold as 100mv for the link 10M */ @@ -1821,11 +1830,13 @@ static int qca808x_read_status(struct phy_device *phydev) * value is configured as the same value, the link can't be up and no link change * occurs. */ - if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || - qca808x_is_prefer_master(phydev)) { - qca808x_phy_ms_seed_enable(phydev, false); - } else { - qca808x_phy_ms_seed_enable(phydev, true); + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || + qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); + } } } @@ -1840,7 +1851,10 @@ static int qca808x_soft_reset(struct phy_device *phydev) if (ret < 0) return ret; - return qca808x_phy_ms_seed_enable(phydev, true); + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) + ret = qca808x_phy_ms_seed_enable(phydev, true); + + return ret; } static bool qca808x_cdt_fault_length_valid(int cdt_code) -- cgit From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 From: Luo Jie Date: Sun, 16 Jul 2023 16:49:24 +0800 Subject: net: phy: at803x: add qca8081 fifo reset on the link changed The qca8081 sgmii fifo needs to be reset on link down and released on the link up in case of any abnormal issue such as the packet blocked on the PHY. Signed-off-by: Luo Jie Reviewed-by: Andrew Lunn Reviewed-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index a141f133b8aa..13c4121fa309 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -276,6 +276,9 @@ #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 +#define QCA8081_PHY_FIFO_RSTN BIT(11) + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); MODULE_LICENSE("GPL"); @@ -2032,6 +2035,16 @@ static int qca808x_get_features(struct phy_device *phydev) return 0; } +static void qca808x_link_change_notify(struct phy_device *phydev) +{ + /* Assert interface sgmii fifo on link down, deassert it on link up, + * the interface device address is always phy address added by 1. + */ + mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, + MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, + QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); +} + static struct phy_driver at803x_driver[] = { { /* Qualcomm Atheros AR8035 */ @@ -2210,6 +2223,7 @@ static struct phy_driver at803x_driver[] = { .soft_reset = qca808x_soft_reset, .cable_test_start = qca808x_cable_test_start, .cable_test_get_status = qca808x_cable_test_get_status, + .link_change_notify = qca808x_link_change_notify, }, }; module_phy_driver(at803x_driver); -- cgit From b382380c0d2da427aaffca931e4a3b831048cace Mon Sep 17 00:00:00 2001 From: Judith Mendez Date: Fri, 7 Jul 2023 15:47:14 -0500 Subject: can: m_can: Add hrtimer to generate software interrupt Introduce timer polling method to MCAN since some SoCs may not have M_CAN interrupt routed to A53 Linux and do not have interrupt property in device tree M_CAN node. On AM62x SoC, MCANs on MCU domain do not have hardware interrupt routed to A53 Linux, instead they will use timer polling method. Add an hrtimer to MCAN class device. Each MCAN will have its own hrtimer instantiated if there is no hardware interrupt found in device tree M_CAN node. The timer will generate a software interrupt every 1 ms. In hrtimer callback, we check if there is a transaction pending by reading a register, then process by calling the isr if there is. Tested-by: Hiago De Franco # Toradex Verdin AM62 Reviewed-by: Tony Lindgren Signed-off-by: Judith Mendez Link: https://lore.kernel.org/all/20230707204714.62964-3-jm@ti.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/m_can.c | 32 +++++++++++++++++++++++++++++++- drivers/net/can/m_can/m_can.h | 3 +++ drivers/net/can/m_can/m_can_platform.c | 21 +++++++++++++++++---- 3 files changed, 51 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index c5af92bcc9c9..13fd84b2e2dd 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -308,6 +309,9 @@ enum m_can_reg { #define TX_EVENT_MM_MASK GENMASK(31, 24) #define TX_EVENT_TXTS_MASK GENMASK(15, 0) +/* Hrtimer polling interval */ +#define HRTIMER_POLL_INTERVAL_MS 1 + /* The ID and DLC registers are adjacent in M_CAN FIFO memory, * and we can save a (potentially slow) bus round trip by combining * reads and writes to them. @@ -1414,6 +1418,12 @@ static int m_can_start(struct net_device *dev) m_can_enable_all_interrupts(cdev); + if (!dev->irq) { + dev_dbg(cdev->dev, "Start hrtimer\n"); + hrtimer_start(&cdev->hrtimer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS), + HRTIMER_MODE_REL_PINNED); + } + return 0; } @@ -1568,6 +1578,11 @@ static void m_can_stop(struct net_device *dev) { struct m_can_classdev *cdev = netdev_priv(dev); + if (!dev->irq) { + dev_dbg(cdev->dev, "Stop hrtimer\n"); + hrtimer_cancel(&cdev->hrtimer); + } + /* disable all interrupts */ m_can_disable_all_interrupts(cdev); @@ -1793,6 +1808,18 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer) +{ + struct m_can_classdev *cdev = container_of(timer, struct + m_can_classdev, hrtimer); + + m_can_isr(0, cdev->net); + + hrtimer_forward_now(timer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS)); + + return HRTIMER_RESTART; +} + static int m_can_open(struct net_device *dev) { struct m_can_classdev *cdev = netdev_priv(dev); @@ -1831,7 +1858,7 @@ static int m_can_open(struct net_device *dev) err = request_threaded_irq(dev->irq, NULL, m_can_isr, IRQF_ONESHOT, dev->name, dev); - } else { + } else if (dev->irq) { err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name, dev); } @@ -2027,6 +2054,9 @@ int m_can_class_register(struct m_can_classdev *cdev) goto clk_disable; } + if (!cdev->net->irq) + cdev->hrtimer.function = &hrtimer_callback; + ret = m_can_dev_setup(cdev); if (ret) goto rx_offload_del; diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index a839dc71dc9b..2ac18ac867a4 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,8 @@ struct m_can_classdev { int is_peripheral; struct mram_cfg mcfg[MRAM_CFG_NUM]; + + struct hrtimer hrtimer; }; struct m_can_classdev *m_can_class_allocate_dev(struct device *dev, int sizeof_priv); diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 94dc82644113..cdb28d6a092c 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -5,6 +5,7 @@ // // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ +#include #include #include @@ -82,7 +83,7 @@ static int m_can_plat_probe(struct platform_device *pdev) void __iomem *addr; void __iomem *mram_addr; struct phy *transceiver; - int irq, ret = 0; + int irq = 0, ret = 0; mcan_class = m_can_class_allocate_dev(&pdev->dev, sizeof(struct m_can_plat_priv)); @@ -96,12 +97,24 @@ static int m_can_plat_probe(struct platform_device *pdev) goto probe_fail; addr = devm_platform_ioremap_resource_byname(pdev, "m_can"); - irq = platform_get_irq_byname(pdev, "int0"); - if (IS_ERR(addr) || irq < 0) { - ret = -EINVAL; + if (IS_ERR(addr)) { + ret = PTR_ERR(addr); goto probe_fail; } + if (device_property_present(mcan_class->dev, "interrupts") || + device_property_present(mcan_class->dev, "interrupt-names")) { + irq = platform_get_irq_byname(pdev, "int0"); + if (irq < 0) { + ret = irq; + goto probe_fail; + } + } else { + dev_dbg(mcan_class->dev, "Polling enabled, initialize hrtimer"); + hrtimer_init(&mcan_class->hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_PINNED); + } + /* message ram could be shared */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); if (!res) { -- cgit From 2cee73cef253a333c7d48a0f8edda53e3cca990c Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 13 Jul 2023 12:57:43 +0300 Subject: net: ftgmac100: support getting MAC address from NVMEM Make use of of_get_ethdev_address() to support reading MAC address not only from the usual DT nodes but also from an NVMEM provider (e.g. using a dedicated area in an FRU EEPROM). Signed-off-by: Paul Fertser Link: https://lore.kernel.org/r/20230713095743.30517-1-fercerpav@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/faraday/ftgmac100.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index a03879a27b04..9135b918dd49 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -177,16 +177,20 @@ static void ftgmac100_write_mac_addr(struct ftgmac100 *priv, const u8 *mac) iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR); } -static void ftgmac100_initial_mac(struct ftgmac100 *priv) +static int ftgmac100_initial_mac(struct ftgmac100 *priv) { u8 mac[ETH_ALEN]; unsigned int m; unsigned int l; + int err; - if (!device_get_ethdev_address(priv->dev, priv->netdev)) { + err = of_get_ethdev_address(priv->dev->of_node, priv->netdev); + if (err == -EPROBE_DEFER) + return err; + if (!err) { dev_info(priv->dev, "Read MAC address %pM from device tree\n", priv->netdev->dev_addr); - return; + return 0; } m = ioread32(priv->base + FTGMAC100_OFFSET_MAC_MADR); @@ -207,6 +211,8 @@ static void ftgmac100_initial_mac(struct ftgmac100 *priv) dev_info(priv->dev, "Generated random MAC address %pM\n", priv->netdev->dev_addr); } + + return 0; } static int ftgmac100_set_mac_addr(struct net_device *dev, void *p) @@ -1843,7 +1849,9 @@ static int ftgmac100_probe(struct platform_device *pdev) priv->aneg_pause = true; /* MAC address from chip or random one */ - ftgmac100_initial_mac(priv); + err = ftgmac100_initial_mac(priv); + if (err) + goto err_phy_connect; np = pdev->dev.of_node; if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac") || -- cgit From 8f42c07fb0f208150676e2e7b6b0482522b304c9 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 14 Jul 2023 10:12:12 +0100 Subject: net: dsa: remove legacy_pre_march2020 from drivers Since DSA no longer marks anything as phylink-legacy, there is now no need for DSA drivers to set this member to false. Remove all instances of this. Signed-off-by: Russell King (Oracle) Reviewed-by: Florian Fainelli Reviewed-by: Vladimir Oltean Signed-off-by: Paolo Abeni --- drivers/net/dsa/b53/b53_common.c | 6 ------ drivers/net/dsa/lan9303-core.c | 6 ------ drivers/net/dsa/microchip/ksz_common.c | 2 -- drivers/net/dsa/mt7530.c | 6 ------ drivers/net/dsa/mv88e6xxx/chip.c | 4 ---- drivers/net/dsa/ocelot/felix.c | 6 ------ drivers/net/dsa/qca/qca8k-8xxx.c | 2 -- drivers/net/dsa/sja1105/sja1105_main.c | 6 ------ 8 files changed, 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 3464ce5e7470..4e27dc913cf7 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1393,12 +1393,6 @@ static void b53_phylink_get_caps(struct dsa_switch *ds, int port, /* Get the implementation specific capabilities */ if (dev->ops->phylink_get_caps) dev->ops->phylink_get_caps(dev, port, config); - - /* This driver does not make use of the speed, duplex, pause or the - * advertisement in its mac_config, so it is safe to mark this driver - * as non-legacy. - */ - config->legacy_pre_march2020 = false; } static struct phylink_pcs *b53_phylink_mac_select_pcs(struct dsa_switch *ds, diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index ff76444057d2..b0da1e4de63c 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1290,12 +1290,6 @@ static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces); } - - /* This driver does not make use of the speed, duplex, pause or the - * advertisement in its mac_config, so it is safe to mark this driver - * as non-legacy. - */ - config->legacy_pre_march2020 = false; } static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 813b91a816bb..07ba2b54ab99 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1624,8 +1624,6 @@ static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, { struct ksz_device *dev = ds->priv; - config->legacy_pre_march2020 = false; - if (dev->info->supports_mii[port]) __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 38b3c6dda386..8fbda739c1b3 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2949,12 +2949,6 @@ static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; - /* This driver does not make use of the speed, duplex, pause or the - * advertisement in its mac_config, so it is safe to mark this driver - * as non-legacy. - */ - config->legacy_pre_march2020 = false; - priv->info->mac_port_get_caps(ds, port, config); } diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6174855188d9..8dd82fd87fc6 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -769,10 +769,6 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces); } - - /* If we have a .pcs_init, we are not legacy. */ - if (chip->info->ops->pcs_ops) - config->legacy_pre_march2020 = false; } static struct phylink_pcs *mv88e6xxx_mac_select_pcs(struct dsa_switch *ds, diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 8da46d284e35..fd7eb4a52918 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1042,12 +1042,6 @@ static void felix_phylink_get_caps(struct dsa_switch *ds, int port, { struct ocelot *ocelot = ds->priv; - /* This driver does not make use of the speed, duplex, pause or the - * advertisement in its mac_config, so it is safe to mark this driver - * as non-legacy. - */ - config->legacy_pre_march2020 = false; - config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index 09b80644c11b..27bf58e40be6 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1397,8 +1397,6 @@ static void qca8k_phylink_get_caps(struct dsa_switch *ds, int port, config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; - - config->legacy_pre_march2020 = false; } static void diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 3529a565b4aa..52dd52d6c43d 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1396,12 +1396,6 @@ static void sja1105_phylink_get_caps(struct dsa_switch *ds, int port, struct sja1105_xmii_params_entry *mii; phy_interface_t phy_mode; - /* This driver does not make use of the speed, duplex, pause or the - * advertisement in its mac_config, so it is safe to mark this driver - * as non-legacy. - */ - config->legacy_pre_march2020 = false; - phy_mode = priv->phy_mode[port]; if (phy_mode == PHY_INTERFACE_MODE_SGMII || phy_mode == PHY_INTERFACE_MODE_2500BASEX) { -- cgit From 76226787e137962750241bb29a9572dfc10d9eb1 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 14 Jul 2023 10:12:17 +0100 Subject: net: phylink: remove legacy mac_an_restart() method The mac_an_restart() method is now completely unused, and has been superseded by phylink_pcs support. Remove this method. Since phylink_pcs_mac_an_restart() now only deals with the PCS, rename the function to remove the _mac infix. Signed-off-by: Russell King (Oracle) Reviewed-by: Florian Fainelli Signed-off-by: Paolo Abeni --- drivers/net/phy/phylink.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 71b1012ef3be..f07e496319b4 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1079,17 +1079,13 @@ static void phylink_mac_config(struct phylink *pl, pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); } -static void phylink_mac_pcs_an_restart(struct phylink *pl) +static void phylink_pcs_an_restart(struct phylink *pl) { - if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - pl->link_config.advertising) && + if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + pl->link_config.advertising) && phy_interface_mode_is_8023z(pl->link_config.interface) && - phylink_autoneg_inband(pl->cur_link_an_mode)) { - if (pl->pcs) - pl->pcs->ops->pcs_an_restart(pl->pcs); - else if (pl->config->legacy_pre_march2020) - pl->mac_ops->mac_an_restart(pl->config); - } + phylink_autoneg_inband(pl->cur_link_an_mode)) + pl->pcs->ops->pcs_an_restart(pl->pcs); } static void phylink_major_config(struct phylink *pl, bool restart, @@ -1169,7 +1165,7 @@ static void phylink_major_config(struct phylink *pl, bool restart, restart = true; if (restart) - phylink_mac_pcs_an_restart(pl); + phylink_pcs_an_restart(pl); if (pl->mac_ops->mac_finish) { err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode, @@ -1205,7 +1201,7 @@ static int phylink_change_inband_advert(struct phylink *pl) if (!pl->pcs && pl->config->legacy_pre_march2020) { /* Legacy method */ phylink_mac_config(pl, &pl->link_config); - phylink_mac_pcs_an_restart(pl); + phylink_pcs_an_restart(pl); return 0; } @@ -1234,7 +1230,7 @@ static int phylink_change_inband_advert(struct phylink *pl) return ret; if (ret > 0) - phylink_mac_pcs_an_restart(pl); + phylink_pcs_an_restart(pl); return 0; } @@ -2533,7 +2529,7 @@ int phylink_ethtool_nway_reset(struct phylink *pl) if (pl->phydev) ret = phy_restart_aneg(pl->phydev); - phylink_mac_pcs_an_restart(pl); + phylink_pcs_an_restart(pl); return ret; } -- cgit From c62c0a17f9b7398022f9eebe547878033264f81f Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 14 Jul 2023 04:13:29 -0700 Subject: netconsole: Append kernel version to message Create a new netconsole runtime option that prepends the kernel version in the netconsole message. This is useful to map kernel messages to kernel version in a simple way, i.e., without checking somewhere which kernel version the host that sent the message is using. If this option is selected, then the "," is prepended before the netconsole message. This is an example of a netconsole output, with release feature enabled: 6.4.0-01762-ga1ba2ffe946e;12,426,112883998,-;this is a test Cc: Dave Jones Signed-off-by: Breno Leitao Link: https://lore.kernel.org/r/20230714111330.3069605-1-leitao@debian.org Signed-off-by: Paolo Abeni --- drivers/net/netconsole.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 4f4f79532c6c..31cbe02eda49 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -36,6 +36,7 @@ #include #include #include +#include MODULE_AUTHOR("Maintainer: Matt Mackall "); MODULE_DESCRIPTION("Console driver for network interfaces"); @@ -84,6 +85,8 @@ static struct console netconsole_ext; * Also, other parameters of a target may be modified at * runtime only when it is disabled (enabled == 0). * @extended: Denotes whether console is extended or not. + * @release: Denotes whether kernel release version should be prepended + * to the message. Depends on extended console. * @np: The netpoll structure for this target. * Contains the other userspace visible parameters: * dev_name (read-write) @@ -101,6 +104,7 @@ struct netconsole_target { #endif bool enabled; bool extended; + bool release; struct netpoll np; }; @@ -188,6 +192,15 @@ static struct netconsole_target *alloc_param_target(char *target_config) target_config++; } + if (*target_config == 'r') { + if (!nt->extended) { + pr_err("Netconsole configuration error. Release feature requires extended log message"); + goto fail; + } + nt->release = true; + target_config++; + } + /* Parse parameters and setup netpoll */ err = netpoll_parse_options(&nt->np, target_config); if (err) @@ -222,6 +235,7 @@ static void free_param_target(struct netconsole_target *nt) * | * / * | enabled + * | release * | dev_name * | local_port * | remote_port @@ -254,6 +268,11 @@ static ssize_t extended_show(struct config_item *item, char *buf) return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended); } +static ssize_t release_show(struct config_item *item, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->release); +} + static ssize_t dev_name_show(struct config_item *item, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name); @@ -332,6 +351,11 @@ static ssize_t enabled_store(struct config_item *item, } if (enabled) { /* true */ + if (nt->release && !nt->extended) { + pr_err("Not enabling netconsole. Release feature requires extended log message"); + goto out_unlock; + } + if (nt->extended && !console_is_registered(&netconsole_ext)) register_console(&netconsole_ext); @@ -366,6 +390,38 @@ out_unlock: return err; } +static ssize_t release_store(struct config_item *item, const char *buf, + size_t count) +{ + struct netconsole_target *nt = to_target(item); + int release; + int err; + + mutex_lock(&dynamic_netconsole_mutex); + if (nt->enabled) { + pr_err("target (%s) is enabled, disable to update parameters\n", + config_item_name(&nt->item)); + err = -EINVAL; + goto out_unlock; + } + + err = kstrtoint(buf, 10, &release); + if (err < 0) + goto out_unlock; + if (release < 0 || release > 1) { + err = -EINVAL; + goto out_unlock; + } + + nt->release = release; + + mutex_unlock(&dynamic_netconsole_mutex); + return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return err; +} + static ssize_t extended_store(struct config_item *item, const char *buf, size_t count) { @@ -576,10 +632,12 @@ CONFIGFS_ATTR(, local_ip); CONFIGFS_ATTR(, remote_ip); CONFIGFS_ATTR_RO(, local_mac); CONFIGFS_ATTR(, remote_mac); +CONFIGFS_ATTR(, release); static struct configfs_attribute *netconsole_target_attrs[] = { &attr_enabled, &attr_extended, + &attr_release, &attr_dev_name, &attr_local_port, &attr_remote_port, @@ -772,9 +830,23 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg, const char *header, *body; int offset = 0; int header_len, body_len; + const char *msg_ready = msg; + const char *release; + int release_len = 0; + + if (nt->release) { + release = init_utsname()->release; + release_len = strlen(release) + 1; + } - if (msg_len <= MAX_PRINT_CHUNK) { - netpoll_send_udp(&nt->np, msg, msg_len); + if (msg_len + release_len <= MAX_PRINT_CHUNK) { + /* No fragmentation needed */ + if (nt->release) { + scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg); + msg_len += release_len; + msg_ready = buf; + } + netpoll_send_udp(&nt->np, msg_ready, msg_len); return; } @@ -792,7 +864,10 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg, * Transfer multiple chunks with the following extra header. * "ncfrag=/" */ - memcpy(buf, header, header_len); + if (nt->release) + scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release); + memcpy(buf + release_len, header, header_len); + header_len += release_len; while (offset < body_len) { int this_header = header_len; -- cgit From d3750076d4641b697da990b6aee5b096a10c4d12 Mon Sep 17 00:00:00 2001 From: Muhammad Husaini Zulkifli Date: Fri, 14 Jul 2023 13:14:28 -0700 Subject: igc: Add TransmissionOverrun counter Add TransmissionOverrun as per defined by IEEE 802.1Q Bridges. TransmissionOverrun counter shall be incremented if the implementation detects that a frame from a given queue is still being transmitted by the MAC when that gate-close event for that queue occurs. This counter is utilised by the Certification conformance test to inform the user application whether any packets are currently being transmitted on a particular queue during a gate-close event. Intel Discrete I225/I226 have a mechanism to not transmit a packets if the gate open time is insufficient for the packet transmission by setting the Strict_End bit. Thus, it is expected for this counter to be always zero at this moment. Inspired from enetc_taprio_stats() and enetc_taprio_queue_stats(), now driver also report the tx_overruns counter per traffic class. User can get this counter by using below command: 1) tc -s qdisc show dev root 2) tc -s class show dev Test Result (Before): class mq :1 root Sent 1289 bytes 20 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 class mq :2 root Sent 124 bytes 2 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 class mq :3 root Sent 46028 bytes 86 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 class mq :4 root Sent 2596 bytes 14 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 Test Result (After): class taprio 100:1 root Sent 8491 bytes 38 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 Transmit overruns: 0 class taprio 100:2 root Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 Transmit overruns: 0 class taprio 100:3 root Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 Transmit overruns: 0 class taprio 100:4 root Sent 994 bytes 11 pkt (dropped 0, overlimits 0 requeues 1) backlog 0b 0p requeues 1 Transmit overruns: 0 Signed-off-by: Muhammad Husaini Zulkifli Reviewed-by: Vladimir Oltean Tested-by: Naama Meir Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20230714201428.1718097-1-anthony.l.nguyen@intel.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/intel/igc/igc_main.c | 35 ++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 9f93f0f4f752..ddb4386c00cc 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6115,6 +6115,26 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) return 0; } +static void igc_taprio_stats(struct net_device *dev, + struct tc_taprio_qopt_stats *stats) +{ + /* When Strict_End is enabled, the tx_overruns counter + * will always be zero. + */ + stats->tx_overruns = 0; +} + +static void igc_taprio_queue_stats(struct net_device *dev, + struct tc_taprio_qopt_queue_stats *queue_stats) +{ + struct tc_taprio_qopt_stats *stats = &queue_stats->stats; + + /* When Strict_End is enabled, the tx_overruns counter + * will always be zero. + */ + stats->tx_overruns = 0; +} + static int igc_save_qbv_schedule(struct igc_adapter *adapter, struct tc_taprio_qopt_offload *qopt) { @@ -6125,11 +6145,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, size_t n; int i; - if (qopt->cmd == TAPRIO_CMD_DESTROY) + switch (qopt->cmd) { + case TAPRIO_CMD_REPLACE: + break; + case TAPRIO_CMD_DESTROY: return igc_tsn_clear_schedule(adapter); - - if (qopt->cmd != TAPRIO_CMD_REPLACE) + case TAPRIO_CMD_STATS: + igc_taprio_stats(adapter->netdev, &qopt->stats); + return 0; + case TAPRIO_CMD_QUEUE_STATS: + igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); + return 0; + default: return -EOPNOTSUPP; + } if (qopt->base_time < 0) return -ERANGE; -- cgit From 9843814fc651d590cc5a82488c644ccf70975f16 Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Mon, 17 Jul 2023 10:13:33 +0800 Subject: net: txgbe: change LAN reset mode The old way to do LAN reset is sending reset command to firmware. Once firmware performs reset, it reconfigures what it needs. In the new firmware versions, veto bit is introduced for NCSI/LLDP to block PHY domain in LAN reset. At this point, writing register of LAN reset directly makes the same effect as the old way. And it does not reset MNG domain, so that veto bit does not change. Since veto bit was never used, the old firmware is compatible with the driver before and after this change. The new firmware needs to use with the driver after this change if it wants to implement the new feature, otherwise it is the same as the old firmware. Signed-off-by: Jiawen Wu Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230717021333.94181-1-jiawenwu@trustnetic.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 65 --------------------------- drivers/net/ethernet/wangxun/libwx/wx_hw.h | 1 - drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c | 8 ++-- 3 files changed, 4 insertions(+), 70 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index ad09ab1d1209..f833c84a7876 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -431,71 +431,6 @@ out: } EXPORT_SYMBOL(wx_read_ee_hostif_buffer); -/** - * wx_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 wx_calculate_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u32 i; - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8)(0 - sum); -} - -/** - * wx_reset_hostif - send reset cmd to fw - * @wx: pointer to hardware structure - * - * Sends reset cmd to firmware through the manageability - * block. - **/ -int wx_reset_hostif(struct wx *wx) -{ - struct wx_hic_reset reset_cmd; - int ret_val = 0; - int i; - - reset_cmd.hdr.cmd = FW_RESET_CMD; - reset_cmd.hdr.buf_len = FW_RESET_LEN; - reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; - reset_cmd.lan_id = wx->bus.func; - reset_cmd.reset_type = (u16)wx->reset_type; - reset_cmd.hdr.checksum = 0; - reset_cmd.hdr.checksum = wx_calculate_checksum((u8 *)&reset_cmd, - (FW_CEM_HDR_LEN + - reset_cmd.hdr.buf_len)); - - for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { - ret_val = wx_host_interface_command(wx, (u32 *)&reset_cmd, - sizeof(reset_cmd), - WX_HI_COMMAND_TIMEOUT, - true); - if (ret_val != 0) - continue; - - if (reset_cmd.hdr.cmd_or_resp.ret_status == - FW_CEM_RESP_STATUS_SUCCESS) - ret_val = 0; - else - ret_val = -EFAULT; - - break; - } - - return ret_val; -} -EXPORT_SYMBOL(wx_reset_hostif); - /** * wx_init_eeprom_params - Initialize EEPROM params * @wx: pointer to hardware structure diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h index b95090e973ae..0b3447bc6f2f 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h @@ -14,7 +14,6 @@ int wx_host_interface_command(struct wx *wx, u32 *buffer, int wx_read_ee_hostif(struct wx *wx, u16 offset, u16 *data); int wx_read_ee_hostif_buffer(struct wx *wx, u16 offset, u16 words, u16 *data); -int wx_reset_hostif(struct wx *wx); void wx_init_eeprom_params(struct wx *wx); void wx_get_mac_addr(struct wx *wx, u8 *mac_addr); void wx_init_rx_addrs(struct wx *wx); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c index 0772eb14eabf..6e130d1f7a7b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c @@ -257,16 +257,16 @@ static void txgbe_reset_misc(struct wx *wx) int txgbe_reset_hw(struct wx *wx) { int status; + u32 val; /* Call adapter stop to disable tx/rx and clear interrupts */ status = wx_stop_adapter(wx); if (status != 0) return status; - if (!(((wx->subsystem_device_id & WX_NCSI_MASK) == WX_NCSI_SUP) || - ((wx->subsystem_device_id & WX_WOL_MASK) == WX_WOL_SUP))) - wx_reset_hostif(wx); - + val = WX_MIS_RST_LAN_RST(wx->bus.func); + wr32(wx, WX_MIS_RST, val | rd32(wx, WX_MIS_RST)); + WX_WRITE_FLUSH(wx); usleep_range(10, 100); status = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_LAN_SW_RST(wx->bus.func)); -- cgit From f8e343326c1d267e2144586a72663540f651c6a7 Mon Sep 17 00:00:00 2001 From: Minjie Du Date: Mon, 17 Jul 2023 10:55:37 +0800 Subject: net: mvpp2: debugfs: remove redundant parameter check in three functions As per the comment above debugfs_create_dir(), it is not expected to return an error, so an extra error check is not needed. Drop the return check of debugfs_create_dir() in mvpp2_dbgfs_c2_entry_init(), mvpp2_dbgfs_flow_tbl_entry_init() and mvpp2_dbgfs_cls_init(). Signed-off-by: Minjie Du Reviewed-by: Russell King (Oracle) Link: https://lore.kernel.org/r/20230717025538.2848-1-duminjie@vivo.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c index 75e83ea2a926..0f9bc4f8ec3b 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c @@ -593,8 +593,6 @@ static int mvpp2_dbgfs_c2_entry_init(struct dentry *parent, sprintf(c2_entry_name, "%03d", id); c2_entry_dir = debugfs_create_dir(c2_entry_name, parent); - if (!c2_entry_dir) - return -ENOMEM; entry = &priv->dbgfs_entries->c2_entries[id]; @@ -626,8 +624,6 @@ static int mvpp2_dbgfs_flow_tbl_entry_init(struct dentry *parent, sprintf(flow_tbl_entry_name, "%03d", id); flow_tbl_entry_dir = debugfs_create_dir(flow_tbl_entry_name, parent); - if (!flow_tbl_entry_dir) - return -ENOMEM; entry = &priv->dbgfs_entries->flt_entries[id]; @@ -646,12 +642,8 @@ static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv) int i, ret; cls_dir = debugfs_create_dir("classifier", parent); - if (!cls_dir) - return -ENOMEM; c2_dir = debugfs_create_dir("c2", cls_dir); - if (!c2_dir) - return -ENOMEM; for (i = 0; i < MVPP22_CLS_C2_N_ENTRIES; i++) { ret = mvpp2_dbgfs_c2_entry_init(c2_dir, priv, i); @@ -660,8 +652,6 @@ static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv) } flow_tbl_dir = debugfs_create_dir("flow_table", cls_dir); - if (!flow_tbl_dir) - return -ENOMEM; for (i = 0; i < MVPP2_CLS_FLOWS_TBL_SIZE; i++) { ret = mvpp2_dbgfs_flow_tbl_entry_init(flow_tbl_dir, priv, i); -- cgit From da4e8648079eb6f26f3a88d8c34270a057e2bfe6 Mon Sep 17 00:00:00 2001 From: Long Li Date: Mon, 17 Jul 2023 12:35:38 -0700 Subject: net: mana: Batch ringing RX queue doorbell on receiving packets It's inefficient to ring the doorbell page every time a WQE is posted to the received queue. Excessive MMIO writes result in CPU spending more time waiting on LOCK instructions (atomic operations), resulting in poor scaling performance. Move the code for ringing doorbell page to where after we have posted all WQEs to the receive queue during a callback from napi_poll(). With this change, tests showed an improvement from 120G/s to 160G/s on a 200G physical link, with 16 or 32 hardware queues. Tests showed no regression in network latency benchmarks on single connection. Reviewed-by: Haiyang Zhang Reviewed-by: Dexuan Cui Signed-off-by: Long Li Link: https://lore.kernel.org/r/1689622539-5334-2-git-send-email-longli@linuxonhyperv.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microsoft/mana/mana_en.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index a499e460594b..ac2acc9aca9d 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1386,8 +1386,8 @@ static void mana_post_pkt_rxq(struct mana_rxq *rxq) recv_buf_oob = &rxq->rx_oobs[curr_index]; - err = mana_gd_post_and_ring(rxq->gdma_rq, &recv_buf_oob->wqe_req, - &recv_buf_oob->wqe_inf); + err = mana_gd_post_work_request(rxq->gdma_rq, &recv_buf_oob->wqe_req, + &recv_buf_oob->wqe_inf); if (WARN_ON_ONCE(err)) return; @@ -1657,6 +1657,12 @@ static void mana_poll_rx_cq(struct mana_cq *cq) mana_process_rx_cqe(rxq, cq, &comp[i]); } + if (comp_read > 0) { + struct gdma_context *gc = rxq->gdma_rq->gdma_dev->gdma_context; + + mana_gd_wq_ring_doorbell(gc, rxq->gdma_rq); + } + if (rxq->xdp_flush) xdp_do_flush(); } -- cgit From f5e39b57124fd4715d7f0e2f841b8609b38f3e40 Mon Sep 17 00:00:00 2001 From: Long Li Date: Mon, 17 Jul 2023 12:35:39 -0700 Subject: net: mana: Use the correct WQE count for ringing RQ doorbell The hardware specification specifies that WQE_COUNT should set to 0 for the Receive Queue. Although currently the hardware doesn't enforce the check, in the future releases it may check on this value. Reviewed-by: Haiyang Zhang Reviewed-by: Dexuan Cui Signed-off-by: Long Li Link: https://lore.kernel.org/r/1689622539-5334-3-git-send-email-longli@linuxonhyperv.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microsoft/mana/gdma_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index 8f3f78b68592..3765d3389a9a 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -300,8 +300,11 @@ static void mana_gd_ring_doorbell(struct gdma_context *gc, u32 db_index, void mana_gd_wq_ring_doorbell(struct gdma_context *gc, struct gdma_queue *queue) { + /* Hardware Spec specifies that software client should set 0 for + * wqe_cnt for Receive Queues. This value is not used in Send Queues. + */ mana_gd_ring_doorbell(gc, queue->gdma_dev->doorbell, queue->type, - queue->id, queue->head * GDMA_WQE_BU_SIZE, 1); + queue->id, queue->head * GDMA_WQE_BU_SIZE, 0); } void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit) -- cgit From f15fbe46f5ed473f547944ebafdff35372588fb5 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:10:55 +0800 Subject: net: atlantic: Remove unnecessary (void*) conversions No need cast (void*) to (struct hw_atl2_priv *). Signed-off-by: Wu Yunchuan Link: https://lore.kernel.org/r/20230717031055.54266-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 12 ++++++------ .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c index 5dfc751572ed..220400a633f5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c @@ -93,7 +93,7 @@ static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) static int hw_atl2_hw_reset(struct aq_hw_s *self) { - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; + struct hw_atl2_priv *priv = self->priv; int err; err = hw_atl2_utils_soft_reset(self); @@ -378,8 +378,8 @@ static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self) { - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; u8 *prio_tc_map = self->aq_nic_cfg->prio_tc_map; + struct hw_atl2_priv *priv = self->priv; u16 action; u8 index; int i; @@ -433,7 +433,7 @@ static void hw_atl2_hw_new_rx_filter_vlan_promisc(struct aq_hw_s *self, u16 off_action = (!promisc && !hw_atl_rpfl2promiscuous_mode_en_get(self)) ? HW_ATL2_ACTION_DROP : HW_ATL2_ACTION_DISABLE; - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; + struct hw_atl2_priv *priv = self->priv; u8 index; index = priv->art_base_index + HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX; @@ -445,7 +445,7 @@ static void hw_atl2_hw_new_rx_filter_vlan_promisc(struct aq_hw_s *self, static void hw_atl2_hw_new_rx_filter_promisc(struct aq_hw_s *self, bool promisc) { u16 off_action = promisc ? HW_ATL2_ACTION_DISABLE : HW_ATL2_ACTION_DROP; - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; + struct hw_atl2_priv *priv = self->priv; bool vlan_promisc_enable; u8 index; @@ -539,8 +539,8 @@ static int hw_atl2_hw_init(struct aq_hw_s *self, const u8 *mac_addr) [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, }; - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + struct hw_atl2_priv *priv = self->priv; u8 base_index, count; int err; @@ -770,7 +770,7 @@ static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) static int hw_atl2_hw_vlan_set(struct aq_hw_s *self, struct aq_rx_filter_vlan *aq_vlans) { - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; + struct hw_atl2_priv *priv = self->priv; u32 queue; u8 index; int i; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c index 674683b54304..52e2070a4a2f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c @@ -413,8 +413,8 @@ do { \ static int aq_a2_fw_update_stats(struct aq_hw_s *self) { - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; struct aq_stats_s *cs = &self->curr_stats; + struct hw_atl2_priv *priv = self->priv; struct statistics_s stats; struct version_s version; int err; -- cgit From 89c04d6c49c36f7bb6e5d2f7c90dd0634d7a1642 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:11:15 +0800 Subject: net: ppp: Remove unnecessary (void*) conversions No need cast (void*) to (struct sock *). Signed-off-by: Wu Yunchuan Reviewed-by: Guillaume Nault Link: https://lore.kernel.org/r/20230717031115.54432-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ppp/pppoe.c | 4 ++-- drivers/net/ppp/pptp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 3b79c603b936..ba8b6bd8233c 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -968,7 +968,7 @@ abort: ***********************************************************************/ static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) { - struct sock *sk = (struct sock *)chan->private; + struct sock *sk = chan->private; return __pppoe_xmit(sk, skb); } @@ -976,7 +976,7 @@ static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx, struct net_device_path *path, const struct ppp_channel *chan) { - struct sock *sk = (struct sock *)chan->private; + struct sock *sk = chan->private; struct pppox_sock *po = pppox_sk(sk); struct net_device *dev = po->pppoe_dev; diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 57d38b27812d..6833ef0c7930 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -148,7 +148,7 @@ static struct rtable *pptp_route_output(const struct pppox_sock *po, static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) { - struct sock *sk = (struct sock *) chan->private; + struct sock *sk = chan->private; struct pppox_sock *po = pppox_sk(sk); struct net *net = sock_net(sk); struct pptp_opt *opt = &po->proto.pptp; @@ -575,7 +575,7 @@ out: static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) { - struct sock *sk = (struct sock *) chan->private; + struct sock *sk = chan->private; struct pppox_sock *po = pppox_sk(sk); struct pptp_opt *opt = &po->proto.pptp; void __user *argp = (void __user *)arg; -- cgit From 14fbcad00fe51be25ff4c545836fdc518b69045a Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:11:28 +0800 Subject: net: hns3: remove unnecessary (void*) conversions. No need cast (void*) to (struct hns3_nic_priv *). Signed-off-by: Wu Yunchuan Reviewed-by: Hao Lan Link: https://lore.kernel.org/r/20230717031128.54557-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 407d30ee55d2..36858a72d771 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -569,8 +569,8 @@ static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data) static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data) { - struct hns3_nic_priv *nic_priv = (struct hns3_nic_priv *)handle->priv; struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hns3_nic_priv *nic_priv = handle->priv; struct hns3_enet_ring *ring; u8 *stat; int i, j; -- cgit From 406eb9cf6f6fc248bd898bef26ea34987c84f8cd Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:11:37 +0800 Subject: net: hns: Remove unnecessary (void*) conversions No need cast (void*) to (struct hns_mdio_device *). Signed-off-by: Wu Yunchuan Reviewed-by: Hao Lan Link: https://lore.kernel.org/r/20230717031137.54639-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hns_mdio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 9232caaf0bdc..409a89d80220 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -217,7 +217,7 @@ static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev, static int hns_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum, u16 data) { - struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + struct hns_mdio_device *mdio_dev = bus->priv; u16 reg = (u16)(regnum & 0xffff); u16 cmd_reg_cfg; int ret; @@ -259,7 +259,7 @@ static int hns_mdio_write_c22(struct mii_bus *bus, static int hns_mdio_write_c45(struct mii_bus *bus, int phy_id, int devad, int regnum, u16 data) { - struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + struct hns_mdio_device *mdio_dev = bus->priv; u16 reg = (u16)(regnum & 0xffff); u16 cmd_reg_cfg; int ret; @@ -312,7 +312,7 @@ static int hns_mdio_write_c45(struct mii_bus *bus, int phy_id, int devad, */ static int hns_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum) { - struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + struct hns_mdio_device *mdio_dev = bus->priv; u16 reg = (u16)(regnum & 0xffff); u16 reg_val; int ret; @@ -363,7 +363,7 @@ static int hns_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum) static int hns_mdio_read_c45(struct mii_bus *bus, int phy_id, int devad, int regnum) { - struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + struct hns_mdio_device *mdio_dev = bus->priv; u16 reg = (u16)(regnum & 0xffff); u16 reg_val; int ret; @@ -424,7 +424,7 @@ static int hns_mdio_read_c45(struct mii_bus *bus, int phy_id, int devad, */ static int hns_mdio_reset(struct mii_bus *bus) { - struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + struct hns_mdio_device *mdio_dev = bus->priv; const struct hns_mdio_sc_reg *sc_reg; int ret; -- cgit From c59cc2679accb9b6b2b50190cf484e036d9662c3 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:11:54 +0800 Subject: ice: remove unnecessary (void*) conversions No need cast (void*) to (struct ice_ring_container *). Signed-off-by: Wu Yunchuan Link: https://lore.kernel.org/r/20230717031154.54740-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/ice/ice_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 19a5e7f3a075..6d021597506f 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -6249,7 +6249,7 @@ static void ice_tx_dim_work(struct work_struct *work) u16 itr; dim = container_of(work, struct dim, work); - rc = (struct ice_ring_container *)dim->priv; + rc = dim->priv; WARN_ON(dim->profile_ix >= ARRAY_SIZE(tx_profile)); @@ -6269,7 +6269,7 @@ static void ice_rx_dim_work(struct work_struct *work) u16 itr; dim = container_of(work, struct dim, work); - rc = (struct ice_ring_container *)dim->priv; + rc = dim->priv; WARN_ON(dim->profile_ix >= ARRAY_SIZE(rx_profile)); -- cgit From 099090c6effc6b28b30c680b33903559bcaff6d0 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:12:04 +0800 Subject: ethernet: smsc: remove unnecessary (void*) conversions No need cast (voidd*) to (struct smsc911x_data *) or (struct smsc9420_pdata *). Signed-off-by: Wu Yunchuan Link: https://lore.kernel.org/r/20230717031204.54912-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/smsc/smsc911x.c | 4 ++-- drivers/net/ethernet/smsc/smsc9420.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 174dc8908b72..c362bff3cb83 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -552,7 +552,7 @@ static void smsc911x_mac_write(struct smsc911x_data *pdata, /* Get a phy register */ static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx) { - struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv; + struct smsc911x_data *pdata = bus->priv; unsigned long flags; unsigned int addr; int i, reg; @@ -591,7 +591,7 @@ out: static int smsc911x_mii_write(struct mii_bus *bus, int phyaddr, int regidx, u16 val) { - struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv; + struct smsc911x_data *pdata = bus->priv; unsigned long flags; unsigned int addr; int i, reg; diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index 71fbb358bb7d..3b26f1d86beb 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -102,7 +102,7 @@ static inline void smsc9420_pci_flush_write(struct smsc9420_pdata *pd) static int smsc9420_mii_read(struct mii_bus *bus, int phyaddr, int regidx) { - struct smsc9420_pdata *pd = (struct smsc9420_pdata *)bus->priv; + struct smsc9420_pdata *pd = bus->priv; unsigned long flags; u32 addr; int i, reg = -EIO; @@ -140,7 +140,7 @@ out: static int smsc9420_mii_write(struct mii_bus *bus, int phyaddr, int regidx, u16 val) { - struct smsc9420_pdata *pd = (struct smsc9420_pdata *)bus->priv; + struct smsc9420_pdata *pd = bus->priv; unsigned long flags; u32 addr; int i, reg = -EIO; -- cgit From 04115debedce8a14f4e293b5493ed7379a0d3cf8 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:12:12 +0800 Subject: net: mdio: Remove unnecessary (void*) conversions No need cast (void*) to (struct xgene_mdio_pdata *). Signed-off-by: Wu Yunchuan Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230717031212.54991-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/mdio/mdio-xgene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c index 7aafc221b5cf..683e8f8319ab 100644 --- a/drivers/net/mdio/mdio-xgene.c +++ b/drivers/net/mdio/mdio-xgene.c @@ -79,7 +79,7 @@ EXPORT_SYMBOL(xgene_mdio_wr_mac); int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) { - struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; + struct xgene_mdio_pdata *pdata = bus->priv; u32 data, done; u8 wait = 10; @@ -105,7 +105,7 @@ EXPORT_SYMBOL(xgene_mdio_rgmii_read); int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data) { - struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; + struct xgene_mdio_pdata *pdata = bus->priv; u32 val, done; u8 wait = 10; -- cgit From 9235e3bcc613e3c549fb4e5948b7d75294f9e2c9 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:12:21 +0800 Subject: can: ems_pci: Remove unnecessary (void*) conversions No need cast (void*) to (struct ems_pci_card *). Signed-off-by: Wu Yunchuan Acked-by: Marc Kleine-Budde Link: https://lore.kernel.org/r/20230717031221.55073-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/can/sja1000/ems_pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index c56e27223e5f..ac86640998a8 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -148,7 +148,7 @@ static void ems_pci_v1_write_reg(const struct sja1000_priv *priv, static void ems_pci_v1_post_irq(const struct sja1000_priv *priv) { - struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; + struct ems_pci_card *card = priv->priv; /* reset int flag of pita */ writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, @@ -168,7 +168,7 @@ static void ems_pci_v2_write_reg(const struct sja1000_priv *priv, static void ems_pci_v2_post_irq(const struct sja1000_priv *priv) { - struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; + struct ems_pci_card *card = priv->priv; writel(PLX_ICSR_ENA_CLR, card->conf_addr + PLX_ICSR); } @@ -186,7 +186,7 @@ static void ems_pci_v3_write_reg(const struct sja1000_priv *priv, static void ems_pci_v3_post_irq(const struct sja1000_priv *priv) { - struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; + struct ems_pci_card *card = priv->priv; writel(ASIX_LINTSR_INT0AC, card->conf_addr + ASIX_LINTSR); } -- cgit From 1d5123efdb917f102e30dba1cdd6c6912b85cdb9 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Mon, 17 Jul 2023 11:12:29 +0800 Subject: net: bna: Remove unnecessary (void*) conversions No need cast (void*) to (struct bnad_tx_info *) or (struct bnad_rx_info *). Signed-off-by: Wu Yunchuan Link: https://lore.kernel.org/r/20230717031229.55169-1-yunchuan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/brocade/bna/bnad.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index d6d90f9722a7..31191b520b58 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -1037,8 +1037,7 @@ bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb) static void bnad_cb_tx_stall(struct bnad *bnad, struct bna_tx *tx) { - struct bnad_tx_info *tx_info = - (struct bnad_tx_info *)tx->priv; + struct bnad_tx_info *tx_info = tx->priv; struct bna_tcb *tcb; u32 txq_id; int i; @@ -1056,7 +1055,7 @@ bnad_cb_tx_stall(struct bnad *bnad, struct bna_tx *tx) static void bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx) { - struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv; + struct bnad_tx_info *tx_info = tx->priv; struct bna_tcb *tcb; u32 txq_id; int i; @@ -1133,7 +1132,7 @@ bnad_tx_cleanup(struct delayed_work *work) static void bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx) { - struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv; + struct bnad_tx_info *tx_info = tx->priv; struct bna_tcb *tcb; int i; @@ -1149,7 +1148,7 @@ bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx) static void bnad_cb_rx_stall(struct bnad *bnad, struct bna_rx *rx) { - struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv; + struct bnad_rx_info *rx_info = rx->priv; struct bna_ccb *ccb; struct bnad_rx_ctrl *rx_ctrl; int i; @@ -1208,7 +1207,7 @@ bnad_rx_cleanup(void *work) static void bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx) { - struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv; + struct bnad_rx_info *rx_info = rx->priv; struct bna_ccb *ccb; struct bnad_rx_ctrl *rx_ctrl; int i; @@ -1231,7 +1230,7 @@ bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx) static void bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx) { - struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv; + struct bnad_rx_info *rx_info = rx->priv; struct bna_ccb *ccb; struct bna_rcb *rcb; struct bnad_rx_ctrl *rx_ctrl; -- cgit From 22d8e8d6338d17bc192559dad24d1e45be0f9795 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 14 Jul 2023 11:47:57 -0600 Subject: can: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/all/20230714174757.4060748-1-robh@kernel.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/grcan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 3174efdae271..6d3ba71a6a73 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -30,8 +30,9 @@ #include #include #include +#include #include -#include +#include #include #include -- cgit From 25000fc785b4cf034466ff547eabf2adcf1845bc Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Wed, 12 Jul 2023 14:20:46 +0200 Subject: can: xilinx_can: Add support for controller reset Add support for an optional reset for the CAN controller using the reset driver. If the CAN node contains the "resets" property, then this logic will perform CAN controller reset. Signed-off-by: Srinivas Neeli Signed-off-by: Michal Simek Link: https://lore.kernel.org/all/ab7e6503aa3343e39ead03c1797e765be6c50de2.1689164442.git.michal.simek@amd.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 4d3283db3a13..abe58f103043 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -30,6 +30,7 @@ #include #include #include +#include #define DRIVER_NAME "xilinx_can" @@ -200,6 +201,7 @@ struct xcan_devtype_data { * @can_clk: Pointer to struct clk * @devtype: Device type specific constants * @transceiver: Optional pointer to associated CAN transceiver + * @rstc: Pointer to reset control */ struct xcan_priv { struct can_priv can; @@ -218,6 +220,7 @@ struct xcan_priv { struct clk *can_clk; struct xcan_devtype_data devtype; struct phy *transceiver; + struct reset_control *rstc; }; /* CAN Bittiming constants as per Xilinx CAN specs */ @@ -1799,6 +1802,16 @@ static int xcan_probe(struct platform_device *pdev) priv->can.do_get_berr_counter = xcan_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_BERR_REPORTING; + priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) { + dev_err(&pdev->dev, "Cannot get CAN reset.\n"); + ret = PTR_ERR(priv->rstc); + goto err_free; + } + + ret = reset_control_reset(priv->rstc); + if (ret) + goto err_free; if (devtype->cantype == XAXI_CANFD) { priv->can.data_bittiming_const = @@ -1827,7 +1840,7 @@ static int xcan_probe(struct platform_device *pdev) /* Get IRQ for the device */ ret = platform_get_irq(pdev, 0); if (ret < 0) - goto err_free; + goto err_reset; ndev->irq = ret; @@ -1843,21 +1856,21 @@ static int xcan_probe(struct platform_device *pdev) if (IS_ERR(priv->can_clk)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->can_clk), "device clock not found\n"); - goto err_free; + goto err_reset; } priv->bus_clk = devm_clk_get(&pdev->dev, devtype->bus_clk_name); if (IS_ERR(priv->bus_clk)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->bus_clk), "bus clock not found\n"); - goto err_free; + goto err_reset; } transceiver = devm_phy_optional_get(&pdev->dev, NULL); if (IS_ERR(transceiver)) { ret = PTR_ERR(transceiver); dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); - goto err_free; + goto err_reset; } priv->transceiver = transceiver; @@ -1904,6 +1917,8 @@ static int xcan_probe(struct platform_device *pdev) err_disableclks: pm_runtime_put(priv->dev); pm_runtime_disable(&pdev->dev); +err_reset: + reset_control_assert(priv->rstc); err_free: free_candev(ndev); err: @@ -1920,9 +1935,11 @@ err: static void xcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct xcan_priv *priv = netdev_priv(ndev); unregister_candev(ndev); pm_runtime_disable(&pdev->dev); + reset_control_assert(priv->rstc); free_candev(ndev); } -- cgit From c2ad812956aeb3068f4e24cacdbe9d0847de2bc5 Mon Sep 17 00:00:00 2001 From: Jimmy Assarsson Date: Thu, 22 Jun 2023 17:11:52 +0200 Subject: can: kvaser_pciefd: Move hardware specific constants and functions into a driver_data struct Move hardware specific address offsets, interrupt masks and DMA mapping function, into struct kvaser_pciefd_driver_data, as a step towards adding new devices based on different hardware. Co-developed-by: Martin Jocic Signed-off-by: Martin Jocic Signed-off-by: Jimmy Assarsson Link: https://lore.kernel.org/all/20230622151153.294844-2-extja@kvaser.com [mkl: mark structs as static] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/kvaser_pciefd.c | 230 +++++++++++++++++++++++++++------------- 1 file changed, 154 insertions(+), 76 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index db6256f2b1b3..3d478e6fb73b 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -33,37 +33,17 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) #define KVASER_PCIEFD_VENDOR 0x1a07 +/* Altera based devices */ #define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d #define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e #define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f #define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 #define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 -/* PCIe IRQ registers */ -#define KVASER_PCIEFD_IRQ_REG 0x40 -#define KVASER_PCIEFD_IEN_REG 0x50 -/* DMA address translation map register base */ -#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 -/* Loopback control register */ -#define KVASER_PCIEFD_LOOP_REG 0x1f000 -/* System identification and information registers */ -#define KVASER_PCIEFD_SYSID_BASE 0x1f020 -#define KVASER_PCIEFD_SYSID_VERSION_REG (KVASER_PCIEFD_SYSID_BASE + 0x8) -#define KVASER_PCIEFD_SYSID_CANFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0xc) -#define KVASER_PCIEFD_SYSID_BUSFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0x10) -#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14) -/* Shared receive buffer registers */ -#define KVASER_PCIEFD_SRB_BASE 0x1f200 -#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4) -#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200) -#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204) -#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c) -#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210) -#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214) -#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218) +/* Altera SerDes Enable 64-bit DMA address translation */ +#define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0) + /* Kvaser KCAN CAN controller registers */ -#define KVASER_PCIEFD_KCAN0_BASE 0x10000 -#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 #define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 @@ -77,13 +57,20 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 #define KVASER_PCIEFD_KCAN_PWM_REG 0x430 - -/* PCI interrupt fields */ -#define KVASER_PCIEFD_IRQ_SRB BIT(4) -#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0) - -/* Enable 64-bit DMA address translation */ -#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) +/* System identification and information registers */ +#define KVASER_PCIEFD_SYSID_VERSION_REG 0x8 +#define KVASER_PCIEFD_SYSID_CANFREQ_REG 0xc +#define KVASER_PCIEFD_SYSID_BUSFREQ_REG 0x10 +#define KVASER_PCIEFD_SYSID_BUILD_REG 0x14 +/* Shared receive buffer FIFO registers */ +#define KVASER_PCIEFD_SRB_FIFO_LAST_REG 0x1f4 +/* Shared receive buffer registers */ +#define KVASER_PCIEFD_SRB_CMD_REG 0x0 +#define KVASER_PCIEFD_SRB_IEN_REG 0x04 +#define KVASER_PCIEFD_SRB_IRQ_REG 0x0c +#define KVASER_PCIEFD_SRB_STAT_REG 0x10 +#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG 0x14 +#define KVASER_PCIEFD_SRB_CTRL_REG 0x18 /* System build information fields */ #define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24) @@ -253,7 +240,92 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); /* KCAN Error detected packet, second word */ #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) +/* Macros for calculating addresses of registers */ +#define KVASER_PCIEFD_GET_BLOCK_ADDR(pcie, block) \ + ((pcie)->reg_base + (pcie)->driver_data->address_offset->block) +#define KVASER_PCIEFD_PCI_IEN_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_ien)) +#define KVASER_PCIEFD_PCI_IRQ_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_irq)) +#define KVASER_PCIEFD_SERDES_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), serdes)) +#define KVASER_PCIEFD_SYSID_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), sysid)) +#define KVASER_PCIEFD_LOOPBACK_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), loopback)) +#define KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb_fifo)) +#define KVASER_PCIEFD_SRB_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb)) +#define KVASER_PCIEFD_KCAN_CH0_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch0)) +#define KVASER_PCIEFD_KCAN_CH1_ADDR(pcie) \ + (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch1)) +#define KVASER_PCIEFD_KCAN_CHANNEL_SPAN(pcie) \ + (KVASER_PCIEFD_KCAN_CH1_ADDR((pcie)) - KVASER_PCIEFD_KCAN_CH0_ADDR((pcie))) +#define KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i) \ + (KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)) + (i) * KVASER_PCIEFD_KCAN_CHANNEL_SPAN((pcie))) + struct kvaser_pciefd; +static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, + dma_addr_t addr, int index); + +struct kvaser_pciefd_address_offset { + u32 serdes; + u32 pci_ien; + u32 pci_irq; + u32 sysid; + u32 loopback; + u32 kcan_srb_fifo; + u32 kcan_srb; + u32 kcan_ch0; + u32 kcan_ch1; +}; + +struct kvaser_pciefd_dev_ops { + void (*kvaser_pciefd_write_dma_map)(struct kvaser_pciefd *pcie, + dma_addr_t addr, int index); +}; + +struct kvaser_pciefd_irq_mask { + u32 kcan_rx0; + u32 kcan_tx[KVASER_PCIEFD_MAX_CAN_CHANNELS]; + u32 all; +}; + +struct kvaser_pciefd_driver_data { + const struct kvaser_pciefd_address_offset *address_offset; + const struct kvaser_pciefd_irq_mask *irq_mask; + const struct kvaser_pciefd_dev_ops *ops; +}; + +static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_offset = { + .serdes = 0x1000, + .pci_ien = 0x50, + .pci_irq = 0x40, + .sysid = 0x1f020, + .loopback = 0x1f000, + .kcan_srb_fifo = 0x1f200, + .kcan_srb = 0x1f400, + .kcan_ch0 = 0x10000, + .kcan_ch1 = 0x11000, +}; + +static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = { + .kcan_rx0 = BIT(4), + .kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) }, + .all = GENMASK(4, 0), +}; + +static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = { + .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera, +}; + +static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = { + .address_offset = &kvaser_pciefd_altera_address_offset, + .irq_mask = &kvaser_pciefd_altera_irq_mask, + .ops = &kvaser_pciefd_altera_dev_ops, +}; struct kvaser_pciefd_can { struct can_priv can; @@ -273,6 +345,7 @@ struct kvaser_pciefd { struct pci_dev *pci; void __iomem *reg_base; struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS]; + const struct kvaser_pciefd_driver_data *driver_data; void *dma_data[KVASER_PCIEFD_DMA_COUNT]; u8 nr_channels; u32 bus_freq; @@ -305,18 +378,23 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { static struct pci_device_id kvaser_pciefd_id_table[] = { { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, { 0, @@ -783,8 +861,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) can = netdev_priv(netdev); netdev->netdev_ops = &kvaser_pciefd_netdev_ops; netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops; - can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + - i * KVASER_PCIEFD_KCAN_BASE_OFFSET; + can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i); can->kv_pcie = pcie; can->cmd_seq = 0; can->err_rep_cnt = 0; @@ -865,20 +942,22 @@ static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie) return 0; } -static void kvaser_pciefd_write_dma_map(struct kvaser_pciefd *pcie, - dma_addr_t addr, int offset) +static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, + dma_addr_t addr, int index) { + void __iomem *serdes_base; u32 word1, word2; #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT - word1 = addr | KVASER_PCIEFD_64BIT_DMA_BIT; + word1 = addr | KVASER_PCIEFD_ALTERA_DMA_64BIT; word2 = addr >> 32; #else word1 = addr; word2 = 0; #endif - iowrite32(word1, pcie->reg_base + offset); - iowrite32(word2, pcie->reg_base + offset + 4); + serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x8 * index; + iowrite32(word1, serdes_base); + iowrite32(word2, serdes_base + 0x4); } static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) @@ -889,10 +968,8 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT]; /* Disable the DMA */ - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { - unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i; - pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev, KVASER_PCIEFD_DMA_SIZE, &dma_addr[i], @@ -903,24 +980,25 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) KVASER_PCIEFD_DMA_SIZE); return -ENOMEM; } - kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); + pcie->driver_data->ops->kvaser_pciefd_write_dma_map(pcie, dma_addr[i], i); } /* Reset Rx FIFO, and both DMA buffers */ iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | KVASER_PCIEFD_SRB_CMD_RDB1, - pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); /* Empty Rx FIFO */ srb_packet_count = FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK, - ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); + ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); while (srb_packet_count) { /* Drop current packet in FIFO */ - ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG); + ioread32(KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) + KVASER_PCIEFD_SRB_FIFO_LAST_REG); srb_packet_count--; } - srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); + srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG); if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) { dev_err(&pcie->pci->dev, "DMA not idle before enabling\n"); return -EIO; @@ -928,7 +1006,7 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) /* Enable the DMA */ iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE, - pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); return 0; } @@ -937,30 +1015,29 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) { u32 version, srb_status, build; - version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); + version = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_VERSION_REG); pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS, FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version)); - build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); + build = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUILD_REG); dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n", FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version), FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version), FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build)); - srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); + srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG); if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n"); return -ENODEV; } - pcie->bus_freq = ioread32(pcie->reg_base + - KVASER_PCIEFD_SYSID_BUSFREQ_REG); - pcie->freq = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_CANFREQ_REG); + pcie->bus_freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUSFREQ_REG); + pcie->freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_CANFREQ_REG); pcie->freq_to_ticks_div = pcie->freq / 1000000; if (pcie->freq_to_ticks_div == 0) pcie->freq_to_ticks_div = 1; /* Turn off all loopback functionality */ - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); + iowrite32(0, KVASER_PCIEFD_LOOPBACK_ADDR(pcie)); return 0; } @@ -1430,21 +1507,20 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) { - u32 irq; + u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); - irq = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) { kvaser_pciefd_read_buffer(pcie, 0); /* Reset DMA buffer 0 */ iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, - pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); } if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) { kvaser_pciefd_read_buffer(pcie, 1); /* Reset DMA buffer 1 */ iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, - pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); } if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 || @@ -1453,7 +1529,7 @@ static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) irq & KVASER_PCIEFD_SRB_IRQ_DUF1) dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); - iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); + iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); } static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) @@ -1479,15 +1555,14 @@ static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) { struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev; - u32 board_irq; + const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask; + u32 board_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie)); int i; - board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); - - if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK)) + if (!(board_irq & irq_mask->all)) return IRQ_NONE; - if (board_irq & KVASER_PCIEFD_IRQ_SRB) + if (board_irq & irq_mask->kcan_rx0) kvaser_pciefd_receive_irq(pcie); for (i = 0; i < pcie->nr_channels; i++) { @@ -1498,7 +1573,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) } /* Check that mask matches channel (i) IRQ mask */ - if (board_irq & (1 << i)) + if (board_irq & irq_mask->kcan_tx[i]) kvaser_pciefd_transmit_irq(pcie->can[i]); } @@ -1525,6 +1600,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, { int err; struct kvaser_pciefd *pcie; + const struct kvaser_pciefd_irq_mask *irq_mask; + void __iomem *irq_en_base; pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); if (!pcie) @@ -1532,6 +1609,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, pcie); pcie->pci = pdev; + pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data; + irq_mask = pcie->driver_data->irq_mask; err = pci_enable_device(pdev); if (err) @@ -1567,22 +1646,21 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, goto err_teardown_can_ctrls; iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1, - pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 | KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 | KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, - pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IEN_REG); /* Enable PCI interrupts */ - iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK, - pcie->reg_base + KVASER_PCIEFD_IEN_REG); - + irq_en_base = KVASER_PCIEFD_PCI_IEN_ADDR(pcie); + iowrite32(irq_mask->all, irq_en_base); /* Ready the DMA buffers */ iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, - pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, - pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); + KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); err = kvaser_pciefd_reg_candev(pcie); if (err) @@ -1592,12 +1670,12 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, err_free_irq: /* Disable PCI interrupts */ - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); + iowrite32(0, irq_en_base); free_irq(pcie->pci->irq, pcie); err_teardown_can_ctrls: kvaser_pciefd_teardown_can_ctrls(pcie); - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); + iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); pci_clear_master(pdev); err_pci_iounmap: @@ -1636,8 +1714,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev) kvaser_pciefd_remove_all_ctrls(pcie); /* Disable interrupts */ - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); + iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); + iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie)); free_irq(pcie->pci->irq, pcie); -- cgit From f33ad6776b2fb8005c954fa1f8b88125260c190f Mon Sep 17 00:00:00 2001 From: Jimmy Assarsson Date: Thu, 22 Jun 2023 17:11:53 +0200 Subject: can: kvaser_pciefd: Add support for new Kvaser pciefd devices Add support for new Kvaser pciefd devices, based on SmartFusion2 SoC. Signed-off-by: Jimmy Assarsson Link: https://lore.kernel.org/all/20230622151153.294844-3-extja@kvaser.com [mkl: mark structs as static] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 5 +++ drivers/net/can/kvaser_pciefd.c | 77 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index a5c5036dfb94..18e4a6e94ba9 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -160,8 +160,13 @@ config CAN_KVASER_PCIEFD Kvaser PCIEcan 4xHS Kvaser PCIEcan 2xHS v2 Kvaser PCIEcan HS v2 + Kvaser PCIEcan 1xCAN v3 + Kvaser PCIEcan 2xCAN v3 + Kvaser PCIEcan 4xCAN v2 Kvaser Mini PCI Express HS v2 Kvaser Mini PCI Express 2xHS v2 + Kvaser Mini PCI Express 1xCAN v3 + Kvaser Mini PCI Express 2xCAN v3 config CAN_SLCAN tristate "Serial / USB serial CAN Adaptors (slcan)" diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index 3d478e6fb73b..a57005faa04f 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause /* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved. * Parts of this driver are based on the following: - * - Kvaser linux pciefd driver (version 5.25) + * - Kvaser linux pciefd driver (version 5.42) * - PEAK linux canfd driver */ @@ -40,9 +40,19 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 #define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 +/* SmartFusion2 based devices */ +#define KVASER_PCIEFD_2CAN_V3_DEVICE_ID 0x0012 +#define KVASER_PCIEFD_1CAN_V3_DEVICE_ID 0x0013 +#define KVASER_PCIEFD_4CAN_V2_DEVICE_ID 0x0014 +#define KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID 0x0015 +#define KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID 0x0016 + /* Altera SerDes Enable 64-bit DMA address translation */ #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0) +/* SmartFusion2 SerDes LSB address translation mask */ +#define KVASER_PCIEFD_SF2_DMA_LSB_MASK GENMASK(31, 12) + /* Kvaser KCAN CAN controller registers */ #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 @@ -269,6 +279,8 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); struct kvaser_pciefd; static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, dma_addr_t addr, int index); +static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie, + dma_addr_t addr, int index); struct kvaser_pciefd_address_offset { u32 serdes; @@ -311,22 +323,50 @@ static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_of .kcan_ch1 = 0x11000, }; +static const struct kvaser_pciefd_address_offset kvaser_pciefd_sf2_address_offset = { + .serdes = 0x280c8, + .pci_ien = 0x102004, + .pci_irq = 0x102008, + .sysid = 0x100000, + .loopback = 0x103000, + .kcan_srb_fifo = 0x120000, + .kcan_srb = 0x121000, + .kcan_ch0 = 0x140000, + .kcan_ch1 = 0x142000, +}; + static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = { .kcan_rx0 = BIT(4), .kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) }, .all = GENMASK(4, 0), }; +static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = { + .kcan_rx0 = BIT(4), + .kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) }, + .all = GENMASK(19, 16) | BIT(4), +}; + static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = { .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera, }; +static const struct kvaser_pciefd_dev_ops kvaser_pciefd_sf2_dev_ops = { + .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_sf2, +}; + static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = { .address_offset = &kvaser_pciefd_altera_address_offset, .irq_mask = &kvaser_pciefd_altera_irq_mask, .ops = &kvaser_pciefd_altera_dev_ops, }; +static const struct kvaser_pciefd_driver_data kvaser_pciefd_sf2_driver_data = { + .address_offset = &kvaser_pciefd_sf2_address_offset, + .irq_mask = &kvaser_pciefd_sf2_irq_mask, + .ops = &kvaser_pciefd_sf2_dev_ops, +}; + struct kvaser_pciefd_can { struct can_priv can; struct kvaser_pciefd *kv_pcie; @@ -396,6 +436,26 @@ static struct pci_device_id kvaser_pciefd_id_table[] = { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2CAN_V3_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_1CAN_V3_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4CAN_V2_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID), + .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, + }, { 0, }, @@ -960,6 +1020,21 @@ static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, iowrite32(word2, serdes_base + 0x4); } +static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie, + dma_addr_t addr, int index) +{ + void __iomem *serdes_base; + u32 lsb = addr & KVASER_PCIEFD_SF2_DMA_LSB_MASK; + u32 msb = 0x0; + +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + msb = addr >> 32; +#endif + serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x10 * index; + iowrite32(lsb, serdes_base); + iowrite32(msb, serdes_base + 0x4); +} + static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) { int i; -- cgit From 03df47c1bb392b795bcecb6953dcc49199d33b2a Mon Sep 17 00:00:00 2001 From: Mao Zhu Date: Wed, 19 Jul 2023 00:25:23 +0800 Subject: can: ucan: Remove repeated word Delete one of repeated word 'information' in comment. Signed-off-by: Mao Zhu Link: https://lore.kernel.org/all/20230718163718.461137-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/ucan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c index a0f7bcec719c..39a63b7313a4 100644 --- a/drivers/net/can/usb/ucan.c +++ b/drivers/net/can/usb/ucan.c @@ -284,7 +284,7 @@ struct ucan_priv { */ spinlock_t echo_skb_lock; - /* usb device information information */ + /* usb device information */ u8 intf_index; u8 in_ep_addr; u8 out_ep_addr; -- cgit From d977e1c8e3a143bceb63a0042890f4a0268a9990 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 17 Jul 2023 11:12:27 +0300 Subject: vxlan: Add support for nexthop ID metadata VXLAN FDB entries can point to FDB nexthop objects. Each such object includes the IP address(es) of remote VTEP(s) via which the target host is accessible. Example: # ip nexthop add id 1 via 192.0.2.1 fdb # ip nexthop add id 2 via 192.0.2.17 fdb # ip nexthop add id 1000 group 1/2 fdb # bridge fdb add 00:11:22:33:44:55 dev vx0 self static nhid 1000 src_vni 10020 This is useful for EVPN multihoming where a single host can be connected to multiple VTEPs. The source VTEP will calculate the flow hash of the skb and forward it towards the IP address of one of the VTEPs member in the nexthop group. There are cases where an external entity (e.g., the bridge driver) can provide not only the tunnel ID (i.e., VNI) of the skb, but also the ID of the nexthop object via which the skb should be forwarded. Therefore, in order to support such cases, when the VXLAN device is in external / collect metadata mode and the tunnel info attached to the skb is of bridge type, extract the nexthop ID from the tunnel info. If the ID is valid (i.e., non-zero), forward the skb via the nexthop object associated with the ID, as if the skb hit an FDB entry associated with this ID. Signed-off-by: Ido Schimmel Acked-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/vxlan/vxlan_core.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 78744549c1b3..10a4dbd50710 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2672,6 +2672,45 @@ drop: dev_kfree_skb(skb); } +static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev, + u32 nhid, __be32 vni) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst nh_rdst; + struct nexthop *nh; + bool do_xmit; + u32 hash; + + memset(&nh_rdst, 0, sizeof(struct vxlan_rdst)); + hash = skb_get_hash(skb); + + rcu_read_lock(); + nh = nexthop_find_by_id(dev_net(dev), nhid); + if (unlikely(!nh || !nexthop_is_fdb(nh) || !nexthop_is_multipath(nh))) { + rcu_read_unlock(); + goto drop; + } + do_xmit = vxlan_fdb_nh_path_select(nh, hash, &nh_rdst); + rcu_read_unlock(); + + if (vxlan->cfg.saddr.sa.sa_family != nh_rdst.remote_ip.sa.sa_family) + goto drop; + + if (likely(do_xmit)) + vxlan_xmit_one(skb, dev, vni, &nh_rdst, false); + else + goto drop; + + return NETDEV_TX_OK; + +drop: + dev->stats.tx_dropped++; + vxlan_vnifilter_count(netdev_priv(dev), vni, NULL, + VXLAN_VNI_STATS_TX_DROPS, 0); + dev_kfree_skb(skb); + return NETDEV_TX_OK; +} + /* Transmit local packets over Vxlan * * Outer IP header inherits ECN and DF from inner header. @@ -2687,6 +2726,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) struct vxlan_fdb *f; struct ethhdr *eth; __be32 vni = 0; + u32 nhid = 0; info = skb_tunnel_info(skb); @@ -2696,6 +2736,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) if (info && info->mode & IP_TUNNEL_INFO_BRIDGE && info->mode & IP_TUNNEL_INFO_TX) { vni = tunnel_id_to_key32(info->key.tun_id); + nhid = info->key.nhid; } else { if (info && info->mode & IP_TUNNEL_INFO_TX) vxlan_xmit_one(skb, dev, vni, NULL, false); @@ -2723,6 +2764,9 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) #endif } + if (nhid) + return vxlan_xmit_nhid(skb, dev, nhid, vni); + if (vxlan->cfg.flags & VXLAN_F_MDB) { struct vxlan_mdb_entry *mdb_entry; -- cgit From 47448ff2d5c7715d9c06a27aa6d1b1f5ad1ff3db Mon Sep 17 00:00:00 2001 From: Rohan G Thomas Date: Mon, 17 Jul 2023 20:06:03 +0800 Subject: net: stmmac: xgmac: Fix L3L4 filter count Get the exact count of L3L4 filters when the L3L4FNUM field of HW_FEATURE1 register is >= 8. If L3L4FNUM < 8, then the number of L3L4 filters supported by XGMAC is equal to L3L4FNUM. From L3L4FNUM >= 8 the number of L3L4 filters goes on like 8, 16, 32, ... Current maximum of L3L4FNUM = 10. Also, fix the XGMAC_IDDR bitmask of L3L4_ADDR_CTRL register. IDDR field starts from the 8th bit of the L3L4_ADDR_CTRL register. IDDR[3:0] indicates the type of L3L4 filter register while IDDR[8:4] indicates the filter number (0 to 31). So overall 9 bits are used for IDDR (i.e. L3L4_ADDR_CTRL[16:8]) to address the registers of all the filters. Currently, XGMAC_IDDR is GENMASK(15,8), causing issues accessing L3L4 filters above 15 for those XGMACs configured with more than 16 L3L4 filters. Signed-off-by: Rohan G Thomas Reviewed-by: Andy Shevchenko Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 1913385df685..153321fe42c3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -165,7 +165,7 @@ #define XGMAC_DCS_SHIFT 16 #define XGMAC_ADDRx_LOW(x) (0x00000304 + (x) * 0x8) #define XGMAC_L3L4_ADDR_CTRL 0x00000c00 -#define XGMAC_IDDR GENMASK(15, 8) +#define XGMAC_IDDR GENMASK(16, 8) #define XGMAC_IDDR_SHIFT 8 #define XGMAC_IDDR_FNUM 4 #define XGMAC_TT BIT(1) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 070bd912580b..df5af52fd1a1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -408,6 +408,16 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature 1 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); dma_cap->l3l4fnum = (hw_cap & XGMAC_HWFEAT_L3L4FNUM) >> 27; + /* If L3L4FNUM < 8, then the number of L3L4 filters supported by + * XGMAC is equal to L3L4FNUM. From L3L4FNUM >= 8 the number of + * L3L4 filters goes on like 8, 16, 32, ... Current maximum of + * L3L4FNUM = 10. + */ + if (dma_cap->l3l4fnum >= 8 && dma_cap->l3l4fnum <= 10) + dma_cap->l3l4fnum = 8 << (dma_cap->l3l4fnum - 8); + else if (dma_cap->l3l4fnum > 10) + dma_cap->l3l4fnum = 32; + dma_cap->hash_tb_sz = (hw_cap & XGMAC_HWFEAT_HASHTBLSZ) >> 24; dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20; dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18; -- cgit From b16b50476714c75ff99dba23b8ee96179197e31e Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Mon, 17 Jul 2023 15:53:30 +0200 Subject: gtp: Set TOS and routing scope independently for fib lookups. There's no reason for setting the RTO_ONLINK flag in ->flowi4_tos as RT_CONN_FLAGS() does. We can easily set ->flowi4_scope properly instead. This makes the code more explicit and will allow to convert ->flowi4_tos to dscp_t in the future. Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- drivers/net/gtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index acb20ad4e37e..144ec626230d 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -243,7 +243,8 @@ static struct rtable *ip4_route_output_gtp(struct flowi4 *fl4, fl4->flowi4_oif = sk->sk_bound_dev_if; fl4->daddr = daddr; fl4->saddr = saddr; - fl4->flowi4_tos = RT_CONN_FLAGS(sk); + fl4->flowi4_tos = ip_sock_rt_tos(sk); + fl4->flowi4_scope = ip_sock_rt_scope(sk); fl4->flowi4_proto = sk->sk_protocol; return ip_route_output_key(sock_net(sk), fl4); -- cgit From 1bbc04de607babfca7374d374960e20ebb20813f Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Wed, 19 Jul 2023 15:24:09 +0200 Subject: ice: xsk: add RX multi-buffer support This support is strongly inspired by work that introduced multi-buffer support to regular Rx data path in ice. There are some differences, though. When adding a frag, besides adding it to skb_shared_info, use also fresh xsk_buff_add_frag() helper. Reason for doing both things is that we can not rule out the fact that AF_XDP pipeline could use XDP program that needs to access frame fragments. Without them being in skb_shared_info it will not be possible. Another difference is that XDP_PASS has to allocate a new pages for each frags and copy contents from memory backed by xsk_buff_pool. chain_len that is used for programming HW Rx descriptors no longer has to be limited to 1 when xsk_pool is present - remove this restriction. Signed-off-by: Maciej Fijalkowski Link: https://lore.kernel.org/r/20230719132421.584801-13-maciej.fijalkowski@intel.com Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/intel/ice/ice_base.c | 9 +- drivers/net/ethernet/intel/ice/ice_xsk.c | 136 ++++++++++++++++++++++-------- 2 files changed, 102 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 4a12316f7b46..3367b8ba9851 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -408,7 +408,6 @@ static unsigned int ice_rx_offset(struct ice_rx_ring *rx_ring) */ static int ice_setup_rx_ctx(struct ice_rx_ring *ring) { - int chain_len = ICE_MAX_CHAINED_RX_BUFS; struct ice_vsi *vsi = ring->vsi; u32 rxdid = ICE_RXDID_FLEX_NIC; struct ice_rlan_ctx rlan_ctx; @@ -472,17 +471,11 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring) */ rlan_ctx.showiv = 0; - /* For AF_XDP ZC, we disallow packets to span on - * multiple buffers, thus letting us skip that - * handling in the fast-path. - */ - if (ring->xsk_pool) - chain_len = 1; /* Max packet size for this queue - must not be set to a larger value * than 5 x DBUF */ rlan_ctx.rxmax = min_t(u32, vsi->max_frame, - chain_len * ring->rx_buf_len); + ICE_MAX_CHAINED_RX_BUFS * ring->rx_buf_len); /* Rx queue threshold in units of 64 */ rlan_ctx.lrxqthresh = 1; diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index a7fe2b4ce655..91cdd5e4790d 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -545,19 +545,6 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) return __ice_alloc_rx_bufs_zc(rx_ring, leftover); } -/** - * ice_bump_ntc - Bump the next_to_clean counter of an Rx ring - * @rx_ring: Rx ring - */ -static void ice_bump_ntc(struct ice_rx_ring *rx_ring) -{ - int ntc = rx_ring->next_to_clean + 1; - - ntc = (ntc < rx_ring->count) ? ntc : 0; - rx_ring->next_to_clean = ntc; - prefetch(ICE_RX_DESC(rx_ring, ntc)); -} - /** * ice_construct_skb_zc - Create an sk_buff from zero-copy buffer * @rx_ring: Rx ring @@ -572,8 +559,14 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp) { unsigned int totalsize = xdp->data_end - xdp->data_meta; unsigned int metasize = xdp->data - xdp->data_meta; + struct skb_shared_info *sinfo = NULL; struct sk_buff *skb; + u32 nr_frags = 0; + if (unlikely(xdp_buff_has_frags(xdp))) { + sinfo = xdp_get_shared_info_from_buff(xdp); + nr_frags = sinfo->nr_frags; + } net_prefetch(xdp->data_meta); skb = __napi_alloc_skb(&rx_ring->q_vector->napi, totalsize, @@ -589,6 +582,29 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp) __skb_pull(skb, metasize); } + if (likely(!xdp_buff_has_frags(xdp))) + goto out; + + for (int i = 0; i < nr_frags; i++) { + struct skb_shared_info *skinfo = skb_shinfo(skb); + skb_frag_t *frag = &sinfo->frags[i]; + struct page *page; + void *addr; + + page = dev_alloc_page(); + if (!page) { + dev_kfree_skb(skb); + return NULL; + } + addr = page_to_virt(page); + + memcpy(addr, skb_frag_page(frag), skb_frag_size(frag)); + + __skb_fill_page_desc_noacc(skinfo, skinfo->nr_frags++, + addr, 0, skb_frag_size(frag)); + } + +out: xsk_buff_free(xdp); return skb; } @@ -752,6 +768,34 @@ out_failure: return result; } +static int +ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first, + struct xdp_buff *xdp, const unsigned int size) +{ + struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first); + + if (!size) + return 0; + + if (!xdp_buff_has_frags(first)) { + sinfo->nr_frags = 0; + sinfo->xdp_frags_size = 0; + xdp_buff_set_frags_flag(first); + } + + if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { + xsk_buff_free(first); + return -ENOMEM; + } + + __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, + virt_to_page(xdp->data_hard_start), 0, size); + sinfo->xdp_frags_size += size; + xsk_buff_add_frag(xdp); + + return 0; +} + /** * ice_clean_rx_irq_zc - consumes packets from the hardware ring * @rx_ring: AF_XDP Rx ring @@ -762,9 +806,14 @@ out_failure: int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) { unsigned int total_rx_bytes = 0, total_rx_packets = 0; + struct xsk_buff_pool *xsk_pool = rx_ring->xsk_pool; + u32 ntc = rx_ring->next_to_clean; + u32 ntu = rx_ring->next_to_use; + struct xdp_buff *first = NULL; struct ice_tx_ring *xdp_ring; unsigned int xdp_xmit = 0; struct bpf_prog *xdp_prog; + u32 cnt = rx_ring->count; bool failure = false; int entries_to_alloc; @@ -774,6 +823,9 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) xdp_prog = READ_ONCE(rx_ring->xdp_prog); xdp_ring = rx_ring->xdp_ring; + if (ntc != rx_ring->first_desc) + first = *ice_xdp_buf(rx_ring, rx_ring->first_desc); + while (likely(total_rx_packets < (unsigned int)budget)) { union ice_32b_rx_flex_desc *rx_desc; unsigned int size, xdp_res = 0; @@ -783,7 +835,7 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) u16 vlan_tag = 0; u16 rx_ptype; - rx_desc = ICE_RX_DESC(rx_ring, rx_ring->next_to_clean); + rx_desc = ICE_RX_DESC(rx_ring, ntc); stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S); if (!ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits)) @@ -795,51 +847,61 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) */ dma_rmb(); - if (unlikely(rx_ring->next_to_clean == rx_ring->next_to_use)) + if (unlikely(ntc == ntu)) break; - xdp = *ice_xdp_buf(rx_ring, rx_ring->next_to_clean); + xdp = *ice_xdp_buf(rx_ring, ntc); size = le16_to_cpu(rx_desc->wb.pkt_len) & ICE_RX_FLX_DESC_PKT_LEN_M; - if (!size) { - xdp->data = NULL; - xdp->data_end = NULL; - xdp->data_hard_start = NULL; - xdp->data_meta = NULL; - goto construct_skb; - } xsk_buff_set_size(xdp, size); - xsk_buff_dma_sync_for_cpu(xdp, rx_ring->xsk_pool); + xsk_buff_dma_sync_for_cpu(xdp, xsk_pool); + + if (!first) { + first = xdp; + xdp_buff_clear_frags_flag(first); + } else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) { + break; + } + + if (++ntc == cnt) + ntc = 0; + + if (ice_is_non_eop(rx_ring, rx_desc)) + continue; - xdp_res = ice_run_xdp_zc(rx_ring, xdp, xdp_prog, xdp_ring); + xdp_res = ice_run_xdp_zc(rx_ring, first, xdp_prog, xdp_ring); if (likely(xdp_res & (ICE_XDP_TX | ICE_XDP_REDIR))) { xdp_xmit |= xdp_res; } else if (xdp_res == ICE_XDP_EXIT) { failure = true; + first = NULL; + rx_ring->first_desc = ntc; break; } else if (xdp_res == ICE_XDP_CONSUMED) { - xsk_buff_free(xdp); + xsk_buff_free(first); } else if (xdp_res == ICE_XDP_PASS) { goto construct_skb; } - total_rx_bytes += size; + total_rx_bytes += xdp_get_buff_len(first); total_rx_packets++; - ice_bump_ntc(rx_ring); + first = NULL; + rx_ring->first_desc = ntc; continue; construct_skb: /* XDP_PASS path */ - skb = ice_construct_skb_zc(rx_ring, xdp); + skb = ice_construct_skb_zc(rx_ring, first); if (!skb) { rx_ring->ring_stats->rx_stats.alloc_buf_failed++; break; } - ice_bump_ntc(rx_ring); + first = NULL; + rx_ring->first_desc = ntc; if (eth_skb_pad(skb)) { skb = NULL; @@ -858,18 +920,22 @@ construct_skb: ice_receive_skb(rx_ring, skb, vlan_tag); } - entries_to_alloc = ICE_DESC_UNUSED(rx_ring); + rx_ring->next_to_clean = ntc; + entries_to_alloc = ICE_RX_DESC_UNUSED(rx_ring); if (entries_to_alloc > ICE_RING_QUARTER(rx_ring)) failure |= !ice_alloc_rx_bufs_zc(rx_ring, entries_to_alloc); ice_finalize_xdp_rx(xdp_ring, xdp_xmit, 0); ice_update_rx_ring_stats(rx_ring, total_rx_packets, total_rx_bytes); - if (xsk_uses_need_wakeup(rx_ring->xsk_pool)) { - if (failure || rx_ring->next_to_clean == rx_ring->next_to_use) - xsk_set_rx_need_wakeup(rx_ring->xsk_pool); + if (xsk_uses_need_wakeup(xsk_pool)) { + /* ntu could have changed when allocating entries above, so + * use rx_ring value instead of stack based one + */ + if (failure || ntc == rx_ring->next_to_use) + xsk_set_rx_need_wakeup(xsk_pool); else - xsk_clear_rx_need_wakeup(rx_ring->xsk_pool); + xsk_clear_rx_need_wakeup(xsk_pool); return (int)total_rx_packets; } -- cgit From 1c9ba9c146589ff3d679b21e5e56b2d25ef43edd Mon Sep 17 00:00:00 2001 From: Tirthendu Sarkar Date: Wed, 19 Jul 2023 15:24:10 +0200 Subject: i40e: xsk: add RX multi-buffer support This patch is inspired from the multi-buffer support in non-zc path for i40e as well as from the patch to support zc on ice. Each subsequent frag is added to skb_shared_info of the first frag for possible xdp_prog use as well to xsk buffer list for accessing the buffers in af_xdp. For XDP_PASS, new pages are allocated for frags and contents are copied from memory backed by xsk_buff_pool. Replace next_to_clean with next_to_process as done in non-zc path and advance it for every buffer and change the semantics of next_to_clean to point to the first buffer of a packet. Driver will use next_to_process in the same way next_to_clean was used previously. For the non multi-buffer case, next_to_process and next_to_clean will always be the same since each packet consists of a single buffer. Signed-off-by: Tirthendu Sarkar Link: https://lore.kernel.org/r/20230719132421.584801-14-maciej.fijalkowski@intel.com Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 -- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 + drivers/net/ethernet/intel/i40e/i40e_xsk.c | 91 +++++++++++++++++++++++++---- 4 files changed, 84 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 29ad1797adce..1bd72cdedc8a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3585,11 +3585,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) if (ring->xsk_pool) { ring->rx_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool); - /* For AF_XDP ZC, we disallow packets to span on - * multiple buffers, thus letting us skip that - * handling in the fast-path. - */ - chain_len = 1; ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, MEM_TYPE_XSK_BUFF_POOL, NULL); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 8b8bf4880faa..0b3a27f118fb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2284,8 +2284,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, * If the buffer is an EOP buffer, this function exits returning false, * otherwise return true indicating that this is in fact a non-EOP buffer. */ -static bool i40e_is_non_eop(struct i40e_ring *rx_ring, - union i40e_rx_desc *rx_desc) +bool i40e_is_non_eop(struct i40e_ring *rx_ring, + union i40e_rx_desc *rx_desc) { /* if we are the last buffer then there is nothing else to do */ #define I40E_RXD_EOF BIT(I40E_RX_DESC_STATUS_EOF_SHIFT) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 8c3d24012c54..900b0d9ede9f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -473,6 +473,8 @@ int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size); bool __i40e_chk_linearize(struct sk_buff *skb); int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, u32 flags); +bool i40e_is_non_eop(struct i40e_ring *rx_ring, + union i40e_rx_desc *rx_desc); /** * i40e_get_head - Retrieve head from head writeback diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 05ec1181471e..89a8aca1153e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -294,8 +294,14 @@ static struct sk_buff *i40e_construct_skb_zc(struct i40e_ring *rx_ring, { unsigned int totalsize = xdp->data_end - xdp->data_meta; unsigned int metasize = xdp->data - xdp->data_meta; + struct skb_shared_info *sinfo = NULL; struct sk_buff *skb; + u32 nr_frags = 0; + if (unlikely(xdp_buff_has_frags(xdp))) { + sinfo = xdp_get_shared_info_from_buff(xdp); + nr_frags = sinfo->nr_frags; + } net_prefetch(xdp->data_meta); /* allocate a skb to store the frags */ @@ -312,6 +318,28 @@ static struct sk_buff *i40e_construct_skb_zc(struct i40e_ring *rx_ring, __skb_pull(skb, metasize); } + if (likely(!xdp_buff_has_frags(xdp))) + goto out; + + for (int i = 0; i < nr_frags; i++) { + struct skb_shared_info *skinfo = skb_shinfo(skb); + skb_frag_t *frag = &sinfo->frags[i]; + struct page *page; + void *addr; + + page = dev_alloc_page(); + if (!page) { + dev_kfree_skb(skb); + return NULL; + } + addr = page_to_virt(page); + + memcpy(addr, skb_frag_page(frag), skb_frag_size(frag)); + + __skb_fill_page_desc_noacc(skinfo, skinfo->nr_frags++, + addr, 0, skb_frag_size(frag)); + } + out: xsk_buff_free(xdp); return skb; @@ -322,14 +350,13 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring, union i40e_rx_desc *rx_desc, unsigned int *rx_packets, unsigned int *rx_bytes, - unsigned int size, unsigned int xdp_res, bool *failure) { struct sk_buff *skb; *rx_packets = 1; - *rx_bytes = size; + *rx_bytes = xdp_get_buff_len(xdp_buff); if (likely(xdp_res == I40E_XDP_REDIR) || xdp_res == I40E_XDP_TX) return; @@ -363,7 +390,6 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring, return; } - *rx_bytes = skb->len; i40e_process_skb_fields(rx_ring, rx_desc, skb); napi_gro_receive(&rx_ring->q_vector->napi, skb); return; @@ -374,6 +400,31 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring, WARN_ON_ONCE(1); } +static int +i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first, + struct xdp_buff *xdp, const unsigned int size) +{ + struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first); + + if (!xdp_buff_has_frags(first)) { + sinfo->nr_frags = 0; + sinfo->xdp_frags_size = 0; + xdp_buff_set_frags_flag(first); + } + + if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { + xsk_buff_free(first); + return -ENOMEM; + } + + __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, + virt_to_page(xdp->data_hard_start), 0, size); + sinfo->xdp_frags_size += size; + xsk_buff_add_frag(xdp); + + return 0; +} + /** * i40e_clean_rx_irq_zc - Consumes Rx packets from the hardware ring * @rx_ring: Rx ring @@ -384,13 +435,18 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring, int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) { unsigned int total_rx_bytes = 0, total_rx_packets = 0; + u16 next_to_process = rx_ring->next_to_process; u16 next_to_clean = rx_ring->next_to_clean; u16 count_mask = rx_ring->count - 1; unsigned int xdp_res, xdp_xmit = 0; + struct xdp_buff *first = NULL; struct bpf_prog *xdp_prog; bool failure = false; u16 cleaned_count; + if (next_to_process != next_to_clean) + first = *i40e_rx_bi(rx_ring, next_to_clean); + /* NB! xdp_prog will always be !NULL, due to the fact that * this path is enabled by setting an XDP program. */ @@ -404,7 +460,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) unsigned int size; u64 qword; - rx_desc = I40E_RX_DESC(rx_ring, next_to_clean); + rx_desc = I40E_RX_DESC(rx_ring, next_to_process); qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); /* This memory barrier is needed to keep us from reading @@ -417,9 +473,9 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) i40e_clean_programming_status(rx_ring, rx_desc->raw.qword[0], qword); - bi = *i40e_rx_bi(rx_ring, next_to_clean); + bi = *i40e_rx_bi(rx_ring, next_to_process); xsk_buff_free(bi); - next_to_clean = (next_to_clean + 1) & count_mask; + next_to_process = (next_to_process + 1) & count_mask; continue; } @@ -428,22 +484,35 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) if (!size) break; - bi = *i40e_rx_bi(rx_ring, next_to_clean); + bi = *i40e_rx_bi(rx_ring, next_to_process); xsk_buff_set_size(bi, size); xsk_buff_dma_sync_for_cpu(bi, rx_ring->xsk_pool); - xdp_res = i40e_run_xdp_zc(rx_ring, bi, xdp_prog); - i40e_handle_xdp_result_zc(rx_ring, bi, rx_desc, &rx_packets, - &rx_bytes, size, xdp_res, &failure); + if (!first) + first = bi; + else if (i40e_add_xsk_frag(rx_ring, first, bi, size)) + break; + + next_to_process = (next_to_process + 1) & count_mask; + + if (i40e_is_non_eop(rx_ring, rx_desc)) + continue; + + xdp_res = i40e_run_xdp_zc(rx_ring, first, xdp_prog); + i40e_handle_xdp_result_zc(rx_ring, first, rx_desc, &rx_packets, + &rx_bytes, xdp_res, &failure); + first->flags = 0; + next_to_clean = next_to_process; if (failure) break; total_rx_packets += rx_packets; total_rx_bytes += rx_bytes; xdp_xmit |= xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR); - next_to_clean = (next_to_clean + 1) & count_mask; + first = NULL; } rx_ring->next_to_clean = next_to_clean; + rx_ring->next_to_process = next_to_process; cleaned_count = (next_to_clean - rx_ring->next_to_use - 1) & count_mask; if (cleaned_count >= I40E_RX_BUFFER_WRITE) -- cgit From eeb2b5381038201133b52829634d2f95a4a8ac5e Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Wed, 19 Jul 2023 15:24:12 +0200 Subject: ice: xsk: Tx multi-buffer support Most of this patch is about actually supporting XDP_TX action. Pure Tx ZC support is only about looking at XDP_PKT_CONTD presence at options field and based on that generating EOP bit on Tx HW descriptor. This is that simple due to the implementation on xsk_tx_peek_release_desc_batch() where we are making sure that last produced descriptor is an EOP one. Overwrite xdp_zc_max_segs with a value that defines max scatter-gatter count on Tx side that HW can handle. Signed-off-by: Maciej Fijalkowski Link: https://lore.kernel.org/r/20230719132421.584801-16-maciej.fijalkowski@intel.com Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/intel/ice/ice_main.c | 1 + drivers/net/ethernet/intel/ice/ice_xsk.c | 83 ++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 19a5e7f3a075..ca83379b2de1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3392,6 +3392,7 @@ static void ice_set_ops(struct ice_vsi *vsi) netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_XSK_ZEROCOPY | NETDEV_XDP_ACT_RX_SG; + netdev->xdp_zc_max_segs = ICE_MAX_BUF_TXD; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 91cdd5e4790d..2a3f0834e139 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -613,7 +613,7 @@ out: * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ * @xdp_ring: XDP Tx ring */ -static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) +static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) { u16 ntc = xdp_ring->next_to_clean; struct ice_tx_desc *tx_desc; @@ -635,7 +635,7 @@ static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) } if (!completed_frames) - return; + return 0; if (likely(!xdp_ring->xdp_tx_active)) { xsk_frames = completed_frames; @@ -665,6 +665,8 @@ skip: xdp_ring->next_to_clean -= cnt; if (xsk_frames) xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames); + + return completed_frames; } /** @@ -682,37 +684,72 @@ skip: static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring) { + struct skb_shared_info *sinfo = NULL; u32 size = xdp->data_end - xdp->data; u32 ntu = xdp_ring->next_to_use; struct ice_tx_desc *tx_desc; struct ice_tx_buf *tx_buf; - dma_addr_t dma; + struct xdp_buff *head; + u32 nr_frags = 0; + u32 free_space; + u32 frag = 0; - if (ICE_DESC_UNUSED(xdp_ring) < ICE_RING_QUARTER(xdp_ring)) { - ice_clean_xdp_irq_zc(xdp_ring); - if (!ICE_DESC_UNUSED(xdp_ring)) { - xdp_ring->ring_stats->tx_stats.tx_busy++; - return ICE_XDP_CONSUMED; - } - } + free_space = ICE_DESC_UNUSED(xdp_ring); + if (free_space < ICE_RING_QUARTER(xdp_ring)) + free_space += ice_clean_xdp_irq_zc(xdp_ring); - dma = xsk_buff_xdp_get_dma(xdp); - xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, size); + if (unlikely(!free_space)) + goto busy; + + if (unlikely(xdp_buff_has_frags(xdp))) { + sinfo = xdp_get_shared_info_from_buff(xdp); + nr_frags = sinfo->nr_frags; + if (free_space < nr_frags + 1) + goto busy; + } - tx_buf = &xdp_ring->tx_buf[ntu]; - tx_buf->xdp = xdp; - tx_buf->type = ICE_TX_BUF_XSK_TX; tx_desc = ICE_TX_DESC(xdp_ring, ntu); - tx_desc->buf_addr = cpu_to_le64(dma); - tx_desc->cmd_type_offset_bsz = ice_build_ctob(ICE_TX_DESC_CMD_EOP, - 0, size, 0); - xdp_ring->xdp_tx_active++; + tx_buf = &xdp_ring->tx_buf[ntu]; + head = xdp; + + for (;;) { + dma_addr_t dma; + + dma = xsk_buff_xdp_get_dma(xdp); + xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, size); + + tx_buf->xdp = xdp; + tx_buf->type = ICE_TX_BUF_XSK_TX; + tx_desc->buf_addr = cpu_to_le64(dma); + tx_desc->cmd_type_offset_bsz = ice_build_ctob(0, 0, size, 0); + /* account for each xdp_buff from xsk_buff_pool */ + xdp_ring->xdp_tx_active++; + + if (++ntu == xdp_ring->count) + ntu = 0; + + if (frag == nr_frags) + break; + + tx_desc = ICE_TX_DESC(xdp_ring, ntu); + tx_buf = &xdp_ring->tx_buf[ntu]; + + xdp = xsk_buff_get_frag(head); + size = skb_frag_size(&sinfo->frags[frag]); + frag++; + } - if (++ntu == xdp_ring->count) - ntu = 0; xdp_ring->next_to_use = ntu; + /* update last descriptor from a frame with EOP */ + tx_desc->cmd_type_offset_bsz |= + cpu_to_le64(ICE_TX_DESC_CMD_EOP << ICE_TXD_QW1_CMD_S); return ICE_XDP_TX; + +busy: + xdp_ring->ring_stats->tx_stats.tx_busy++; + + return ICE_XDP_CONSUMED; } /** @@ -960,7 +997,7 @@ static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, struct xdp_desc *desc, tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_to_use++); tx_desc->buf_addr = cpu_to_le64(dma); - tx_desc->cmd_type_offset_bsz = ice_build_ctob(ICE_TX_DESC_CMD_EOP, + tx_desc->cmd_type_offset_bsz = ice_build_ctob(xsk_is_eop_desc(desc), 0, desc->len, 0); *total_bytes += desc->len; @@ -987,7 +1024,7 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de tx_desc = ICE_TX_DESC(xdp_ring, ntu++); tx_desc->buf_addr = cpu_to_le64(dma); - tx_desc->cmd_type_offset_bsz = ice_build_ctob(ICE_TX_DESC_CMD_EOP, + tx_desc->cmd_type_offset_bsz = ice_build_ctob(xsk_is_eop_desc(&descs[i]), 0, descs[i].len, 0); *total_bytes += descs[i].len; -- cgit From a92b96c4ae10950d8b904ae443d588c0e7f8344b Mon Sep 17 00:00:00 2001 From: Tirthendu Sarkar Date: Wed, 19 Jul 2023 15:24:13 +0200 Subject: i40e: xsk: add TX multi-buffer support Set eop bit in TX desc command only for the last descriptor of the packet and do not set for all preceding descriptors. Signed-off-by: Tirthendu Sarkar Link: https://lore.kernel.org/r/20230719132421.584801-17-maciej.fijalkowski@intel.com Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + drivers/net/ethernet/intel/i40e/i40e_xsk.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1bd72cdedc8a..982ae70c51e8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -13817,6 +13817,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_XSK_ZEROCOPY | NETDEV_XDP_ACT_RX_SG; + netdev->xdp_zc_max_segs = I40E_MAX_BUFFER_TXD; } else { /* Relate the VSI_VMDQ name to the VSI_MAIN name. Note that we * are still limited by IFNAMSIZ, but we're adding 'v%d\0' to diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 89a8aca1153e..37f41c8a682f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -535,6 +535,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) static void i40e_xmit_pkt(struct i40e_ring *xdp_ring, struct xdp_desc *desc, unsigned int *total_bytes) { + u32 cmd = I40E_TX_DESC_CMD_ICRC | xsk_is_eop_desc(desc); struct i40e_tx_desc *tx_desc; dma_addr_t dma; @@ -543,8 +544,7 @@ static void i40e_xmit_pkt(struct i40e_ring *xdp_ring, struct xdp_desc *desc, tx_desc = I40E_TX_DESC(xdp_ring, xdp_ring->next_to_use++); tx_desc->buffer_addr = cpu_to_le64(dma); - tx_desc->cmd_type_offset_bsz = build_ctob(I40E_TX_DESC_CMD_ICRC | I40E_TX_DESC_CMD_EOP, - 0, desc->len, 0); + tx_desc->cmd_type_offset_bsz = build_ctob(cmd, 0, desc->len, 0); *total_bytes += desc->len; } @@ -558,14 +558,14 @@ static void i40e_xmit_pkt_batch(struct i40e_ring *xdp_ring, struct xdp_desc *des u32 i; loop_unrolled_for(i = 0; i < PKTS_PER_BATCH; i++) { + u32 cmd = I40E_TX_DESC_CMD_ICRC | xsk_is_eop_desc(&desc[i]); + dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, desc[i].addr); xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, desc[i].len); tx_desc = I40E_TX_DESC(xdp_ring, ntu++); tx_desc->buffer_addr = cpu_to_le64(dma); - tx_desc->cmd_type_offset_bsz = build_ctob(I40E_TX_DESC_CMD_ICRC | - I40E_TX_DESC_CMD_EOP, - 0, desc[i].len, 0); + tx_desc->cmd_type_offset_bsz = build_ctob(cmd, 0, desc[i].len, 0); *total_bytes += desc[i].len; } -- cgit From 2eb85b750512cc5dc5a93d5ff00e1f83b99651db Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 18 Jul 2023 00:06:29 +0800 Subject: net: stmmac: don't clear network statistics in .ndo_open() FWICT, the common style in other network drivers: the network statistics are not cleared since initialization, follow the common style for stmmac. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20230717160630.1892-2-jszhang@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index efe85b086abe..a29a9619b48e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3829,10 +3829,6 @@ static int __stmmac_open(struct net_device *dev, } } - /* Extra statistics */ - memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); - priv->xstats.threshold = tc; - priv->rx_copybreak = STMMAC_RX_COPYBREAK; buf_sz = dma_conf->dma_buf_sz; @@ -7322,6 +7318,8 @@ int stmmac_dvr_probe(struct device *device, #endif priv->msg_enable = netif_msg_init(debug, default_msg_level); + priv->xstats.threshold = tc; + /* Initialize RSS */ rxq = priv->plat->rx_queues_to_use; netdev_rss_key_fill(priv->rss.key, sizeof(priv->rss.key)); -- cgit From 133466c3bbe171f826294161db203f7670bb30c8 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 18 Jul 2023 00:06:30 +0800 Subject: net: stmmac: use per-queue 64 bit statistics where necessary Currently, there are two major issues with stmmac driver statistics First of all, statistics in stmmac_extra_stats, stmmac_rxq_stats and stmmac_txq_stats are 32 bit variables on 32 bit platforms. This can cause some stats to overflow after several minutes of high traffic, for example rx_pkt_n, tx_pkt_n and so on. Secondly, if HW supports multiqueues, there are frequent cacheline ping pongs on some driver statistic vars, for example, normal_irq_n, tx_pkt_n and so on. What's more, frequent cacheline ping pongs on normal_irq_n happens in ISR, this makes the situation worse. To improve the driver, we convert those statistics to 64 bit, implement ndo_get_stats64 and update .get_ethtool_stats implementation accordingly. We also use per-queue statistics where necessary to remove the cacheline ping pongs as much as possible to make multiqueue operations faster. Those statistics which are not possible to overflow and not frequently updated are kept as is. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20230717160630.1892-3-jszhang@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/common.h | 39 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 +- drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 7 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 16 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 15 +- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 12 +- .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 6 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 14 +- drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 20 +-- drivers/net/ethernet/stmicro/stmmac/hwif.h | 12 +- drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 15 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 + .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 123 ++++++++++--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 200 ++++++++++++++++----- 14 files changed, 335 insertions(+), 158 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 16e67c18b6f7..57f2137bbe9d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -59,13 +59,25 @@ /* #define FRAME_FILTER_DEBUG */ struct stmmac_txq_stats { - unsigned long tx_pkt_n; - unsigned long tx_normal_irq_n; + u64 tx_bytes; + u64 tx_packets; + u64 tx_pkt_n; + u64 tx_normal_irq_n; + u64 napi_poll; + u64 tx_clean; + u64 tx_set_ic_bit; + u64 tx_tso_frames; + u64 tx_tso_nfrags; + struct u64_stats_sync syncp; }; struct stmmac_rxq_stats { - unsigned long rx_pkt_n; - unsigned long rx_normal_irq_n; + u64 rx_bytes; + u64 rx_packets; + u64 rx_pkt_n; + u64 rx_normal_irq_n; + u64 napi_poll; + struct u64_stats_sync syncp; }; /* Extra statistic and debug information exposed by ethtool */ @@ -81,6 +93,7 @@ struct stmmac_extra_stats { unsigned long tx_frame_flushed; unsigned long tx_payload_error; unsigned long tx_ip_header_error; + unsigned long tx_collision; /* Receive errors */ unsigned long rx_desc; unsigned long sa_filter_fail; @@ -113,14 +126,6 @@ struct stmmac_extra_stats { /* Tx/Rx IRQ Events */ unsigned long rx_early_irq; unsigned long threshold; - unsigned long tx_pkt_n; - unsigned long rx_pkt_n; - unsigned long normal_irq_n; - unsigned long rx_normal_irq_n; - unsigned long napi_poll; - unsigned long tx_normal_irq_n; - unsigned long tx_clean; - unsigned long tx_set_ic_bit; unsigned long irq_receive_pmt_irq_n; /* MMC info */ unsigned long mmc_tx_irq_n; @@ -190,18 +195,16 @@ struct stmmac_extra_stats { unsigned long mtl_rx_fifo_ctrl_active; unsigned long mac_rx_frame_ctrl_fifo; unsigned long mac_gmii_rx_proto_engine; - /* TSO */ - unsigned long tx_tso_frames; - unsigned long tx_tso_nfrags; /* EST */ unsigned long mtl_est_cgce; unsigned long mtl_est_hlbs; unsigned long mtl_est_hlbf; unsigned long mtl_est_btre; unsigned long mtl_est_btrlm; - /* per queue statistics */ - struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES]; - struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES]; + unsigned long rx_dropped; + unsigned long rx_errors; + unsigned long tx_dropped; + unsigned long tx_errors; }; /* Safety Feature statistics exposed by ethtool */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 2b5ebb15bfda..b607279e8cbd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -440,8 +440,10 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, struct stmmac_extra_stats *x, u32 chan, u32 dir) { - u32 v; + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; int ret = 0; + u32 v; v = readl(ioaddr + EMAC_INT_STA); @@ -452,7 +454,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, if (v & EMAC_TX_INT) { ret |= handle_tx; - x->tx_normal_irq_n++; + u64_stats_update_begin(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_normal_irq_n++; + u64_stats_update_end(&tx_q->txq_stats.syncp); } if (v & EMAC_TX_DMA_STOP_INT) @@ -474,7 +478,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, if (v & EMAC_RX_INT) { ret |= handle_rx; - x->rx_normal_irq_n++; + u64_stats_update_begin(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_normal_irq_n++; + u64_stats_update_end(&rx_q->rxq_stats.syncp); } if (v & EMAC_RX_BUF_UA_INT) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 1c32b1788f02..dea270f60cc3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -82,29 +82,24 @@ static void dwmac100_dump_dma_regs(struct stmmac_priv *priv, } /* DMA controller has two counters to track the number of the missed frames. */ -static void dwmac100_dma_diagnostic_fr(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static void dwmac100_dma_diagnostic_fr(struct stmmac_extra_stats *x, void __iomem *ioaddr) { u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); if (unlikely(csr8)) { if (csr8 & DMA_MISSED_FRAME_OVE) { - stats->rx_over_errors += 0x800; x->rx_overflow_cntr += 0x800; } else { unsigned int ove_cntr; ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); - stats->rx_over_errors += ove_cntr; x->rx_overflow_cntr += ove_cntr; } if (csr8 & DMA_MISSED_FRAME_OVE_M) { - stats->rx_missed_errors += 0xffff; x->rx_missed_cntr += 0xffff; } else { unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); - stats->rx_missed_errors += miss_f; x->rx_missed_cntr += miss_f; } } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 6a011d8633e8..89a14084c611 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -13,8 +13,7 @@ #include "dwmac4.h" #include "dwmac4_descs.h" -static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int dwmac4_wrback_get_tx_status(struct stmmac_extra_stats *x, struct dma_desc *p, void __iomem *ioaddr) { @@ -40,15 +39,13 @@ static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats, x->tx_frame_flushed++; if (unlikely(tdes3 & TDES3_LOSS_CARRIER)) { x->tx_losscarrier++; - stats->tx_carrier_errors++; } if (unlikely(tdes3 & TDES3_NO_CARRIER)) { x->tx_carrier++; - stats->tx_carrier_errors++; } if (unlikely((tdes3 & TDES3_LATE_COLLISION) || (tdes3 & TDES3_EXCESSIVE_COLLISION))) - stats->collisions += + x->tx_collision += (tdes3 & TDES3_COLLISION_COUNT_MASK) >> TDES3_COLLISION_COUNT_SHIFT; @@ -73,8 +70,7 @@ static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats, return ret; } -static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x, struct dma_desc *p) { unsigned int rdes1 = le32_to_cpu(p->des1); @@ -93,7 +89,7 @@ static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats, if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) { if (unlikely(rdes3 & RDES3_GIANT_PACKET)) - stats->rx_length_errors++; + x->rx_length++; if (unlikely(rdes3 & RDES3_OVERFLOW_ERROR)) x->rx_gmac_overflow++; @@ -103,10 +99,8 @@ static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats, if (unlikely(rdes3 & RDES3_RECEIVE_ERROR)) x->rx_mii++; - if (unlikely(rdes3 & RDES3_CRC_ERROR)) { + if (unlikely(rdes3 & RDES3_CRC_ERROR)) x->rx_crc_errors++; - stats->rx_crc_errors++; - } if (unlikely(rdes3 & RDES3_DRIBBLE_ERROR)) x->dribbling_bit++; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index df41eac54058..8dc8c2d91fa5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -171,6 +171,8 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; int ret = 0; if (dir == DMA_DIR_RX) @@ -198,18 +200,19 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, } } /* TX/RX NORMAL interrupts */ - if (likely(intr_status & DMA_CHAN_STATUS_NIS)) - x->normal_irq_n++; if (likely(intr_status & DMA_CHAN_STATUS_RI)) { - x->rx_normal_irq_n++; - x->rxq_stats[chan].rx_normal_irq_n++; + u64_stats_update_begin(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_normal_irq_n++; + u64_stats_update_end(&rx_q->rxq_stats.syncp); ret |= handle_rx; } if (likely(intr_status & DMA_CHAN_STATUS_TI)) { - x->tx_normal_irq_n++; - x->txq_stats[chan].tx_normal_irq_n++; + u64_stats_update_begin(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_normal_irq_n++; + u64_stats_update_end(&tx_q->txq_stats.syncp); ret |= handle_tx; } + if (unlikely(intr_status & DMA_CHAN_STATUS_TBU)) ret |= handle_tx; if (unlikely(intr_status & DMA_CHAN_STATUS_ERI)) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 0b6f999a8305..aaa09b16b016 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -10,6 +10,7 @@ #include #include "common.h" #include "dwmac_dma.h" +#include "stmmac.h" #define GMAC_HI_REG_AE 0x80000000 @@ -161,6 +162,8 @@ static void show_rx_process_state(unsigned int status) int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan, u32 dir) { + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; int ret = 0; /* read the status register (CSR5) */ u32 intr_status = readl(ioaddr + DMA_STATUS); @@ -208,17 +211,20 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, } /* TX/RX NORMAL interrupts */ if (likely(intr_status & DMA_STATUS_NIS)) { - x->normal_irq_n++; if (likely(intr_status & DMA_STATUS_RI)) { u32 value = readl(ioaddr + DMA_INTR_ENA); /* to schedule NAPI on real RIE event. */ if (likely(value & DMA_INTR_ENA_RIE)) { - x->rx_normal_irq_n++; + u64_stats_update_begin(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_normal_irq_n++; + u64_stats_update_end(&rx_q->rxq_stats.syncp); ret |= handle_rx; } } if (likely(intr_status & DMA_STATUS_TI)) { - x->tx_normal_irq_n++; + u64_stats_update_begin(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_normal_irq_n++; + u64_stats_update_end(&tx_q->txq_stats.syncp); ret |= handle_tx; } if (unlikely(intr_status & DMA_STATUS_ERI)) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index 13c347ee8be9..fc82862a612c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -8,8 +8,7 @@ #include "common.h" #include "dwxgmac2.h" -static int dwxgmac2_get_tx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int dwxgmac2_get_tx_status(struct stmmac_extra_stats *x, struct dma_desc *p, void __iomem *ioaddr) { unsigned int tdes3 = le32_to_cpu(p->des3); @@ -23,8 +22,7 @@ static int dwxgmac2_get_tx_status(struct net_device_stats *stats, return ret; } -static int dwxgmac2_get_rx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x, struct dma_desc *p) { unsigned int rdes3 = le32_to_cpu(p->des3); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index df5af52fd1a1..b09395f5edcb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -337,6 +337,8 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, struct stmmac_extra_stats *x, u32 chan, u32 dir) { + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan)); u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); int ret = 0; @@ -364,16 +366,16 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, /* TX/RX NORMAL interrupts */ if (likely(intr_status & XGMAC_NIS)) { - x->normal_irq_n++; - if (likely(intr_status & XGMAC_RI)) { - x->rx_normal_irq_n++; - x->rxq_stats[chan].rx_normal_irq_n++; + u64_stats_update_begin(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_normal_irq_n++; + u64_stats_update_end(&rx_q->rxq_stats.syncp); ret |= handle_rx; } if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { - x->tx_normal_irq_n++; - x->txq_stats[chan].tx_normal_irq_n++; + u64_stats_update_begin(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_normal_irq_n++; + u64_stats_update_end(&tx_q->txq_stats.syncp); ret |= handle_tx; } } diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index a91d8f13a931..937b7a0466fc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -12,8 +12,7 @@ #include "common.h" #include "descs_com.h" -static int enh_desc_get_tx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int enh_desc_get_tx_status(struct stmmac_extra_stats *x, struct dma_desc *p, void __iomem *ioaddr) { unsigned int tdes0 = le32_to_cpu(p->des0); @@ -38,15 +37,13 @@ static int enh_desc_get_tx_status(struct net_device_stats *stats, if (unlikely(tdes0 & ETDES0_LOSS_CARRIER)) { x->tx_losscarrier++; - stats->tx_carrier_errors++; } if (unlikely(tdes0 & ETDES0_NO_CARRIER)) { x->tx_carrier++; - stats->tx_carrier_errors++; } if (unlikely((tdes0 & ETDES0_LATE_COLLISION) || (tdes0 & ETDES0_EXCESSIVE_COLLISIONS))) - stats->collisions += + x->tx_collision += (tdes0 & ETDES0_COLLISION_COUNT_MASK) >> 3; if (unlikely(tdes0 & ETDES0_EXCESSIVE_DEFERRAL)) @@ -117,8 +114,7 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err) return ret; } -static void enh_desc_get_ext_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static void enh_desc_get_ext_status(struct stmmac_extra_stats *x, struct dma_extended_desc *p) { unsigned int rdes0 = le32_to_cpu(p->basic.des0); @@ -182,8 +178,7 @@ static void enh_desc_get_ext_status(struct net_device_stats *stats, } } -static int enh_desc_get_rx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int enh_desc_get_rx_status(struct stmmac_extra_stats *x, struct dma_desc *p) { unsigned int rdes0 = le32_to_cpu(p->des0); @@ -193,14 +188,14 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats, return dma_own; if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { - stats->rx_length_errors++; + x->rx_length++; return discard_frame; } if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) { if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) { x->rx_desc++; - stats->rx_length_errors++; + x->rx_length++; } if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR)) x->rx_gmac_overflow++; @@ -209,7 +204,7 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats, pr_err("\tIPC Csum Error/Giant frame\n"); if (unlikely(rdes0 & RDES0_COLLISION)) - stats->collisions++; + x->rx_collision++; if (unlikely(rdes0 & RDES0_RECEIVE_WATCHDOG)) x->rx_watchdog++; @@ -218,7 +213,6 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats, if (unlikely(rdes0 & RDES0_CRC_ERROR)) { x->rx_crc_errors++; - stats->rx_crc_errors++; } ret = discard_frame; } diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 6ee7cf07cfd7..652af8f6e75f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -57,8 +57,7 @@ struct stmmac_desc_ops { /* Last tx segment reports the transmit status */ int (*get_tx_ls)(struct dma_desc *p); /* Return the transmit status looking at the TDES1 */ - int (*tx_status)(struct net_device_stats *stats, - struct stmmac_extra_stats *x, + int (*tx_status)(struct stmmac_extra_stats *x, struct dma_desc *p, void __iomem *ioaddr); /* Get the buffer size from the descriptor */ int (*get_tx_len)(struct dma_desc *p); @@ -67,11 +66,9 @@ struct stmmac_desc_ops { /* Get the receive frame size */ int (*get_rx_frame_len)(struct dma_desc *p, int rx_coe_type); /* Return the reception status looking at the RDES1 */ - int (*rx_status)(struct net_device_stats *stats, - struct stmmac_extra_stats *x, + int (*rx_status)(struct stmmac_extra_stats *x, struct dma_desc *p); - void (*rx_extended_status)(struct net_device_stats *stats, - struct stmmac_extra_stats *x, + void (*rx_extended_status)(struct stmmac_extra_stats *x, struct dma_extended_desc *p); /* Set tx timestamp enable bit */ void (*enable_tx_timestamp) (struct dma_desc *p); @@ -191,8 +188,7 @@ struct stmmac_dma_ops { void (*dma_tx_mode)(struct stmmac_priv *priv, void __iomem *ioaddr, int mode, u32 channel, int fifosz, u8 qmode); /* To track extra statistic (if supported) */ - void (*dma_diagnostic_fr)(struct net_device_stats *stats, - struct stmmac_extra_stats *x, + void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x, void __iomem *ioaddr); void (*enable_dma_transmission) (void __iomem *ioaddr); void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 350e6670a576..68a7cfcb1d8f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -12,8 +12,7 @@ #include "common.h" #include "descs_com.h" -static int ndesc_get_tx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int ndesc_get_tx_status(struct stmmac_extra_stats *x, struct dma_desc *p, void __iomem *ioaddr) { unsigned int tdes0 = le32_to_cpu(p->des0); @@ -31,15 +30,12 @@ static int ndesc_get_tx_status(struct net_device_stats *stats, if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) { if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) { x->tx_underflow++; - stats->tx_fifo_errors++; } if (unlikely(tdes0 & TDES0_NO_CARRIER)) { x->tx_carrier++; - stats->tx_carrier_errors++; } if (unlikely(tdes0 & TDES0_LOSS_CARRIER)) { x->tx_losscarrier++; - stats->tx_carrier_errors++; } if (unlikely((tdes0 & TDES0_EXCESSIVE_DEFERRAL) || (tdes0 & TDES0_EXCESSIVE_COLLISIONS) || @@ -47,7 +43,7 @@ static int ndesc_get_tx_status(struct net_device_stats *stats, unsigned int collisions; collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3; - stats->collisions += collisions; + x->tx_collision += collisions; } ret = tx_err; } @@ -70,8 +66,7 @@ static int ndesc_get_tx_len(struct dma_desc *p) * and, if required, updates the multicast statistics. * In case of success, it returns good_frame because the GMAC device * is supposed to be able to compute the csum in HW. */ -static int ndesc_get_rx_status(struct net_device_stats *stats, - struct stmmac_extra_stats *x, +static int ndesc_get_rx_status(struct stmmac_extra_stats *x, struct dma_desc *p) { int ret = good_frame; @@ -81,7 +76,7 @@ static int ndesc_get_rx_status(struct net_device_stats *stats, return dma_own; if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { - stats->rx_length_errors++; + x->rx_length++; return discard_frame; } @@ -96,11 +91,9 @@ static int ndesc_get_rx_status(struct net_device_stats *stats, x->ipc_csum_error++; if (unlikely(rdes0 & RDES0_COLLISION)) { x->rx_collision++; - stats->collisions++; } if (unlikely(rdes0 & RDES0_CRC_ERROR)) { x->rx_crc_errors++; - stats->rx_crc_errors++; } ret = discard_frame; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 07ea5ab0a60b..4ce5eaaae513 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -77,6 +77,7 @@ struct stmmac_tx_queue { dma_addr_t dma_tx_phy; dma_addr_t tx_tail_addr; u32 mss; + struct stmmac_txq_stats txq_stats; }; struct stmmac_rx_buffer { @@ -121,6 +122,7 @@ struct stmmac_rx_queue { unsigned int len; unsigned int error; } state; + struct stmmac_rxq_stats rxq_stats; }; struct stmmac_channel { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 2ae73ab842d4..b7ac7abecdd3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -89,14 +89,6 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { /* Tx/Rx IRQ Events */ STMMAC_STAT(rx_early_irq), STMMAC_STAT(threshold), - STMMAC_STAT(tx_pkt_n), - STMMAC_STAT(rx_pkt_n), - STMMAC_STAT(normal_irq_n), - STMMAC_STAT(rx_normal_irq_n), - STMMAC_STAT(napi_poll), - STMMAC_STAT(tx_normal_irq_n), - STMMAC_STAT(tx_clean), - STMMAC_STAT(tx_set_ic_bit), STMMAC_STAT(irq_receive_pmt_irq_n), /* MMC info */ STMMAC_STAT(mmc_tx_irq_n), @@ -163,9 +155,6 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { STMMAC_STAT(mtl_rx_fifo_ctrl_active), STMMAC_STAT(mac_rx_frame_ctrl_fifo), STMMAC_STAT(mac_gmii_rx_proto_engine), - /* TSO */ - STMMAC_STAT(tx_tso_frames), - STMMAC_STAT(tx_tso_nfrags), /* EST */ STMMAC_STAT(mtl_est_cgce), STMMAC_STAT(mtl_est_hlbs), @@ -175,6 +164,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { }; #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats) +/* statistics collected in queue which will be summed up for all TX or RX + * queues, or summed up for both TX and RX queues(napi_poll, normal_irq_n). + */ +static const char stmmac_qstats_string[][ETH_GSTRING_LEN] = { + "rx_pkt_n", + "rx_normal_irq_n", + "tx_pkt_n", + "tx_normal_irq_n", + "tx_clean", + "tx_set_ic_bit", + "tx_tso_frames", + "tx_tso_nfrags", + "normal_irq_n", + "napi_poll", +}; +#define STMMAC_QSTATS ARRAY_SIZE(stmmac_qstats_string) + /* HW MAC Management counters (if supported) */ #define STMMAC_MMC_STAT(m) \ { #m, sizeof_field(struct stmmac_counters, m), \ @@ -535,23 +541,44 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data) { u32 tx_cnt = priv->plat->tx_queues_to_use; u32 rx_cnt = priv->plat->rx_queues_to_use; + unsigned int start; int q, stat; + u64 *pos; char *p; + pos = data; for (q = 0; q < tx_cnt; q++) { - p = (char *)priv + offsetof(struct stmmac_priv, - xstats.txq_stats[q].tx_pkt_n); + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[q]; + struct stmmac_txq_stats snapshot; + + data = pos; + do { + start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp); + snapshot = tx_q->txq_stats; + } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start)); + + p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n); for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) { - *data++ = (*(unsigned long *)p); - p += sizeof(unsigned long); + *data++ += (*(u64 *)p); + p += sizeof(u64); } } + + pos = data; for (q = 0; q < rx_cnt; q++) { - p = (char *)priv + offsetof(struct stmmac_priv, - xstats.rxq_stats[q].rx_pkt_n); + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[q]; + struct stmmac_rxq_stats snapshot; + + data = pos; + do { + start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp); + snapshot = rx_q->rxq_stats; + } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start)); + + p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n); for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) { - *data++ = (*(unsigned long *)p); - p += sizeof(unsigned long); + *data++ += (*(u64 *)p); + p += sizeof(u64); } } } @@ -562,8 +589,10 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, struct stmmac_priv *priv = netdev_priv(dev); u32 rx_queues_count = priv->plat->rx_queues_to_use; u32 tx_queues_count = priv->plat->tx_queues_to_use; + u64 napi_poll = 0, normal_irq_n = 0; + int i, j = 0, pos, ret; unsigned long count; - int i, j = 0, ret; + unsigned int start; if (priv->dma_cap.asp) { for (i = 0; i < STMMAC_SAFETY_FEAT_SIZE; i++) { @@ -574,8 +603,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, } /* Update the DMA HW counters for dwmac10/100 */ - ret = stmmac_dma_diagnostic_fr(priv, &dev->stats, (void *) &priv->xstats, - priv->ioaddr); + ret = stmmac_dma_diagnostic_fr(priv, &priv->xstats, priv->ioaddr); if (ret) { /* If supported, for new GMAC chips expose the MMC counters */ if (priv->dma_cap.rmon) { @@ -606,6 +634,48 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, data[j++] = (stmmac_gstrings_stats[i].sizeof_stat == sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p); } + + pos = j; + for (i = 0; i < rx_queues_count; i++) { + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[i]; + struct stmmac_rxq_stats snapshot; + + j = pos; + do { + start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp); + snapshot = rx_q->rxq_stats; + } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start)); + + data[j++] += snapshot.rx_pkt_n; + data[j++] += snapshot.rx_normal_irq_n; + normal_irq_n += snapshot.rx_normal_irq_n; + napi_poll += snapshot.napi_poll; + } + + pos = j; + for (i = 0; i < tx_queues_count; i++) { + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[i]; + struct stmmac_txq_stats snapshot; + + j = pos; + do { + start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp); + snapshot = tx_q->txq_stats; + } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start)); + + data[j++] += snapshot.tx_pkt_n; + data[j++] += snapshot.tx_normal_irq_n; + normal_irq_n += snapshot.tx_normal_irq_n; + data[j++] += snapshot.tx_clean; + data[j++] += snapshot.tx_set_ic_bit; + data[j++] += snapshot.tx_tso_frames; + data[j++] += snapshot.tx_tso_nfrags; + napi_poll += snapshot.napi_poll; + } + normal_irq_n += priv->xstats.rx_early_irq; + data[j++] = normal_irq_n; + data[j++] = napi_poll; + stmmac_get_per_qstats(priv, &data[j]); } @@ -618,7 +688,7 @@ static int stmmac_get_sset_count(struct net_device *netdev, int sset) switch (sset) { case ETH_SS_STATS: - len = STMMAC_STATS_LEN + + len = STMMAC_STATS_LEN + STMMAC_QSTATS + STMMAC_TXQ_STATS * tx_cnt + STMMAC_RXQ_STATS * rx_cnt; @@ -691,8 +761,11 @@ static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; } for (i = 0; i < STMMAC_STATS_LEN; i++) { - memcpy(p, stmmac_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); + memcpy(p, stmmac_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < STMMAC_QSTATS; i++) { + memcpy(p, stmmac_qstats_string[i], ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } stmmac_get_qstats_string(priv, p); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a29a9619b48e..e7ca52f0d2f2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2434,6 +2434,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) struct dma_desc *tx_desc = NULL; struct xdp_desc xdp_desc; bool work_done = true; + u32 tx_set_ic_bit = 0; + unsigned long flags; /* Avoids TX time-out as we are sharing with slow path */ txq_trans_cond_update(nq); @@ -2494,7 +2496,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) if (set_ic) { tx_q->tx_count_frames = 0; stmmac_set_tx_ic(priv, tx_desc); - priv->xstats.tx_set_ic_bit++; + tx_set_ic_bit++; } stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, @@ -2506,6 +2508,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size); entry = tx_q->cur_tx; } + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_set_ic_bit += tx_set_ic_bit; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); if (tx_desc) { stmmac_flush_tx_descriptors(priv, queue); @@ -2547,11 +2552,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; unsigned int bytes_compl = 0, pkts_compl = 0; unsigned int entry, xmits = 0, count = 0; + u32 tx_packets = 0, tx_errors = 0; + unsigned long flags; __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue)); - priv->xstats.tx_clean++; - tx_q->xsk_frames_done = 0; entry = tx_q->dirty_tx; @@ -2582,8 +2587,7 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) else p = tx_q->dma_tx + entry; - status = stmmac_tx_status(priv, &priv->dev->stats, - &priv->xstats, p, priv->ioaddr); + status = stmmac_tx_status(priv, &priv->xstats, p, priv->ioaddr); /* Check if the descriptor is owned by the DMA */ if (unlikely(status & tx_dma_own)) break; @@ -2599,13 +2603,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) if (likely(!(status & tx_not_ls))) { /* ... verify the status error condition */ if (unlikely(status & tx_err)) { - priv->dev->stats.tx_errors++; + tx_errors++; if (unlikely(status & tx_err_bump_tc)) stmmac_bump_dma_threshold(priv, queue); } else { - priv->dev->stats.tx_packets++; - priv->xstats.tx_pkt_n++; - priv->xstats.txq_stats[queue].tx_pkt_n++; + tx_packets++; } if (skb) stmmac_get_tx_hwtstamp(priv, p, skb); @@ -2709,6 +2711,14 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]), HRTIMER_MODE_REL); + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_packets += tx_packets; + tx_q->txq_stats.tx_pkt_n += tx_packets; + tx_q->txq_stats.tx_clean++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); + + priv->xstats.tx_errors += tx_errors; + __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); /* Combine decisions from TX clean and XSK TX */ @@ -2736,7 +2746,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan) tx_q->dma_tx_phy, chan); stmmac_start_tx_dma(priv, chan); - priv->dev->stats.tx_errors++; + priv->xstats.tx_errors++; netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, chan)); } @@ -4109,6 +4119,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) struct stmmac_tx_queue *tx_q; bool has_vlan, set_ic; u8 proto_hdr_len, hdr; + unsigned long flags; u32 pay_len, mss; dma_addr_t des; int i; @@ -4257,7 +4268,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) tx_q->tx_count_frames = 0; stmmac_set_tx_ic(priv, desc); - priv->xstats.tx_set_ic_bit++; } /* We've used all descriptors we need for this skb, however, @@ -4273,9 +4283,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); } - dev->stats.tx_bytes += skb->len; - priv->xstats.tx_tso_frames++; - priv->xstats.tx_tso_nfrags += nfrags; + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_bytes += skb->len; + tx_q->txq_stats.tx_tso_frames++; + tx_q->txq_stats.tx_tso_nfrags += nfrags; + if (set_ic) + tx_q->txq_stats.tx_set_ic_bit++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); if (priv->sarc_type) stmmac_set_desc_sarc(priv, first, priv->sarc_type); @@ -4325,7 +4339,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) dma_map_err: dev_err(priv->device, "Tx dma map failed\n"); dev_kfree_skb(skb); - priv->dev->stats.tx_dropped++; + priv->xstats.tx_dropped++; return NETDEV_TX_OK; } @@ -4351,6 +4365,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) struct stmmac_tx_queue *tx_q; bool has_vlan, set_ic; int entry, first_tx; + unsigned long flags; dma_addr_t des; tx_q = &priv->dma_conf.tx_queue[queue]; @@ -4479,7 +4494,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) tx_q->tx_count_frames = 0; stmmac_set_tx_ic(priv, desc); - priv->xstats.tx_set_ic_bit++; } /* We've used all descriptors we need for this skb, however, @@ -4506,7 +4520,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); } - dev->stats.tx_bytes += skb->len; + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_bytes += skb->len; + if (set_ic) + tx_q->txq_stats.tx_set_ic_bit++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); if (priv->sarc_type) stmmac_set_desc_sarc(priv, first, priv->sarc_type); @@ -4568,7 +4586,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) dma_map_err: netdev_err(priv->dev, "Tx DMA map failed\n"); dev_kfree_skb(skb); - priv->dev->stats.tx_dropped++; + priv->xstats.tx_dropped++; return NETDEV_TX_OK; } @@ -4769,9 +4787,12 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, set_ic = false; if (set_ic) { + unsigned long flags; tx_q->tx_count_frames = 0; stmmac_set_tx_ic(priv, tx_desc); - priv->xstats.tx_set_ic_bit++; + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.tx_set_ic_bit++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); } stmmac_enable_dma_transmission(priv, priv->ioaddr); @@ -4916,16 +4937,18 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, struct dma_desc *p, struct dma_desc *np, struct xdp_buff *xdp) { + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue]; unsigned int len = xdp->data_end - xdp->data; enum pkt_hash_types hash_type; int coe = priv->hw->rx_csum; + unsigned long flags; struct sk_buff *skb; u32 hash; skb = stmmac_construct_skb_zc(ch, xdp); if (!skb) { - priv->dev->stats.rx_dropped++; + priv->xstats.rx_dropped++; return; } @@ -4944,8 +4967,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, skb_record_rx_queue(skb, queue); napi_gro_receive(&ch->rxtx_napi, skb); - priv->dev->stats.rx_packets++; - priv->dev->stats.rx_bytes += len; + flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_pkt_n++; + rx_q->rxq_stats.rx_bytes += len; + u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags); } static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) @@ -5022,9 +5047,11 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) unsigned int count = 0, error = 0, len = 0; int dirty = stmmac_rx_dirty(priv, queue); unsigned int next_entry = rx_q->cur_rx; + u32 rx_errors = 0, rx_dropped = 0; unsigned int desc_size; struct bpf_prog *prog; bool failure = false; + unsigned long flags; int xdp_status = 0; int status = 0; @@ -5080,8 +5107,7 @@ read_again: p = rx_q->dma_rx + entry; /* read the status of the incoming frame */ - status = stmmac_rx_status(priv, &priv->dev->stats, - &priv->xstats, p); + status = stmmac_rx_status(priv, &priv->xstats, p); /* check if managed by the DMA otherwise go ahead */ if (unlikely(status & dma_own)) break; @@ -5103,8 +5129,7 @@ read_again: break; if (priv->extend_desc) - stmmac_rx_extended_status(priv, &priv->dev->stats, - &priv->xstats, + stmmac_rx_extended_status(priv, &priv->xstats, rx_q->dma_erx + entry); if (unlikely(status == discard_frame)) { xsk_buff_free(buf->xdp); @@ -5112,7 +5137,7 @@ read_again: dirty++; error = 1; if (!priv->hwts_rx_en) - priv->dev->stats.rx_errors++; + rx_errors++; } if (unlikely(error && (status & rx_not_ls))) @@ -5160,7 +5185,7 @@ read_again: break; case STMMAC_XDP_CONSUMED: xsk_buff_free(buf->xdp); - priv->dev->stats.rx_dropped++; + rx_dropped++; break; case STMMAC_XDP_TX: case STMMAC_XDP_REDIRECT: @@ -5181,8 +5206,12 @@ read_again: stmmac_finalize_xdp_rx(priv, xdp_status); - priv->xstats.rx_pkt_n += count; - priv->xstats.rxq_stats[queue].rx_pkt_n += count; + flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_pkt_n += count; + u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags); + + priv->xstats.rx_dropped += rx_dropped; + priv->xstats.rx_errors += rx_errors; if (xsk_uses_need_wakeup(rx_q->xsk_pool)) { if (failure || stmmac_rx_dirty(priv, queue) > 0) @@ -5206,6 +5235,7 @@ read_again: */ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) { + u32 rx_errors = 0, rx_dropped = 0, rx_bytes = 0, rx_packets = 0; struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue]; unsigned int count = 0, error = 0, len = 0; @@ -5215,6 +5245,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) unsigned int desc_size; struct sk_buff *skb = NULL; struct stmmac_xdp_buff ctx; + unsigned long flags; int xdp_status = 0; int buf_sz; @@ -5270,8 +5301,7 @@ read_again: p = rx_q->dma_rx + entry; /* read the status of the incoming frame */ - status = stmmac_rx_status(priv, &priv->dev->stats, - &priv->xstats, p); + status = stmmac_rx_status(priv, &priv->xstats, p); /* check if managed by the DMA otherwise go ahead */ if (unlikely(status & dma_own)) break; @@ -5288,14 +5318,13 @@ read_again: prefetch(np); if (priv->extend_desc) - stmmac_rx_extended_status(priv, &priv->dev->stats, - &priv->xstats, rx_q->dma_erx + entry); + stmmac_rx_extended_status(priv, &priv->xstats, rx_q->dma_erx + entry); if (unlikely(status == discard_frame)) { page_pool_recycle_direct(rx_q->page_pool, buf->page); buf->page = NULL; error = 1; if (!priv->hwts_rx_en) - priv->dev->stats.rx_errors++; + rx_errors++; } if (unlikely(error && (status & rx_not_ls))) @@ -5363,7 +5392,7 @@ read_again: virt_to_head_page(ctx.xdp.data), sync_len, true); buf->page = NULL; - priv->dev->stats.rx_dropped++; + rx_dropped++; /* Clear skb as it was set as * status by XDP program. @@ -5392,7 +5421,7 @@ read_again: skb = napi_alloc_skb(&ch->rx_napi, buf1_len); if (!skb) { - priv->dev->stats.rx_dropped++; + rx_dropped++; count++; goto drain_data; } @@ -5452,8 +5481,8 @@ drain_data: napi_gro_receive(&ch->rx_napi, skb); skb = NULL; - priv->dev->stats.rx_packets++; - priv->dev->stats.rx_bytes += len; + rx_packets++; + rx_bytes += len; count++; } @@ -5468,8 +5497,14 @@ drain_data: stmmac_rx_refill(priv, queue); - priv->xstats.rx_pkt_n += count; - priv->xstats.rxq_stats[queue].rx_pkt_n += count; + flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.rx_packets += rx_packets; + rx_q->rxq_stats.rx_bytes += rx_bytes; + rx_q->rxq_stats.rx_pkt_n += count; + u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags); + + priv->xstats.rx_dropped += rx_dropped; + priv->xstats.rx_errors += rx_errors; return count; } @@ -5479,10 +5514,15 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget) struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, rx_napi); struct stmmac_priv *priv = ch->priv_data; + struct stmmac_rx_queue *rx_q; u32 chan = ch->index; + unsigned long flags; int work_done; - priv->xstats.napi_poll++; + rx_q = &priv->dma_conf.rx_queue[chan]; + flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.napi_poll++; + u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags); work_done = stmmac_rx(priv, budget, chan); if (work_done < budget && napi_complete_done(napi, work_done)) { @@ -5501,10 +5541,15 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget) struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, tx_napi); struct stmmac_priv *priv = ch->priv_data; + struct stmmac_tx_queue *tx_q; u32 chan = ch->index; + unsigned long flags; int work_done; - priv->xstats.napi_poll++; + tx_q = &priv->dma_conf.tx_queue[chan]; + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.napi_poll++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); work_done = stmmac_tx_clean(priv, budget, chan); work_done = min(work_done, budget); @@ -5526,9 +5571,20 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget) container_of(napi, struct stmmac_channel, rxtx_napi); struct stmmac_priv *priv = ch->priv_data; int rx_done, tx_done, rxtx_done; + struct stmmac_rx_queue *rx_q; + struct stmmac_tx_queue *tx_q; u32 chan = ch->index; + unsigned long flags; + + rx_q = &priv->dma_conf.rx_queue[chan]; + flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp); + rx_q->rxq_stats.napi_poll++; + u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags); - priv->xstats.napi_poll++; + tx_q = &priv->dma_conf.tx_queue[chan]; + flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp); + tx_q->txq_stats.napi_poll++; + u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags); tx_done = stmmac_tx_clean(priv, budget, chan); tx_done = min(tx_done, budget); @@ -6788,6 +6844,56 @@ int stmmac_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags) return 0; } +static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + struct stmmac_priv *priv = netdev_priv(dev); + u32 tx_cnt = priv->plat->tx_queues_to_use; + u32 rx_cnt = priv->plat->rx_queues_to_use; + unsigned int start; + int q; + + for (q = 0; q < tx_cnt; q++) { + struct stmmac_txq_stats *txq_stats = &priv->dma_conf.tx_queue[q].txq_stats; + u64 tx_packets; + u64 tx_bytes; + + do { + start = u64_stats_fetch_begin(&txq_stats->syncp); + tx_packets = txq_stats->tx_packets; + tx_bytes = txq_stats->tx_bytes; + } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); + + stats->tx_packets += tx_packets; + stats->tx_bytes += tx_bytes; + } + + for (q = 0; q < rx_cnt; q++) { + struct stmmac_rxq_stats *rxq_stats = &priv->dma_conf.rx_queue[q].rxq_stats; + u64 rx_packets; + u64 rx_bytes; + + do { + start = u64_stats_fetch_begin(&rxq_stats->syncp); + rx_packets = rxq_stats->rx_packets; + rx_bytes = rxq_stats->rx_bytes; + } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); + + stats->rx_packets += rx_packets; + stats->rx_bytes += rx_bytes; + } + + stats->rx_dropped = priv->xstats.rx_dropped; + stats->rx_errors = priv->xstats.rx_errors; + stats->tx_dropped = priv->xstats.tx_dropped; + stats->tx_errors = priv->xstats.tx_errors; + stats->tx_carrier_errors = priv->xstats.tx_losscarrier + priv->xstats.tx_carrier; + stats->collisions = priv->xstats.tx_collision + priv->xstats.rx_collision; + stats->rx_length_errors = priv->xstats.rx_length; + stats->rx_crc_errors = priv->xstats.rx_crc_errors; + stats->rx_over_errors = priv->xstats.rx_overflow_cntr; + stats->rx_missed_errors = priv->xstats.rx_missed_cntr; +} + static const struct net_device_ops stmmac_netdev_ops = { .ndo_open = stmmac_open, .ndo_start_xmit = stmmac_xmit, @@ -6798,6 +6904,7 @@ static const struct net_device_ops stmmac_netdev_ops = { .ndo_set_rx_mode = stmmac_set_rx_mode, .ndo_tx_timeout = stmmac_tx_timeout, .ndo_eth_ioctl = stmmac_ioctl, + .ndo_get_stats64 = stmmac_get_stats64, .ndo_setup_tc = stmmac_setup_tc, .ndo_select_queue = stmmac_select_queue, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -7161,6 +7268,11 @@ int stmmac_dvr_probe(struct device *device, priv->device = device; priv->dev = ndev; + for (i = 0; i < MTL_MAX_RX_QUEUES; i++) + u64_stats_init(&priv->dma_conf.rx_queue[i].rxq_stats.syncp); + for (i = 0; i < MTL_MAX_TX_QUEUES; i++) + u64_stats_init(&priv->dma_conf.tx_queue[i].txq_stats.syncp); + stmmac_set_ethtool_ops(ndev); priv->pause = pause; priv->plat = plat_dat; -- cgit From 3b23ecd53ab5cc46965bc49dece460c0e85ddaac Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 18 Jul 2023 17:09:26 +0800 Subject: net: fec: remove the remaining code of rx copybreak Since the commit 95698ff6177b ("net: fec: using page pool to manage RX buffers") has been applied, all the rx packets, no matter small packets or large packets are put directly into the kernel networking buffers. That is to say, the rx copybreak function has been removed since then, but the related code has not been completely cleaned up. So the purpose of this patch is to clean up the remaining related code of rx copybreak. Signed-off-by: Wei Fang Link: https://lore.kernel.org/r/20230718090928.2654347-2-wei.fang@nxp.com Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec.h | 2 -- drivers/net/ethernet/freescale/fec_main.c | 43 ------------------------------- 2 files changed, 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 63a053dea819..81c9a07387c4 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -679,8 +679,6 @@ struct fec_enet_private { struct ethtool_eee eee; unsigned int clk_ref_rate; - u32 rx_copybreak; - /* ptp clock period in ns*/ unsigned int ptp_inc; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1b990a486059..fef313d3380e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -325,8 +325,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define FEC_WOL_FLAG_ENABLE (0x1 << 1) #define FEC_WOL_FLAG_SLEEP_ON (0x1 << 2) -#define COPYBREAK_DEFAULT 256 - /* Max number of allowed TCP segments for software TSO */ #define FEC_MAX_TSO_SEGS 100 #define FEC_MAX_SKB_DESCS (FEC_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) @@ -3051,44 +3049,6 @@ static int fec_enet_set_coalesce(struct net_device *ndev, return 0; } -static int fec_enet_get_tunable(struct net_device *netdev, - const struct ethtool_tunable *tuna, - void *data) -{ - struct fec_enet_private *fep = netdev_priv(netdev); - int ret = 0; - - switch (tuna->id) { - case ETHTOOL_RX_COPYBREAK: - *(u32 *)data = fep->rx_copybreak; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int fec_enet_set_tunable(struct net_device *netdev, - const struct ethtool_tunable *tuna, - const void *data) -{ - struct fec_enet_private *fep = netdev_priv(netdev); - int ret = 0; - - switch (tuna->id) { - case ETHTOOL_RX_COPYBREAK: - fep->rx_copybreak = *(u32 *)data; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - /* LPI Sleep Ts count base on tx clk (clk_ref). * The lpi sleep cnt value = X us / (cycle_ns). */ @@ -3226,8 +3186,6 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .get_sset_count = fec_enet_get_sset_count, #endif .get_ts_info = fec_enet_get_ts_info, - .get_tunable = fec_enet_get_tunable, - .set_tunable = fec_enet_set_tunable, .get_wol = fec_enet_get_wol, .set_wol = fec_enet_set_wol, .get_eee = fec_enet_get_eee, @@ -4476,7 +4434,6 @@ fec_probe(struct platform_device *pdev) if (fep->bufdesc_ex && fep->ptp_clock) netdev_info(ndev, "registered PHC device %d\n", fep->dev_id); - fep->rx_copybreak = COPYBREAK_DEFAULT; INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); pm_runtime_mark_last_busy(&pdev->dev); -- cgit From 36bde9c1accb8f7aa908b9c04c0769251629e6fd Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 18 Jul 2023 17:09:27 +0800 Subject: net: fec: remove fec_set_mac_address() from fec_enet_init() The fec_enet_init() is only invoked when the FEC driver probes, and the network device of FEC is not been brought up at this moment. So the fec_set_mac_address() does nothing and just returns zero when it is invoked in the fec_enet_init(). Actually, the MAC address is set into the hardware through fec_restart() which is also called in the fec_enet_init(). Signed-off-by: Wei Fang Link: https://lore.kernel.org/r/20230718090928.2654347-3-wei.fang@nxp.com Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index fef313d3380e..03ac7690b5c4 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3966,9 +3966,6 @@ static int fec_enet_init(struct net_device *ndev) if (ret) goto free_queue_mem; - /* make sure MAC we just acquired is programmed into the hw */ - fec_set_mac_address(ndev, NULL); - /* Set receive and transmit descriptor base. */ for (i = 0; i < fep->num_rx_queues; i++) { struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i]; -- cgit From 636a5e88233a1a95dcb368d340fd04658d548d5f Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 18 Jul 2023 17:09:28 +0800 Subject: net: fec: remove unused members from struct fec_enet_private Three members of struct fec_enet_private have not been used since they were first introduced into the FEC driver (commit 6605b730c061 ("FEC: Add time stamping code and a PTP hardware clock")). Namely, last_overflow_check, rx_hwtstamp_filter and base_incval. These unused members make the struct fec_enet_private a bit messy and might confuse the readers. There is no reason to keep them in the FEC driver any longer. Signed-off-by: Wei Fang Link: https://lore.kernel.org/r/20230718090928.2654347-4-wei.fang@nxp.com Reviewed-by: Simon Horman Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 81c9a07387c4..8f1edcca96c4 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -651,12 +651,9 @@ struct fec_enet_private { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; - unsigned long last_overflow_check; spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; - int rx_hwtstamp_filter; - u32 base_incval; u32 cycle_speed; int hwts_rx_en; int hwts_tx_en; -- cgit From 25108a834e145a274024d174083089f8a83fe5bb Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 19 Jul 2023 08:42:55 +0200 Subject: net: phy: c45: add support for 1000BASE-T1 forced setup Add support to force 1000BASE-T1 by setting the correct control bit in the MDIO_MMD_PMA_PMD_BT1_CTRL register. Signed-off-by: Stefan Eichenberger Reviewed-by: Andrew Lunn Signed-off-by: Paolo Abeni --- drivers/net/phy/phy-c45.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 93ed07223377..b73c428a1566 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_pma_baset1_setup_master_slave); */ int genphy_c45_pma_setup_forced(struct phy_device *phydev) { - int ctrl1, ctrl2, ret; + int bt1_ctrl, ctrl1, ctrl2, ret; /* Half duplex is not supported */ if (phydev->duplex != DUPLEX_FULL) @@ -176,6 +176,15 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev) ret = genphy_c45_pma_baset1_setup_master_slave(phydev); if (ret < 0) return ret; + + bt1_ctrl = 0; + if (phydev->speed == SPEED_1000) + bt1_ctrl = MDIO_PMA_PMD_BT1_CTRL_STRAP_B1000; + + ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_PMD_BT1_CTRL, + MDIO_PMA_PMD_BT1_CTRL_STRAP, bt1_ctrl); + if (ret < 0) + return ret; } return genphy_c45_an_disable_aneg(phydev); -- cgit From eba2e4c2faef618b6e33dfdba918c76727f891b5 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 19 Jul 2023 08:42:56 +0200 Subject: net: phy: c45: add a separate function to read BASE-T1 abilities Add a separate function to read the BASE-T1 abilities. Some PHYs do not indicate the availability of the extended BASE-T1 ability register, so this function must be called separately. Signed-off-by: Stefan Eichenberger Reviewed-by: Andrew Lunn Signed-off-by: Paolo Abeni --- drivers/net/phy/phy-c45.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index b73c428a1566..58a6bbbe8a70 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -881,6 +881,36 @@ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev) return genphy_c45_write_eee_adv(phydev, phydev->advertising_eee); } +/** + * genphy_c45_pma_baset1_read_abilities - read supported baset1 link modes from PMA + * @phydev: target phy_device struct + * + * Read the supported link modes from the extended BASE-T1 ability register + */ +int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_PMD_BT1); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, + phydev->supported, + val & MDIO_PMA_PMD_BT1_B10L_ABLE); + + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_STAT); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + phydev->supported, + val & MDIO_AN_STAT1_ABLE); + + return 0; +} +EXPORT_SYMBOL_GPL(genphy_c45_pma_baset1_read_abilities); + /** * genphy_c45_pma_read_abilities - read supported link modes from PMA * @phydev: target phy_device struct @@ -977,21 +1007,9 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev) } if (val & MDIO_PMA_EXTABLE_BT1) { - val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_PMD_BT1); + val = genphy_c45_pma_baset1_read_abilities(phydev); if (val < 0) return val; - - linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, - phydev->supported, - val & MDIO_PMA_PMD_BT1_B10L_ABLE); - - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_STAT); - if (val < 0) - return val; - - linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - phydev->supported, - val & MDIO_AN_STAT1_ABLE); } } -- cgit From a60eb72066af272c2891c6685b9a082dde69198c Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 19 Jul 2023 08:42:57 +0200 Subject: net: phy: c45: detect the BASE-T1 speed from the ability register Read the ability to do 100BASE-T1 and 1000BASE-T1 from the extended BASE-T1 ability register of the PHY. Signed-off-by: Stefan Eichenberger Reviewed-by: Andrew Lunn Signed-off-by: Paolo Abeni --- drivers/net/phy/phy-c45.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 58a6bbbe8a70..8e6fd4962c48 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -899,6 +899,14 @@ int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev) phydev->supported, val & MDIO_PMA_PMD_BT1_B10L_ABLE); + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, + phydev->supported, + val & MDIO_PMA_PMD_BT1_B100_ABLE); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, + phydev->supported, + val & MDIO_PMA_PMD_BT1_B1000_ABLE); + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_STAT); if (val < 0) return val; -- cgit From 00f11ac71708d2e5e434aa2ef9249f95b5e7e313 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 19 Jul 2023 08:42:58 +0200 Subject: net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2110 PHY Add a driver for the Marvell 88Q2110. This driver allows to detect the link, switch between 100BASE-T1 and 1000BASE-T1 and switch between master and slave mode. Autonegotiation supported by the PHY does not yet work. Signed-off-by: Stefan Eichenberger Reviewed-by: Andrew Lunn Signed-off-by: Paolo Abeni --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88q2xxx.c | 263 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 drivers/net/phy/marvell-88q2xxx.c (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 78e6981650d9..87b823858717 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -217,6 +217,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88Q2XXX_PHY + tristate "Marvell 88Q2XXX PHY" + help + Support for the Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet + PHYs. + config MARVELL_88X2222_PHY tristate "Marvell 88X2222 PHY" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 2fe51ea83bab..35142780fc9d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c new file mode 100644 index 000000000000..1c3ff77de56b --- /dev/null +++ b/drivers/net/phy/marvell-88q2xxx.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver + */ +#include +#include +#include + +#define MDIO_MMD_AN_MV_STAT 32769 +#define MDIO_MMD_AN_MV_STAT_ANEG 0x0100 +#define MDIO_MMD_AN_MV_STAT_LOCAL_RX 0x1000 +#define MDIO_MMD_AN_MV_STAT_REMOTE_RX 0x2000 +#define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER 0x4000 +#define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT 0x8000 + +#define MDIO_MMD_PCS_MV_100BT1_STAT1 33032 +#define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR 0x00FF +#define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER 0x0100 +#define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK 0x0200 +#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX 0x1000 +#define MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX 0x2000 +#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_MASTER 0x4000 + +#define MDIO_MMD_PCS_MV_100BT1_STAT2 33033 +#define MDIO_MMD_PCS_MV_100BT1_STAT2_JABBER 0x0001 +#define MDIO_MMD_PCS_MV_100BT1_STAT2_POL 0x0002 +#define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK 0x0004 +#define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE 0x0008 + +static int mv88q2xxx_soft_reset(struct phy_device *phydev) +{ + int ret; + int val; + + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, + MDIO_PCS_1000BT1_CTRL, MDIO_PCS_1000BT1_CTRL_RESET); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS, + MDIO_PCS_1000BT1_CTRL, val, + !(val & MDIO_PCS_1000BT1_CTRL_RESET), + 50000, 600000, true); +} + +static int mv88q2xxx_read_link_gbit(struct phy_device *phydev) +{ + int ret; + bool link = false; + + /* Read vendor specific Auto-Negotiation status register to get local + * and remote receiver status according to software initialization + * guide. + */ + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT); + if (ret < 0) { + return ret; + } else if ((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) && + (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) { + /* The link state is latched low so that momentary link + * drops can be detected. Do not double-read the status + * in polling mode to detect such short link drops except + * the link was already down. + */ + if (!phy_polling_mode(phydev) || !phydev->link) { + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT); + if (ret < 0) + return ret; + else if (ret & MDIO_PCS_1000BT1_STAT_LINK) + link = true; + } + + if (!link) { + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT); + if (ret < 0) + return ret; + else if (ret & MDIO_PCS_1000BT1_STAT_LINK) + link = true; + } + } + + phydev->link = link; + + return 0; +} + +static int mv88q2xxx_read_link_100m(struct phy_device *phydev) +{ + int ret; + + /* The link state is latched low so that momentary link + * drops can be detected. Do not double-read the status + * in polling mode to detect such short link drops except + * the link was already down. In case we are not polling, + * we always read the realtime status. + */ + if (!phy_polling_mode(phydev) || !phydev->link) { + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1); + if (ret < 0) + return ret; + else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) + goto out; + } + + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1); + if (ret < 0) + return ret; + +out: + /* Check if we have link and if the remote and local receiver are ok */ + if ((ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) && + (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX) && + (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX)) + phydev->link = true; + else + phydev->link = false; + + return 0; +} + +static int mv88q2xxx_read_link(struct phy_device *phydev) +{ + int ret; + + /* The 88Q2XXX PHYs do not have the PMA/PMD status register available, + * therefore we need to read the link status from the vendor specific + * registers depending on the speed. + */ + if (phydev->speed == SPEED_1000) + ret = mv88q2xxx_read_link_gbit(phydev); + else + ret = mv88q2xxx_read_link_100m(phydev); + + return ret; +} + +static int mv88q2xxx_read_status(struct phy_device *phydev) +{ + int ret; + + ret = mv88q2xxx_read_link(phydev); + if (ret < 0) + return ret; + + return genphy_c45_read_pma(phydev); +} + +static int mv88q2xxx_get_features(struct phy_device *phydev) +{ + int ret; + + ret = genphy_c45_pma_read_abilities(phydev); + if (ret) + return ret; + + /* We need to read the baset1 extended abilities manually because the + * PHY does not signalize it has the extended abilities register + * available. + */ + ret = genphy_c45_pma_baset1_read_abilities(phydev); + if (ret) + return ret; + + /* The PHY signalizes it supports autonegotiation. Unfortunately, so + * far it was not possible to get a link even when following the init + * sequence provided by Marvell. Disable it for now until a proper + * workaround is found or a new PHY revision is released. + */ + linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + + return 0; +} + +static int mv88q2xxx_config_aneg(struct phy_device *phydev) +{ + int ret; + + ret = genphy_c45_config_aneg(phydev); + if (ret) + return ret; + + return mv88q2xxx_soft_reset(phydev); +} + +static int mv88q2xxx_config_init(struct phy_device *phydev) +{ + int ret; + + /* The 88Q2XXX PHYs do have the extended ability register available, but + * register MDIO_PMA_EXTABLE where they should signalize it does not + * work according to specification. Therefore, we force it here. + */ + phydev->pma_extable = MDIO_PMA_EXTABLE_BT1; + + /* Read the current PHY configuration */ + ret = genphy_c45_read_pma(phydev); + if (ret) + return ret; + + return mv88q2xxx_config_aneg(phydev); +} + +static int mv88q2xxxx_get_sqi(struct phy_device *phydev) +{ + int ret; + + if (phydev->speed == SPEED_100) { + /* Read the SQI from the vendor specific receiver status + * register + */ + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8230); + if (ret < 0) + return ret; + + ret = ret >> 12; + } else { + /* Read from vendor specific registers, they are not documented + * but can be found in the Software Initialization Guide. Only + * revisions >= A0 are supported. + */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xFC5D, 0x00FF, 0x00AC); + if (ret < 0) + return ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88); + if (ret < 0) + return ret; + } + + return ret & 0x0F; +} + +static int mv88q2xxxx_get_sqi_max(struct phy_device *phydev) +{ + return 15; +} + +static struct phy_driver mv88q2xxx_driver[] = { + { + .phy_id = MARVELL_PHY_ID_88Q2110, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "mv88q2110", + .get_features = mv88q2xxx_get_features, + .config_aneg = mv88q2xxx_config_aneg, + .config_init = mv88q2xxx_config_init, + .read_status = mv88q2xxx_read_status, + .soft_reset = mv88q2xxx_soft_reset, + .set_loopback = genphy_c45_loopback, + .get_sqi = mv88q2xxxx_get_sqi, + .get_sqi_max = mv88q2xxxx_get_sqi_max, + }, +}; + +module_phy_driver(mv88q2xxx_driver); + +static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = { + { MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK }, + { /*sentinel*/ } +}; +MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl); + +MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver"); +MODULE_LICENSE("GPL"); -- cgit From fea2993aecd74d5d11ede1ebbd60e478ebfed996 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Jul 2023 18:04:38 -0700 Subject: eth: bnxt: move and rename reset helpers Move the reset helpers, subsequent patches will need some of them on the Tx path. While at it rename bnxt_sched_reset(), on more recent chips it schedules a queue reset, instead of a fuller reset. Link: https://lore.kernel.org/r/20230720010440.1967136-2-kuba@kernel.org Reviewed-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 72 +++++++++++++++---------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index d84ded8db93d..417554a4c837 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -293,6 +293,38 @@ static void bnxt_db_cq(struct bnxt *bp, struct bnxt_db_info *db, u32 idx) BNXT_DB_CQ(db, idx); } +static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay) +{ + if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))) + return; + + if (BNXT_PF(bp)) + queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay); + else + schedule_delayed_work(&bp->fw_reset_task, delay); +} + +static void bnxt_queue_sp_work(struct bnxt *bp) +{ + if (BNXT_PF(bp)) + queue_work(bnxt_pf_wq, &bp->sp_task); + else + schedule_work(&bp->sp_task); +} + +static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) +{ + if (!rxr->bnapi->in_reset) { + rxr->bnapi->in_reset = true; + if (bp->flags & BNXT_FLAG_CHIP_P5) + set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); + else + set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event); + bnxt_queue_sp_work(bp); + } + rxr->rx_next_cons = 0xffff; +} + const u16 bnxt_lhint_arr[] = { TX_BD_FLAGS_LHINT_512_AND_SMALLER, TX_BD_FLAGS_LHINT_512_TO_1023, @@ -1234,38 +1266,6 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, return 0; } -static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay) -{ - if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))) - return; - - if (BNXT_PF(bp)) - queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay); - else - schedule_delayed_work(&bp->fw_reset_task, delay); -} - -static void bnxt_queue_sp_work(struct bnxt *bp) -{ - if (BNXT_PF(bp)) - queue_work(bnxt_pf_wq, &bp->sp_task); - else - schedule_work(&bp->sp_task); -} - -static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) -{ - if (!rxr->bnapi->in_reset) { - rxr->bnapi->in_reset = true; - if (bp->flags & BNXT_FLAG_CHIP_P5) - set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); - else - set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } - rxr->rx_next_cons = 0xffff; -} - static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id) { struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map; @@ -1320,7 +1320,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, netdev_warn(bp->dev, "TPA cons %x, expected cons %x, error code %x\n", cons, rxr->rx_next_cons, TPA_START_ERROR_CODE(tpa_start1)); - bnxt_sched_reset(bp, rxr); + bnxt_sched_reset_rxr(bp, rxr); return; } /* Store cfa_code in tpa_info to use in tpa_end @@ -1844,7 +1844,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, if (rxr->rx_next_cons != 0xffff) netdev_warn(bp->dev, "RX cons %x != expected cons %x\n", cons, rxr->rx_next_cons); - bnxt_sched_reset(bp, rxr); + bnxt_sched_reset_rxr(bp, rxr); if (rc1) return rc1; goto next_rx_no_prod_no_len; @@ -1882,7 +1882,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, !(bp->fw_cap & BNXT_FW_CAP_RING_MONITOR)) { netdev_warn_once(bp->dev, "RX buffer error %x\n", rx_err); - bnxt_sched_reset(bp, rxr); + bnxt_sched_reset_rxr(bp, rxr); } } goto next_rx_no_len; @@ -2329,7 +2329,7 @@ static int bnxt_async_event_process(struct bnxt *bp, goto async_event_process_exit; } rxr = bp->bnapi[grp_idx]->rx_ring; - bnxt_sched_reset(bp, rxr); + bnxt_sched_reset_rxr(bp, rxr); goto async_event_process_exit; } case ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST: { -- cgit From 9b1a00fda61ee9874e11c24c6be7ddc36e8a4598 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Jul 2023 18:04:39 -0700 Subject: eth: bnxt: take the bit to set as argument of bnxt_queue_sp_work() Most callers of bnxt_queue_sp_work() set a bit to indicate what work to perform right before calling it. Pass it to the function instead. Link: https://lore.kernel.org/r/20230720010440.1967136-3-kuba@kernel.org Reviewed-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 61 +++++++++++++------------------ 1 file changed, 26 insertions(+), 35 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 417554a4c837..7b545d2a98b4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -304,7 +304,7 @@ static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay) schedule_delayed_work(&bp->fw_reset_task, delay); } -static void bnxt_queue_sp_work(struct bnxt *bp) +static void __bnxt_queue_sp_work(struct bnxt *bp) { if (BNXT_PF(bp)) queue_work(bnxt_pf_wq, &bp->sp_task); @@ -312,6 +312,12 @@ static void bnxt_queue_sp_work(struct bnxt *bp) schedule_work(&bp->sp_task); } +static void bnxt_queue_sp_work(struct bnxt *bp, unsigned int event) +{ + set_bit(event, &bp->sp_event); + __bnxt_queue_sp_work(bp); +} + static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) { if (!rxr->bnapi->in_reset) { @@ -320,7 +326,7 @@ static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); else set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + __bnxt_queue_sp_work(bp); } rxr->rx_next_cons = 0xffff; } @@ -2384,7 +2390,7 @@ static int bnxt_async_event_process(struct bnxt *bp, default: goto async_event_process_exit; } - bnxt_queue_sp_work(bp); + __bnxt_queue_sp_work(bp); async_event_process_exit: return 0; } @@ -2413,8 +2419,7 @@ static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp) } set_bit(vf_id - bp->pf.first_vf_id, bp->pf.vf_event_bmap); - set_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT); break; case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: @@ -11031,8 +11036,7 @@ static void bnxt_set_rx_mode(struct net_device *dev) if (mask != vnic->rx_mask || uc_update || mc_update) { vnic->rx_mask = mask; - set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_RX_MASK_SP_EVENT); } } @@ -11597,8 +11601,7 @@ static void bnxt_tx_timeout(struct net_device *dev, unsigned int txqueue) struct bnxt *bp = netdev_priv(dev); netdev_err(bp->dev, "TX timeout detected, starting reset task!\n"); - set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_RESET_TASK_SP_EVENT); } static void bnxt_fw_health_check(struct bnxt *bp) @@ -11635,8 +11638,7 @@ static void bnxt_fw_health_check(struct bnxt *bp) return; fw_reset: - set_bit(BNXT_FW_EXCEPTION_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_FW_EXCEPTION_SP_EVENT); } static void bnxt_timer(struct timer_list *t) @@ -11653,21 +11655,15 @@ static void bnxt_timer(struct timer_list *t) if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) bnxt_fw_health_check(bp); - if (BNXT_LINK_IS_UP(bp) && bp->stats_coal_ticks) { - set_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } + if (BNXT_LINK_IS_UP(bp) && bp->stats_coal_ticks) + bnxt_queue_sp_work(bp, BNXT_PERIODIC_STATS_SP_EVENT); - if (bnxt_tc_flower_enabled(bp)) { - set_bit(BNXT_FLOW_STATS_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } + if (bnxt_tc_flower_enabled(bp)) + bnxt_queue_sp_work(bp, BNXT_FLOW_STATS_SP_EVENT); #ifdef CONFIG_RFS_ACCEL - if ((bp->flags & BNXT_FLAG_RFS) && bp->ntp_fltr_count) { - set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } + if ((bp->flags & BNXT_FLAG_RFS) && bp->ntp_fltr_count) + bnxt_queue_sp_work(bp, BNXT_RX_NTP_FLTR_SP_EVENT); #endif /*CONFIG_RFS_ACCEL*/ if (bp->link_info.phy_retry) { @@ -11675,21 +11671,17 @@ static void bnxt_timer(struct timer_list *t) bp->link_info.phy_retry = false; netdev_warn(bp->dev, "failed to update phy settings after maximum retries.\n"); } else { - set_bit(BNXT_UPDATE_PHY_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_UPDATE_PHY_SP_EVENT); } } - if (test_bit(BNXT_STATE_L2_FILTER_RETRY, &bp->state)) { - set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } + if (test_bit(BNXT_STATE_L2_FILTER_RETRY, &bp->state)) + bnxt_queue_sp_work(bp, BNXT_RX_MASK_SP_EVENT); if ((bp->flags & BNXT_FLAG_CHIP_P5) && !bp->chip_rev && - netif_carrier_ok(dev)) { - set_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); - } + netif_carrier_ok(dev)) + bnxt_queue_sp_work(bp, BNXT_RING_COAL_NOW_SP_EVENT); + bnxt_restart_timer: mod_timer(&bp->timer, jiffies + bp->current_interval); } @@ -12968,8 +12960,7 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, bp->ntp_fltr_count++; spin_unlock_bh(&bp->ntp_fltr_lock); - set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event); - bnxt_queue_sp_work(bp); + bnxt_queue_sp_work(bp, BNXT_RX_NTP_FLTR_SP_EVENT); return new_fltr->sw_id; -- cgit From 2b56b3d9924160d84c37d085628525666e3b1cea Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Jul 2023 18:04:40 -0700 Subject: eth: bnxt: handle invalid Tx completions more gracefully Invalid Tx completions should never happen (tm) but when they do they crash the host, because driver blindly trusts that there is a valid skb pointer on the ring. The completions I've seen appear to be some form of FW / HW miscalculation or staleness, they have typical (small) values (<100), but they are most often higher than number of queued descriptors. They usually happen after boot. Instead of crashing, print a warning and schedule a reset. Link: https://lore.kernel.org/r/20230720010440.1967136-4-kuba@kernel.org Reviewed-by: Michael Chan Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 25 ++++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 +++ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 4 ++++ 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7b545d2a98b4..a3bbd13c070f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -331,6 +331,22 @@ static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) rxr->rx_next_cons = 0xffff; } +void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr, + int idx) +{ + struct bnxt_napi *bnapi = txr->bnapi; + + if (bnapi->tx_fault) + return; + + netdev_err(bp->dev, "Invalid Tx completion (ring:%d tx_pkts:%d cons:%u prod:%u i:%d)", + txr->txq_index, bnapi->tx_pkts, + txr->tx_cons, txr->tx_prod, idx); + WARN_ON_ONCE(1); + bnapi->tx_fault = 1; + bnxt_queue_sp_work(bp, BNXT_RESET_TASK_SP_EVENT); +} + const u16 bnxt_lhint_arr[] = { TX_BD_FLAGS_LHINT_512_AND_SMALLER, TX_BD_FLAGS_LHINT_512_TO_1023, @@ -690,6 +706,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) skb = tx_buf->skb; tx_buf->skb = NULL; + if (unlikely(!skb)) { + bnxt_sched_reset_txr(bp, txr, i); + return; + } + tx_bytes += skb->len; if (tx_buf->is_push) { @@ -2576,7 +2597,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi) { - if (bnapi->tx_pkts) { + if (bnapi->tx_pkts && !bnapi->tx_fault) { bnapi->tx_int(bp, bnapi, bnapi->tx_pkts); bnapi->tx_pkts = 0; } @@ -9429,6 +9450,8 @@ static void bnxt_enable_napi(struct bnxt *bp) struct bnxt_napi *bnapi = bp->bnapi[i]; struct bnxt_cp_ring_info *cpr; + bnapi->tx_fault = 0; + cpr = &bnapi->cp_ring; if (bnapi->in_reset) cpr->sw_stats.rx.rx_resets++; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 080e73496066..9d16757e27fe 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1008,6 +1008,7 @@ struct bnxt_napi { int); int tx_pkts; u8 events; + u8 tx_fault:1; u32 flags; #define BNXT_NAPI_FLAG_XDP 0x1 @@ -2329,6 +2330,8 @@ int bnxt_get_avail_msix(struct bnxt *bp, int num); int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init); void bnxt_tx_disable(struct bnxt *bp); void bnxt_tx_enable(struct bnxt *bp); +void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr, + int idx); void bnxt_report_link(struct bnxt *bp); int bnxt_update_link(struct bnxt *bp, bool chng_link_state); int bnxt_hwrm_set_pause(struct bnxt *); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index 4efa5fe6972b..5b6fbdc4dc40 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -149,6 +149,7 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) tx_buf->action = 0; tx_buf->xdpf = NULL; } else if (tx_buf->action == XDP_TX) { + tx_buf->action = 0; rx_doorbell_needed = true; last_tx_cons = tx_cons; @@ -158,6 +159,9 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) tx_buf = &txr->tx_buf_ring[tx_cons]; page_pool_recycle_direct(rxr->page_pool, tx_buf->page); } + } else { + bnxt_sched_reset_txr(bp, txr, i); + return; } tx_cons = NEXT_TX(tx_cons); } -- cgit From a5dc694e16d31fbf85596de1239ebf4ca8426042 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 19 Jul 2023 12:29:49 +0200 Subject: net: ethernet: mtk_ppe: add MTK_FOE_ENTRY_V{1,2}_SIZE macros Introduce MTK_FOE_ENTRY_V{1,2}_SIZE macros in order to make more explicit foe_entry size for different chipset revisions. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +++++----- drivers/net/ethernet/mediatek/mtk_ppe.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 2d15342c260a..18a8aca7944d 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -4804,7 +4804,7 @@ static const struct mtk_soc_data mt7621_data = { .required_pctl = false, .offload_version = 1, .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), @@ -4825,7 +4825,7 @@ static const struct mtk_soc_data mt7622_data = { .offload_version = 2, .hash_offset = 2, .has_accounting = true, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), @@ -4844,7 +4844,7 @@ static const struct mtk_soc_data mt7623_data = { .required_pctl = true, .offload_version = 1, .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), @@ -4882,8 +4882,8 @@ static const struct mtk_soc_data mt7981_data = { .required_pctl = false, .offload_version = 2, .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), @@ -4903,8 +4903,8 @@ static const struct mtk_soc_data mt7986_data = { .required_pctl = false, .offload_version = 2, .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h index e51de31a52ec..fb6bf58172d9 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h @@ -216,6 +216,9 @@ struct mtk_foe_ipv6_6rd { struct mtk_foe_mac_info l2; }; +#define MTK_FOE_ENTRY_V1_SIZE 80 +#define MTK_FOE_ENTRY_V2_SIZE 96 + struct mtk_foe_entry { u32 ib1; -- cgit From 6bbc9ca6a3a7eacff0363770c2bc3e7640c2996c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:19 +0200 Subject: mlxsw: spectrum_router: Allow address handlers to run on bridge ports Currently the IP address event handlers bail out when the event is related to a netdevice that is a bridge port or a member of a LAG. In order to create a RIF when a bridged or LAG'd port is unenslaved, these event handlers will be replayed. However, at the point in time when the NETDEV_CHANGEUPPER event is delivered, informing of the loss of enslavement, the port is still formally enslaved. In order for the operation to have any effect, these handlers need an extra parameter to indicate that the check for bridge or LAG membership should not be done. In this patch, add an argument "nomaster" to several event handlers. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 109ac2db0d65..6b1b142c95db 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8884,10 +8884,11 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, } static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev, - unsigned long event, + unsigned long event, bool nomaster, struct netlink_ext_ack *extack) { - if (netif_is_any_bridge_port(port_dev) || netif_is_lag_port(port_dev)) + if (!nomaster && (netif_is_any_bridge_port(port_dev) || + netif_is_lag_port(port_dev))) return 0; return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, @@ -8918,10 +8919,10 @@ static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, } static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev, - unsigned long event, + unsigned long event, bool nomaster, struct netlink_ext_ack *extack) { - if (netif_is_bridge_port(lag_dev)) + if (!nomaster && netif_is_bridge_port(lag_dev)) return 0; return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, @@ -8980,7 +8981,7 @@ static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp, struct net_device *vlan_dev, - unsigned long event, + unsigned long event, bool nomaster, struct netlink_ext_ack *extack) { struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); @@ -8988,7 +8989,7 @@ static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp, u16 lower_pvid; int err; - if (netif_is_bridge_port(vlan_dev)) + if (!nomaster && netif_is_bridge_port(vlan_dev)) return 0; if (mlxsw_sp_port_dev_check(real_dev)) { @@ -9132,19 +9133,21 @@ static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp, static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp, struct net_device *dev, - unsigned long event, + unsigned long event, bool nomaster, struct netlink_ext_ack *extack) { if (mlxsw_sp_port_dev_check(dev)) - return mlxsw_sp_inetaddr_port_event(dev, event, extack); + return mlxsw_sp_inetaddr_port_event(dev, event, nomaster, + extack); else if (netif_is_lag_master(dev)) - return mlxsw_sp_inetaddr_lag_event(dev, event, extack); + return mlxsw_sp_inetaddr_lag_event(dev, event, nomaster, + extack); else if (netif_is_bridge_master(dev)) return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, -1, event, extack); else if (is_vlan_dev(dev)) return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp, dev, event, - extack); + nomaster, extack); else if (netif_is_macvlan(dev)) return mlxsw_sp_inetaddr_macvlan_event(mlxsw_sp, dev, event, extack); @@ -9171,7 +9174,8 @@ static int mlxsw_sp_inetaddr_event(struct notifier_block *nb, if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, NULL); + err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, false, + NULL); out: mutex_unlock(&router->lock); return notifier_from_errno(err); @@ -9195,7 +9199,8 @@ static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, ivi->extack); + err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false, + ivi->extack); out: mutex_unlock(&mlxsw_sp->router->lock); return notifier_from_errno(err); @@ -9224,7 +9229,7 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work) if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, NULL); + __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false, NULL); out: mutex_unlock(&mlxsw_sp->router->lock); rtnl_unlock(); @@ -9278,7 +9283,8 @@ static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, i6vi->extack); + err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, false, + i6vi->extack); out: mutex_unlock(&mlxsw_sp->router->lock); return notifier_from_errno(err); @@ -9598,10 +9604,11 @@ static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp, */ rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); if (rif) - __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, + __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, false, extack); - return __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_UP, extack); + return __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_UP, false, + extack); } static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, @@ -9612,7 +9619,7 @@ static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); if (!rif) return; - __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, NULL); + __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, false, NULL); } static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr) -- cgit From 96c3e45c0130205136a13dab129c207e958a5637 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:20 +0200 Subject: mlxsw: spectrum_router: Extract a helper to schedule neighbour work This will come in handy for neighbour replay. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 6b1b142c95db..18e059e94079 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2872,6 +2872,21 @@ static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev) return !!mlxsw_sp_port; } +static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router, + struct neighbour *n) +{ + struct net *net; + + net = neigh_parms_net(n->parms); + + /* Take a reference to ensure the neighbour won't be destructed until we + * drop the reference in delayed work. + */ + neigh_clone(n); + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); +} + static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -2879,7 +2894,6 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, unsigned long interval; struct neigh_parms *p; struct neighbour *n; - struct net *net; router = container_of(nb, struct mlxsw_sp_router, netevent_nb); @@ -2903,7 +2917,6 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, break; case NETEVENT_NEIGH_UPDATE: n = ptr; - net = neigh_parms_net(n->parms); if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6) return NOTIFY_DONE; @@ -2911,13 +2924,7 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, if (!mlxsw_sp_dev_lower_is_port(n->dev)) return NOTIFY_DONE; - /* Take a reference to ensure the neighbour won't be - * destructed until we drop the reference in delayed - * work. - */ - neigh_clone(n); - return mlxsw_sp_router_schedule_work(net, router, n, - mlxsw_sp_router_neigh_event_work); + return mlxsw_sp_router_schedule_neigh_work(router, n); case NETEVENT_IPV4_MPATH_HASH_UPDATE: case NETEVENT_IPV6_MPATH_HASH_UPDATE: -- cgit From 721717fafdc416c66ed66f10ce9ac01e1f52d145 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:21 +0200 Subject: mlxsw: spectrum: Split a helper out of mlxsw_sp_netdevice_event() Move the meat of mlxsw_sp_netdevice_event() to a separate function that does just the validation. This separate helper will be possible to call later for recursive ascent when validating attachment of a front panel port to a bridge with uppers. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 86e2f0ed64d3..0488fe5695bd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -5146,21 +5146,18 @@ static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp, return 0; } -static int mlxsw_sp_netdevice_event(struct notifier_block *nb, - unsigned long event, void *ptr) +static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp, + unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct mlxsw_sp_span_entry *span_entry; - struct mlxsw_sp *mlxsw_sp; int err = 0; - mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb); if (event == NETDEV_UNREGISTER) { span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, dev); if (span_entry) mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry); } - mlxsw_sp_span_respin(mlxsw_sp); if (netif_is_vxlan(dev)) err = mlxsw_sp_netdevice_vxlan_event(mlxsw_sp, dev, event, ptr); @@ -5175,6 +5172,19 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, else if (netif_is_macvlan(dev)) err = mlxsw_sp_netdevice_macvlan_event(dev, event, ptr); + return err; +} + +static int mlxsw_sp_netdevice_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct mlxsw_sp *mlxsw_sp; + int err; + + mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb); + mlxsw_sp_span_respin(mlxsw_sp); + err = __mlxsw_sp_netdevice_event(mlxsw_sp, event, ptr); + return notifier_from_errno(err); } -- cgit From 40b7b4236c1f8e31d7608ecdae07d3889d5e95a0 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:22 +0200 Subject: mlxsw: spectrum: Allow event handlers to check unowned bridges Currently the bridge-related handlers bail out when the event is related to a netdevice that is not an upper of one of the front-panel ports. In order to allow enslavement of front-panel ports to bridges that already have uppers, it will be necessary to replay CHANGEUPPER events to validate that the configuration is offloadable. In order for the replay to be effective, it must be possible to ignore unsupported configuration in the context of an actual notifier event, but to still "veto" these configurations when the validation is performed. To that end, introduce two parameters to a number of handlers: mlxsw_sp, because it will not be possible to deduce that from the netdevice lowers; and process_foreign to indicate whether netdevices that are not front panel uppers should be validated. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 40 +++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 0488fe5695bd..3d1a045ff470 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4936,17 +4936,17 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev, return 0; } -static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev, +static int mlxsw_sp_netdevice_bridge_vlan_event(struct mlxsw_sp *mlxsw_sp, + struct net_device *vlan_dev, struct net_device *br_dev, unsigned long event, void *ptr, - u16 vid) + u16 vid, bool process_foreign) { - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev); struct netdev_notifier_changeupper_info *info = ptr; struct netlink_ext_ack *extack; struct net_device *upper_dev; - if (!mlxsw_sp) + if (!process_foreign && !mlxsw_sp_lower_get(vlan_dev)) return 0; extack = netdev_notifier_info_to_extack(&info->info); @@ -4979,8 +4979,10 @@ static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev, return 0; } -static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev, - unsigned long event, void *ptr) +static int mlxsw_sp_netdevice_vlan_event(struct mlxsw_sp *mlxsw_sp, + struct net_device *vlan_dev, + unsigned long event, void *ptr, + bool process_foreign) { struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); u16 vid = vlan_dev_vlan_id(vlan_dev); @@ -4993,22 +4995,25 @@ static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev, real_dev, event, ptr, vid); else if (netif_is_bridge_master(real_dev)) - return mlxsw_sp_netdevice_bridge_vlan_event(vlan_dev, real_dev, - event, ptr, vid); + return mlxsw_sp_netdevice_bridge_vlan_event(mlxsw_sp, vlan_dev, + real_dev, event, + ptr, vid, + process_foreign); return 0; } -static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev, - unsigned long event, void *ptr) +static int mlxsw_sp_netdevice_bridge_event(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev, + unsigned long event, void *ptr, + bool process_foreign) { - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(br_dev); struct netdev_notifier_changeupper_info *info = ptr; struct netlink_ext_ack *extack; struct net_device *upper_dev; u16 proto; - if (!mlxsw_sp) + if (!process_foreign && !mlxsw_sp_lower_get(br_dev)) return 0; extack = netdev_notifier_info_to_extack(&info->info); @@ -5147,7 +5152,8 @@ static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp, } static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp, - unsigned long event, void *ptr) + unsigned long event, void *ptr, + bool process_foreign) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct mlxsw_sp_span_entry *span_entry; @@ -5166,9 +5172,11 @@ static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp, else if (netif_is_lag_master(dev)) err = mlxsw_sp_netdevice_lag_event(dev, event, ptr); else if (is_vlan_dev(dev)) - err = mlxsw_sp_netdevice_vlan_event(dev, event, ptr); + err = mlxsw_sp_netdevice_vlan_event(mlxsw_sp, dev, event, ptr, + process_foreign); else if (netif_is_bridge_master(dev)) - err = mlxsw_sp_netdevice_bridge_event(dev, event, ptr); + err = mlxsw_sp_netdevice_bridge_event(mlxsw_sp, dev, event, ptr, + process_foreign); else if (netif_is_macvlan(dev)) err = mlxsw_sp_netdevice_macvlan_event(dev, event, ptr); @@ -5183,7 +5191,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb); mlxsw_sp_span_respin(mlxsw_sp); - err = __mlxsw_sp_netdevice_event(mlxsw_sp, event, ptr); + err = __mlxsw_sp_netdevice_event(mlxsw_sp, event, ptr, false); return notifier_from_errno(err); } -- cgit From 1c47e65b8c0ba018152beb13f28afe50017438e4 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:23 +0200 Subject: mlxsw: spectrum: Add a replay_deslavement argument to event handlers When handling deslavement of LAG or its upper from a bridge device, when the deslaved netdevice has an IP address, it should join the router. This should be done after all the lowers of the LAG have left the bridge. The replay intended to cause the device to join the router therefore cannot be invoked unconditionally in the event handlers themselves. It can be done right away if the handler is invoked for a sole device, but when it is invoked repeated for each LAG lower, the replay needs to be postponed until after this processing is done. To that end, add a boolean parameter, replay_deslavement, to mlxsw_sp_netdevice_port_upper_event(), mlxsw_sp_netdevice_port_vlan_event() and one helper on the call path. Have the invocations that are done for sole netdevices pass true, and those done for LAG lowers pass false. Nothing depends on this flag at this point, but it removes some noise from the patch that introduces the replay itself. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 3d1a045ff470..b9ceffe258bf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4641,7 +4641,8 @@ static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev, static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, struct net_device *dev, - unsigned long event, void *ptr) + unsigned long event, void *ptr, + bool replay_deslavement) { struct netdev_notifier_changeupper_info *info; struct mlxsw_sp_port *mlxsw_sp_port; @@ -4815,13 +4816,15 @@ static int mlxsw_sp_netdevice_port_lower_event(struct net_device *dev, static int mlxsw_sp_netdevice_port_event(struct net_device *lower_dev, struct net_device *port_dev, - unsigned long event, void *ptr) + unsigned long event, void *ptr, + bool replay_deslavement) { switch (event) { case NETDEV_PRECHANGEUPPER: case NETDEV_CHANGEUPPER: return mlxsw_sp_netdevice_port_upper_event(lower_dev, port_dev, - event, ptr); + event, ptr, + replay_deslavement); case NETDEV_CHANGELOWERSTATE: return mlxsw_sp_netdevice_port_lower_event(port_dev, event, ptr); @@ -4840,7 +4843,7 @@ static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev, netdev_for_each_lower_dev(lag_dev, dev, iter) { if (mlxsw_sp_port_dev_check(dev)) { ret = mlxsw_sp_netdevice_port_event(lag_dev, dev, event, - ptr); + ptr, false); if (ret) return ret; } @@ -4852,7 +4855,7 @@ static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev, static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev, struct net_device *dev, unsigned long event, void *ptr, - u16 vid) + u16 vid, bool replay_deslavement) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; @@ -4927,7 +4930,7 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev, if (mlxsw_sp_port_dev_check(dev)) { ret = mlxsw_sp_netdevice_port_vlan_event(vlan_dev, dev, event, ptr, - vid); + vid, false); if (ret) return ret; } @@ -4989,7 +4992,8 @@ static int mlxsw_sp_netdevice_vlan_event(struct mlxsw_sp *mlxsw_sp, if (mlxsw_sp_port_dev_check(real_dev)) return mlxsw_sp_netdevice_port_vlan_event(vlan_dev, real_dev, - event, ptr, vid); + event, ptr, vid, + true); else if (netif_is_lag_master(real_dev)) return mlxsw_sp_netdevice_lag_port_vlan_event(vlan_dev, real_dev, event, @@ -5168,7 +5172,7 @@ static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp, if (netif_is_vxlan(dev)) err = mlxsw_sp_netdevice_vxlan_event(mlxsw_sp, dev, event, ptr); else if (mlxsw_sp_port_dev_check(dev)) - err = mlxsw_sp_netdevice_port_event(dev, dev, event, ptr); + err = mlxsw_sp_netdevice_port_event(dev, dev, event, ptr, true); else if (netif_is_lag_master(dev)) err = mlxsw_sp_netdevice_lag_event(dev, event, ptr); else if (is_vlan_dev(dev)) -- cgit From 987c7782f0627e1c87617458806a7e6c1995678a Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:24 +0200 Subject: mlxsw: spectrum: On port enslavement to a LAG, join upper's bridges Currently it never happens that a netdevice that is already a bridge slave would suddenly become mlxsw upper. The only case where this might be possible as far as mlxsw is concerned, is with LAG netdevices. But if a LAG already has an upper, enslaving mlxsw port to that LAG is forbidden. Thus the only way to install a LAG between a bridge and a mlxsw port is by first enslaving the port to the LAG, and then enslaving that LAG to a bridge. However in the following patches, the requirement that ports be only enslaved to masters without uppers, is going to be relaxed. It will therefore be necessary to join bridges of LAG uppers. Without this replay, the mlxsw bridge_port objects are not instantiated, which causes issues later, as a lot of code relies on their presence. Therefore in this patch, when the first mlxsw physical netdevice is enslaved to a LAG, consider bridges upper to the LAG (both the direct master, if any, and any bridge masters of VLAN uppers), and have the relevant netdevices join their bridges. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 90 ++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index b9ceffe258bf..9a6e1ce4e786 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4337,6 +4337,88 @@ static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp, return -EBUSY; } +static int mlxsw_sp_lag_uppers_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + struct net_device *upper_dev; + struct net_device *master; + struct list_head *iter; + int done = 0; + int err; + + master = netdev_master_upper_dev_get(lag_dev); + if (master && netif_is_bridge_master(master)) { + err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, lag_dev, master, + extack); + if (err) + return err; + } + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (master && netif_is_bridge_master(master)) { + err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, + upper_dev, master, + extack); + if (err) + goto err_port_bridge_join; + } + + ++done; + } + + return 0; + +err_port_bridge_join: + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (!master || !netif_is_bridge_master(master)) + continue; + + if (!done--) + break; + + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master); + } + + master = netdev_master_upper_dev_get(lag_dev); + if (master && netif_is_bridge_master(master)) + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master); + + return err; +} + +static void +mlxsw_sp_lag_uppers_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev) +{ + struct net_device *upper_dev; + struct net_device *master; + struct list_head *iter; + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (!master) + continue; + + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master); + } + + master = netdev_master_upper_dev_get(lag_dev); + if (master) + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master); +} + static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack) @@ -4361,6 +4443,12 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index); if (err) return err; + + err = mlxsw_sp_lag_uppers_bridge_join(mlxsw_sp_port, lag_dev, + extack); + if (err) + goto err_lag_uppers_bridge_join; + err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index); if (err) goto err_col_port_add; @@ -4390,6 +4478,8 @@ err_router_join: mlxsw_sp_port->local_port); mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id); err_col_port_add: + mlxsw_sp_lag_uppers_bridge_leave(mlxsw_sp_port, lag_dev); +err_lag_uppers_bridge_join: if (!lag->ref_count) mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); return err; -- cgit From ec4643ca3d98c4a7a421f11b76c8a46223a1aa19 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:25 +0200 Subject: mlxsw: spectrum_switchdev: Replay switchdev objects on port join Currently it never happens that a netdevice that is already a bridge slave would suddenly become mlxsw upper. The only case where this might be possible as far as mlxsw is concerned, is with LAG netdevices. But if a LAG has any upper (e.g. is enslaved), enlaving mlxsw port to that LAG is forbidden. Thus the only way to install a LAG between a bridge and a mlxsw port is by first enslaving the port to the LAG, and then enslaving that LAG to a bridge. At that point there are no bridge objects (such as port VLANs) to replay. Those are added afterwards, and notified as they are created. This holds even for the PVID. However in the following patches, the requirement that ports be only enslaved to masters without uppers, is going to be relaxed. It will therefore be necessary to replay the existing bridge objects. Without this replay, e.g. the mlxsw bridge_port_vlan objects are not instantiated, which causes issues later, as a lot of code relies on their presence. To that end, add a new notifier block whose sole role is to filter out events related to the one relevant upper, and forward those to the existing switchdev notifier block. Pass the new notifier block to switchdev_bridge_port_offload() when the bridge port is created. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 131 ++++++++++++++++++++- 3 files changed, 132 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 9a6e1ce4e786..8087da00f38f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1132,8 +1132,8 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev, return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid)); } -static int mlxsw_sp_port_kill_vid(struct net_device *dev, - __be16 __always_unused proto, u16 vid) +int mlxsw_sp_port_kill_vid(struct net_device *dev, + __be16 __always_unused proto, u16 vid) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index c6231e62a371..65eaa181e0aa 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -700,6 +700,8 @@ int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, struct mlxsw_sp_port_vlan * mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); +int mlxsw_sp_port_kill_vid(struct net_device *dev, + __be16 __always_unused proto, u16 vid); int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin, u16 vid_end, bool is_member, bool untagged); int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 79d45c6c6edf..982eae6bd63e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -384,6 +384,91 @@ mlxsw_sp_bridge_port_find(struct mlxsw_sp_bridge *bridge, return __mlxsw_sp_bridge_port_find(bridge_device, brport_dev); } +static int mlxsw_sp_port_obj_add(struct net_device *dev, const void *ctx, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack); +static int mlxsw_sp_port_obj_del(struct net_device *dev, const void *ctx, + const struct switchdev_obj *obj); + +struct mlxsw_sp_bridge_port_replay_switchdev_objs { + struct net_device *brport_dev; + struct mlxsw_sp_port *mlxsw_sp_port; + int done; +}; + +static int +mlxsw_sp_bridge_port_replay_switchdev_objs(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + struct switchdev_notifier_port_obj_info *port_obj_info = ptr; + struct netlink_ext_ack *extack = port_obj_info->info.extack; + struct mlxsw_sp_bridge_port_replay_switchdev_objs *rso; + int err = 0; + + rso = (void *)port_obj_info->info.ctx; + + if (event != SWITCHDEV_PORT_OBJ_ADD || + dev != rso->brport_dev) + goto out; + + /* When a port is joining the bridge through a LAG, there likely are + * VLANs configured on that LAG already. The replay will thus attempt to + * have the given port-vlans join the corresponding FIDs. But the LAG + * netdevice has already called the ndo_vlan_rx_add_vid NDO for its VLAN + * memberships, back before CHANGEUPPER was distributed and netdevice + * master set. So now before propagating the VLAN events further, we + * first need to kill the corresponding VID at the mlxsw_sp_port. + * + * Note that this doesn't need to be rolled back on failure -- if the + * replay fails, the enslavement is off, and the VIDs would be killed by + * LAG anyway as part of its rollback. + */ + if (port_obj_info->obj->id == SWITCHDEV_OBJ_ID_PORT_VLAN) { + u16 vid = SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj)->vid; + + err = mlxsw_sp_port_kill_vid(rso->mlxsw_sp_port->dev, 0, vid); + if (err) + goto out; + } + + ++rso->done; + err = mlxsw_sp_port_obj_add(rso->mlxsw_sp_port->dev, NULL, + port_obj_info->obj, extack); + +out: + return notifier_from_errno(err); +} + +static struct notifier_block mlxsw_sp_bridge_port_replay_switchdev_objs_nb = { + .notifier_call = mlxsw_sp_bridge_port_replay_switchdev_objs, +}; + +static int +mlxsw_sp_bridge_port_unreplay_switchdev_objs(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + struct switchdev_notifier_port_obj_info *port_obj_info = ptr; + struct mlxsw_sp_bridge_port_replay_switchdev_objs *rso; + + rso = (void *)port_obj_info->info.ctx; + + if (event != SWITCHDEV_PORT_OBJ_ADD || + dev != rso->brport_dev) + return NOTIFY_DONE; + if (!rso->done--) + return NOTIFY_STOP; + + mlxsw_sp_port_obj_del(rso->mlxsw_sp_port->dev, NULL, + port_obj_info->obj); + return NOTIFY_DONE; +} + +static struct notifier_block mlxsw_sp_bridge_port_unreplay_switchdev_objs_nb = { + .notifier_call = mlxsw_sp_bridge_port_unreplay_switchdev_objs, +}; + static struct mlxsw_sp_bridge_port * mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device, struct net_device *brport_dev, @@ -2350,6 +2435,33 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, return NULL; } +static int +mlxsw_sp_bridge_port_replay(struct mlxsw_sp_bridge_port *bridge_port, + struct mlxsw_sp_port *mlxsw_sp_port, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_bridge_port_replay_switchdev_objs rso = { + .brport_dev = bridge_port->dev, + .mlxsw_sp_port = mlxsw_sp_port, + }; + struct notifier_block *nb; + int err; + + nb = &mlxsw_sp_bridge_port_replay_switchdev_objs_nb; + err = switchdev_bridge_port_replay(bridge_port->dev, mlxsw_sp_port->dev, + &rso, NULL, nb, extack); + if (err) + goto err_replay; + + return 0; + +err_replay: + nb = &mlxsw_sp_bridge_port_unreplay_switchdev_objs_nb; + switchdev_bridge_port_replay(bridge_port->dev, mlxsw_sp_port->dev, + &rso, NULL, nb, extack); + return err; +} + static int mlxsw_sp_bridge_vlan_aware_port_join(struct mlxsw_sp_bridge_port *bridge_port, struct mlxsw_sp_port *mlxsw_sp_port, @@ -2364,7 +2476,7 @@ mlxsw_sp_bridge_vlan_aware_port_join(struct mlxsw_sp_bridge_port *bridge_port, if (mlxsw_sp_port->default_vlan->fid) mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan); - return 0; + return mlxsw_sp_bridge_port_replay(bridge_port, mlxsw_sp_port, extack); } static int @@ -2536,6 +2648,7 @@ mlxsw_sp_bridge_8021d_port_join(struct mlxsw_sp_bridge_device *bridge_device, struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; struct net_device *dev = bridge_port->dev; u16 vid; + int err; vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : MLXSW_SP_DEFAULT_VID; mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid); @@ -2551,8 +2664,20 @@ mlxsw_sp_bridge_8021d_port_join(struct mlxsw_sp_bridge_device *bridge_device, if (mlxsw_sp_port_vlan->fid) mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); - return mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port, - extack); + err = mlxsw_sp_port_vlan_bridge_join(mlxsw_sp_port_vlan, bridge_port, + extack); + if (err) + return err; + + err = mlxsw_sp_bridge_port_replay(bridge_port, mlxsw_sp_port, extack); + if (err) + goto err_replay; + + return 0; + +err_replay: + mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan); + return err; } static void -- cgit From ef59713c26b1c2a9b0b3a8c481b23335ce6d7183 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:26 +0200 Subject: mlxsw: spectrum_router: Join RIFs of LAG upper VLANs In the following patches, the requirement that ports be only enslaved to masters without uppers, is going to be relaxed. It will therefore be necessary to join not only RIF for the immediate LAG, as is currently the case, but also RIFs for VLAN netdevices upper to the LAG. In this patch, extend mlxsw_sp_netdevice_router_join_lag() to walk the uppers of a LAG being joined, and also join any VLAN ones. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 55 ++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 18e059e94079..ae2d5e760f1b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -9685,15 +9685,64 @@ mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port, dev, extack); } +static void +mlxsw_sp_port_vid_router_leave(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, + struct net_device *dev) +{ + struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; + + mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, + vid); + if (WARN_ON(!mlxsw_sp_port_vlan)) + return; + + __mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); +} + static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack) { u16 default_vid = MLXSW_SP_DEFAULT_VID; + struct net_device *upper_dev; + struct list_head *iter; + int done = 0; + u16 vid; + int err; - return mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, - default_vid, lag_dev, - extack); + err = mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, default_vid, + lag_dev, extack); + if (err) + return err; + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + vid = vlan_dev_vlan_id(upper_dev); + err = mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, vid, + upper_dev, extack); + if (err) + goto err_router_join_dev; + + ++done; + } + + return 0; + +err_router_join_dev: + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + if (!done--) + break; + + vid = vlan_dev_vlan_id(upper_dev); + mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev); + } + + mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev); + return err; } int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, -- cgit From cfc01a92eaffdb9ac635f3aedc00ad5a6a2f437a Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:27 +0200 Subject: mlxsw: spectrum_router: Offload ethernet nexthops when RIF is made As RIF is created, refresh each netxhop group tracked at the CRIF for which the RIF was created. Note that nothing needs to be done for IPIP nexthops. The RIF for these is either available from the get-go, or will never be available, so no after the fact offloading needs to be done. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index ae2d5e760f1b..fe1855cc2c76 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -4404,6 +4404,19 @@ err_neigh_init: return err; } +static int mlxsw_sp_nexthop_type_rif_made(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) +{ + switch (nh->type) { + case MLXSW_SP_NEXTHOP_TYPE_ETH: + return mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh); + case MLXSW_SP_NEXTHOP_TYPE_IPIP: + break; + } + + return 0; +} + static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh) { @@ -4532,6 +4545,35 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, } } +static int mlxsw_sp_nexthop_rif_made_sync(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *rif) +{ + struct mlxsw_sp_nexthop *nh, *tmp; + unsigned int n = 0; + int err; + + list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list, + crif_list_node) { + err = mlxsw_sp_nexthop_type_rif_made(mlxsw_sp, nh); + if (err) + goto err_nexthop_type_rif; + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + n++; + } + + return 0; + +err_nexthop_type_rif: + list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list, + crif_list_node) { + if (!n--) + break; + mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh); + mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); + } + return err; +} + static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { @@ -7892,6 +7934,12 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); } +static int mlxsw_sp_router_rif_made_sync(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *rif) +{ + return mlxsw_sp_nexthop_rif_made_sync(mlxsw_sp, rif); +} + static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { @@ -8329,6 +8377,10 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, goto err_mr_rif_add; } + err = mlxsw_sp_router_rif_made_sync(mlxsw_sp, rif); + if (err) + goto err_rif_made_sync; + if (netdev_offload_xstats_enabled(params->dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { err = mlxsw_sp_router_port_l3_stats_enable(rif); @@ -8343,6 +8395,8 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, return rif; err_stats_enable: + mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); +err_rif_made_sync: err_mr_rif_add: for (i--; i >= 0; i--) mlxsw_sp_mr_rif_del(vr->mr_table[i], rif); -- cgit From 49c3a615d382c984a373690b8c4aa783f58e8089 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:28 +0200 Subject: mlxsw: spectrum_router: Replay MACVLANs when RIF is made If IP address is added to a MACVLAN netdevice, the effect is of configuring VRRP on the RIF for the netdevice linked to the MACVLAN. Because the MACVLAN offload is tied to existence of a RIF at the linked netdevice, adding a MACVLAN is currently not allowed until a RIF is present. If this requirement stays, it will never be possible to attach a first port into a topology that involves a MACVLAN. Thus topologies would need to be built in a certain order, which is impractical. Additionally, IP address removal, which leads to disappearance of the RIF that the MACVLAN depends on, cannot be vetoed. Thus even as things stand now it is possible to get to a state where a MACVLAN netdevice exists without a RIF, despite having mlxsw lowers. And once the MACVLAN is un-offloaded due to RIF getting destroyed, recreating the RIF does not bring it back. In this patch, accept that MACVLAN can be created out of order and support that use case. One option would seem to be to simply recognize MACVLAN netdevices as "interesting", and let the existing replay mechanisms take care of the offload. However, that does not address the necessity to reoffload MACVLAN once a RIF is created. Thus add a new replay hook, symmetrical to mlxsw_sp_rif_macvlan_flush(), called mlxsw_sp_rif_macvlan_replay(), which instead of unwinding the existing offloads, applies the configuration as if the netdevice were created just now. Additionally, remove all vetoes and warning messages that checked for presence of a RIF at the linked device. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 22 -------- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 59 ++++++++++++++++++++-- 2 files changed, 54 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8087da00f38f..4346cc736579 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4786,11 +4786,6 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, NL_SET_ERR_MSG_MOD(extack, "Can not put a VLAN on a LAG port"); return -EINVAL; } - if (netif_is_macvlan(upper_dev) && - !mlxsw_sp_rif_exists(mlxsw_sp, lower_dev)) { - NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces"); - return -EOPNOTSUPP; - } if (netif_is_ovs_master(upper_dev) && vlan_uses_dev(dev)) { NL_SET_ERR_MSG_MOD(extack, "Master device is an OVS master and this device has a VLAN"); return -EINVAL; @@ -4979,11 +4974,6 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev, NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported"); return -EINVAL; } - if (netif_is_macvlan(upper_dev) && - !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) { - NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces"); - return -EOPNOTSUPP; - } break; case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; @@ -5052,13 +5042,6 @@ static int mlxsw_sp_netdevice_bridge_vlan_event(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type"); return -EOPNOTSUPP; } - if (!info->linking) - break; - if (netif_is_macvlan(upper_dev) && - !mlxsw_sp_rif_exists(mlxsw_sp, vlan_dev)) { - NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces"); - return -EOPNOTSUPP; - } break; case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; @@ -5135,11 +5118,6 @@ static int mlxsw_sp_netdevice_bridge_event(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(extack, "VLAN uppers are only supported with 802.1q VLAN protocol"); return -EOPNOTSUPP; } - if (netif_is_macvlan(upper_dev) && - !mlxsw_sp_rif_exists(mlxsw_sp, br_dev)) { - NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces"); - return -EOPNOTSUPP; - } break; case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index fe1855cc2c76..2322429cdb72 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -9121,10 +9121,8 @@ static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp, int err; rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev); - if (!rif) { - NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces"); - return -EOPNOTSUPP; - } + if (!rif) + return 0; err = mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); @@ -9857,6 +9855,40 @@ out: return notifier_from_errno(err); } +struct mlxsw_sp_macvlan_replay { + struct mlxsw_sp *mlxsw_sp; + struct netlink_ext_ack *extack; +}; + +static int mlxsw_sp_macvlan_replay_upper(struct net_device *dev, + struct netdev_nested_priv *priv) +{ + const struct mlxsw_sp_macvlan_replay *rms = priv->data; + struct netlink_ext_ack *extack = rms->extack; + struct mlxsw_sp *mlxsw_sp = rms->mlxsw_sp; + + if (!netif_is_macvlan(dev)) + return 0; + + return mlxsw_sp_rif_macvlan_add(mlxsw_sp, dev, extack); +} + +static int mlxsw_sp_macvlan_replay(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_macvlan_replay rms = { + .mlxsw_sp = rif->mlxsw_sp, + .extack = extack, + }; + struct netdev_nested_priv priv = { + .data = &rms, + }; + + return netdev_walk_all_upper_dev_rcu(mlxsw_sp_rif_dev(rif), + mlxsw_sp_macvlan_replay_upper, + &priv); +} + static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, struct netdev_nested_priv *priv) { @@ -9879,7 +9911,6 @@ static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif) if (!netif_is_macvlan_port(dev)) return 0; - netdev_warn(dev, "Router interface is deleted. Upper macvlans will not work\n"); return netdev_walk_all_upper_dev_rcu(dev, __mlxsw_sp_rif_macvlan_flush, &priv); } @@ -9937,6 +9968,10 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, if (err) goto err_rif_subport_op; + err = mlxsw_sp_macvlan_replay(rif, extack); + if (err) + goto err_macvlan_replay; + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) @@ -9952,6 +9987,8 @@ err_fid_rif_set: mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: + mlxsw_sp_rif_macvlan_flush(rif); +err_macvlan_replay: mlxsw_sp_rif_subport_op(rif, false); err_rif_subport_op: mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, mac_profile); @@ -10038,6 +10075,10 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, if (err) goto err_fid_bc_flood_set; + err = mlxsw_sp_macvlan_replay(rif, extack); + if (err) + goto err_macvlan_replay; + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) @@ -10053,6 +10094,8 @@ err_fid_rif_set: mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: + mlxsw_sp_rif_macvlan_flush(rif); +err_macvlan_replay: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, mlxsw_sp_router_port(mlxsw_sp), false); err_fid_bc_flood_set: @@ -10200,6 +10243,10 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, if (err) goto err_fid_bc_flood_set; + err = mlxsw_sp_macvlan_replay(rif, extack); + if (err) + goto err_macvlan_replay; + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) @@ -10215,6 +10262,8 @@ err_fid_rif_set: mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: + mlxsw_sp_rif_macvlan_flush(rif); +err_macvlan_replay: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, mlxsw_sp_router_port(mlxsw_sp), false); err_fid_bc_flood_set: -- cgit From 8fdb09a7674c61c4f0e5faf0d63b3ce500a341b0 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:29 +0200 Subject: mlxsw: spectrum_router: Replay neighbours when RIF is made As neighbours are created, mlxsw is involved through the netevent notifications. When at the time there is no RIF for a given neighbour, the notification is not acted upon. When the RIF is later created, these outstanding neighbours are left unoffloaded and cause traffic to go through the SW datapath. In order to fix this issue, as a RIF is created, walk the ARP and ND tables and find neighbours for the netdevice that represents the RIF. Then schedule neighbour work for them, allowing them to be offloaded. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 62 +++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 2322429cdb72..9263a914bcc7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2983,6 +2983,52 @@ static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, } } +struct mlxsw_sp_neigh_rif_made_sync { + struct mlxsw_sp *mlxsw_sp; + struct mlxsw_sp_rif *rif; + int err; +}; + +static void mlxsw_sp_neigh_rif_made_sync_each(struct neighbour *n, void *data) +{ + struct mlxsw_sp_neigh_rif_made_sync *rms = data; + int rc; + + if (rms->err) + return; + if (n->dev != mlxsw_sp_rif_dev(rms->rif)) + return; + rc = mlxsw_sp_router_schedule_neigh_work(rms->mlxsw_sp->router, n); + if (rc != NOTIFY_DONE) + rms->err = -ENOMEM; +} + +static int mlxsw_sp_neigh_rif_made_sync(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *rif) +{ + struct mlxsw_sp_neigh_rif_made_sync rms = { + .mlxsw_sp = mlxsw_sp, + .rif = rif, + }; + + neigh_for_each(&arp_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); + if (rms.err) + goto err_arp; + +#if IS_ENABLED(CONFIG_IPV6) + neigh_for_each(&nd_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); +#endif + if (rms.err) + goto err_nd; + + return 0; + +err_nd: +err_arp: + mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif); + return rms.err; +} + enum mlxsw_sp_nexthop_type { MLXSW_SP_NEXTHOP_TYPE_ETH, MLXSW_SP_NEXTHOP_TYPE_IPIP, @@ -7937,7 +7983,21 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) static int mlxsw_sp_router_rif_made_sync(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { - return mlxsw_sp_nexthop_rif_made_sync(mlxsw_sp, rif); + int err; + + err = mlxsw_sp_neigh_rif_made_sync(mlxsw_sp, rif); + if (err) + return err; + + err = mlxsw_sp_nexthop_rif_made_sync(mlxsw_sp, rif); + if (err) + goto err_nexthop; + + return 0; + +err_nexthop: + mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif); + return err; } static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, -- cgit From 31618b22f2c4c0a4491554a2d879141efdffe88f Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:30 +0200 Subject: mlxsw: spectrum_router: Replay IP NETDEV_UP on device enslavement Enslaving of front panel ports (and their uppers) to netdevices that already have uppers is currently forbidden. When this is permitted, any uppers with IP addresses need to have the NETDEV_UP inetaddr event replayed, so that any RIFs are created. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 6 ++ .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 119 +++++++++++++++++++++ .../net/ethernet/mellanox/mlxsw/spectrum_router.h | 5 + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 7 ++ 4 files changed, 137 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4346cc736579..0dcd988ffce1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4469,8 +4469,14 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, if (err) goto err_router_join; + err = mlxsw_sp_netdevice_enslavement_replay(mlxsw_sp, lag_dev, extack); + if (err) + goto err_replay; + return 0; +err_replay: + mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev); err_router_join: lag->ref_count--; mlxsw_sp_port->lagged = 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 9263a914bcc7..18d1bcbb3fdf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -9781,6 +9781,97 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, return err; } +struct mlxsw_sp_router_replay_inetaddr_up { + struct mlxsw_sp *mlxsw_sp; + struct netlink_ext_ack *extack; + unsigned int done; +}; + +static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev, + struct netdev_nested_priv *priv) +{ + struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data; + struct mlxsw_sp_crif *crif; + int err; + + if (mlxsw_sp_dev_addr_list_empty(dev)) + return 0; + + crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev); + if (!crif || crif->rif) + return 0; + + if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP)) + return 0; + + err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP, + false, ctx->extack); + if (err) + return err; + + ctx->done++; + return 0; +} + +static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev, + struct netdev_nested_priv *priv) +{ + struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data; + struct mlxsw_sp_crif *crif; + + if (!ctx->done) + return 0; + + if (mlxsw_sp_dev_addr_list_empty(dev)) + return 0; + + crif = mlxsw_sp_crif_lookup(ctx->mlxsw_sp->router, dev); + if (!crif || !crif->rif) + return 0; + + /* We are rolling back NETDEV_UP, so ask for that. */ + if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP)) + return 0; + + __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, false, NULL); + + ctx->done--; + return 0; +} + +int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp, + struct net_device *upper_dev, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_router_replay_inetaddr_up ctx = { + .mlxsw_sp = mlxsw_sp, + .extack = extack, + }; + struct netdev_nested_priv priv = { + .data = &ctx, + }; + int err; + + err = mlxsw_sp_router_replay_inetaddr_up(upper_dev, &priv); + if (err) + return err; + + err = netdev_walk_all_upper_dev_rcu(upper_dev, + mlxsw_sp_router_replay_inetaddr_up, + &priv); + if (err) + goto err_replay_up; + + return 0; + +err_replay_up: + netdev_walk_all_upper_dev_rcu(upper_dev, + mlxsw_sp_router_unreplay_inetaddr_up, + &priv); + mlxsw_sp_router_unreplay_inetaddr_up(upper_dev, &priv); + return err; +} + static int mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, struct net_device *dev, @@ -9857,6 +9948,26 @@ err_router_join_dev: return err; } +static void +__mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev) +{ + u16 default_vid = MLXSW_SP_DEFAULT_VID; + struct net_device *upper_dev; + struct list_head *iter; + u16 vid; + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + vid = vlan_dev_vlan_id(upper_dev); + mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, vid, upper_dev); + } + + mlxsw_sp_port_vid_router_leave(mlxsw_sp_port, default_vid, lag_dev); +} + int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack) @@ -9870,6 +9981,14 @@ int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, return err; } +void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev) +{ + mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock); + __mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev); + mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock); +} + static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 74242220a0cf..eed04fbf719f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -178,5 +178,10 @@ int mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack); +void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev); +int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp, + struct net_device *upper_dev, + struct netlink_ext_ack *extack); #endif /* _MLXSW_ROUTER_H_*/ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 982eae6bd63e..dffb67c1038e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -2894,8 +2894,15 @@ int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port, if (err) goto err_port_join; + err = mlxsw_sp_netdevice_enslavement_replay(mlxsw_sp, br_dev, extack); + if (err) + goto err_replay; + return 0; +err_replay: + bridge_device->ops->port_leave(bridge_device, bridge_port, + mlxsw_sp_port); err_port_join: mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port); return err; -- cgit From 4560cf408ecae4824a2bbdcef83cf91b2db5d268 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:31 +0200 Subject: mlxsw: spectrum_router: Replay IP NETDEV_UP on device deslavement When a netdevice is removed from a bridge or a LAG, and it has an IP address, it should join the router and gain a RIF. Do that by replaying address addition event on the netdevice. When handling deslavement of LAG or its upper from a bridge device, the replay should be done after all the lowers of the LAG have left the bridge. Thus these scenarios are handled by passing replay_deslavement of false, and by invoking, after the lowers have been processed, a new helper, mlxsw_sp_netdevice_post_lag_event(), which does the per-LAG / -upper handling, and in particular invokes the replay. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 48 +++++++++++++++++++--- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 23 ++++++++++- .../net/ethernet/mellanox/mlxsw/spectrum_router.h | 2 + 3 files changed, 65 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 0dcd988ffce1..b955511fe5a2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4838,15 +4838,20 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; if (netif_is_bridge_master(upper_dev)) { - if (info->linking) + if (info->linking) { err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, lower_dev, upper_dev, extack); - else + } else { mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lower_dev, upper_dev); + if (!replay_deslavement) + break; + mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp, + lower_dev); + } } else if (netif_is_lag_master(upper_dev)) { if (info->linking) { err = mlxsw_sp_port_lag_join(mlxsw_sp_port, @@ -4855,6 +4860,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port); mlxsw_sp_port_lag_leave(mlxsw_sp_port, upper_dev); + mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp, + dev); } } else if (netif_is_ovs_master(upper_dev)) { if (info->linking) @@ -4924,6 +4931,30 @@ static int mlxsw_sp_netdevice_port_event(struct net_device *lower_dev, return 0; } +/* Called for LAG or its upper VLAN after the per-LAG-lower processing was done, + * to do any per-LAG / per-LAG-upper processing. + */ +static int mlxsw_sp_netdevice_post_lag_event(struct net_device *dev, + unsigned long event, + void *ptr) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(dev); + struct netdev_notifier_changeupper_info *info = ptr; + + if (!mlxsw_sp) + return 0; + + switch (event) { + case NETDEV_CHANGEUPPER: + if (info->linking) + break; + if (netif_is_bridge_master(info->upper_dev)) + mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp, dev); + break; + } + return 0; +} + static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev, unsigned long event, void *ptr) { @@ -4940,7 +4971,7 @@ static int mlxsw_sp_netdevice_lag_event(struct net_device *lag_dev, } } - return 0; + return mlxsw_sp_netdevice_post_lag_event(lag_dev, event, ptr); } static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev, @@ -4984,15 +5015,20 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev, case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; if (netif_is_bridge_master(upper_dev)) { - if (info->linking) + if (info->linking) { err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, vlan_dev, upper_dev, extack); - else + } else { mlxsw_sp_port_bridge_leave(mlxsw_sp_port, vlan_dev, upper_dev); + if (!replay_deslavement) + break; + mlxsw_sp_netdevice_deslavement_replay(mlxsw_sp, + vlan_dev); + } } else if (netif_is_macvlan(upper_dev)) { if (!info->linking) mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev); @@ -5022,7 +5058,7 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev, } } - return 0; + return mlxsw_sp_netdevice_post_lag_event(vlan_dev, event, ptr); } static int mlxsw_sp_netdevice_bridge_vlan_event(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 18d1bcbb3fdf..57f0faac836c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -9785,12 +9785,14 @@ struct mlxsw_sp_router_replay_inetaddr_up { struct mlxsw_sp *mlxsw_sp; struct netlink_ext_ack *extack; unsigned int done; + bool deslavement; }; static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev, struct netdev_nested_priv *priv) { struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data; + bool nomaster = ctx->deslavement; struct mlxsw_sp_crif *crif; int err; @@ -9805,7 +9807,7 @@ static int mlxsw_sp_router_replay_inetaddr_up(struct net_device *dev, return 0; err = __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_UP, - false, ctx->extack); + nomaster, ctx->extack); if (err) return err; @@ -9817,6 +9819,7 @@ static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev, struct netdev_nested_priv *priv) { struct mlxsw_sp_router_replay_inetaddr_up *ctx = priv->data; + bool nomaster = ctx->deslavement; struct mlxsw_sp_crif *crif; if (!ctx->done) @@ -9833,7 +9836,8 @@ static int mlxsw_sp_router_unreplay_inetaddr_up(struct net_device *dev, if (!mlxsw_sp_rif_should_config(crif->rif, dev, NETDEV_UP)) return 0; - __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, false, NULL); + __mlxsw_sp_inetaddr_event(ctx->mlxsw_sp, dev, NETDEV_DOWN, nomaster, + NULL); ctx->done--; return 0; @@ -9846,6 +9850,7 @@ int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_router_replay_inetaddr_up ctx = { .mlxsw_sp = mlxsw_sp, .extack = extack, + .deslavement = false, }; struct netdev_nested_priv priv = { .data = &ctx, @@ -9872,6 +9877,20 @@ err_replay_up: return err; } +void mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + struct mlxsw_sp_router_replay_inetaddr_up ctx = { + .mlxsw_sp = mlxsw_sp, + .deslavement = true, + }; + struct netdev_nested_priv priv = { + .data = &ctx, + }; + + mlxsw_sp_router_replay_inetaddr_up(dev, &priv); +} + static int mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, struct net_device *dev, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index eed04fbf719f..ed3b628caafe 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -183,5 +183,7 @@ void mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp, struct net_device *upper_dev, struct netlink_ext_ack *extack); +void mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev); #endif /* _MLXSW_ROUTER_H_*/ -- cgit From 2c5ffe8d7226283856e258c1531c957edb45226c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 19 Jul 2023 13:01:32 +0200 Subject: mlxsw: spectrum: Permit enslavement to netdevices with uppers Enslaving of front panel ports (and their uppers) to netdevices that already have uppers is currently forbidden. In the previous patches, a number of replays have been added. Those ensure that various bits of state, such as next hops or switchdev objects, are offloaded when they become relevant due to a mlxsw lower being introduced into the topology. However the act of actually, for example, enslaving a front-panel port to a bridge with uppers, has been vetoed so far. In this patch, remove the vetoes and permit the operation. mlxsw currently validates creation of "interesting" uppers. Thus creating VLAN netdevices on top of 802.1ad bridges is forbidden if the bridge has an mlxsw lower, but permitted in general. This validation code never gets run when a port is introduced as a lower of an existing netdevice structure. Thus when enslaving an mlxsw netdevice to netdevices with uppers, invoke the PRECHANGEUPPER event handler for each netdevice above the one that the front panel port is being enslaved to. This way the tower of netdevices above the attachment point is validated. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 66 ++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index b955511fe5a2..f0f6af3ec7c5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4735,6 +4735,58 @@ static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev, return true; } +static bool mlxsw_sp_netdev_is_master(struct net_device *upper_dev, + struct net_device *dev) +{ + return upper_dev == netdev_master_upper_dev_get(dev); +} + +static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp, + unsigned long event, void *ptr, + bool process_foreign); + +static int mlxsw_sp_netdevice_validate_uppers(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev, + struct netlink_ext_ack *extack) +{ + struct net_device *upper_dev; + struct list_head *iter; + int err; + + netdev_for_each_upper_dev_rcu(dev, upper_dev, iter) { + struct netdev_notifier_changeupper_info info = { + .info = { + .dev = dev, + .extack = extack, + }, + .master = mlxsw_sp_netdev_is_master(upper_dev, dev), + .upper_dev = upper_dev, + .linking = true, + + /* upper_info is relevant for LAG devices. But we would + * only need this if LAG were a valid upper above + * another upper (e.g. a bridge that is a member of a + * LAG), and that is never a valid configuration. So we + * can keep this as NULL. + */ + .upper_info = NULL, + }; + + err = __mlxsw_sp_netdevice_event(mlxsw_sp, + NETDEV_PRECHANGEUPPER, + &info, true); + if (err) + return err; + + err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp, upper_dev, + extack); + if (err) + return err; + } + + return 0; +} + static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, struct net_device *dev, unsigned long event, void *ptr, @@ -4776,8 +4828,11 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, (!netif_is_bridge_master(upper_dev) || !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev))) { - NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported"); - return -EINVAL; + err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp, + upper_dev, + extack); + if (err) + return err; } if (netif_is_lag_master(upper_dev) && !mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev, @@ -5008,8 +5063,11 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev, (!netif_is_bridge_master(upper_dev) || !mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp, upper_dev))) { - NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported"); - return -EINVAL; + err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp, + upper_dev, + extack); + if (err) + return err; } break; case NETDEV_CHANGEUPPER: -- cgit From f78dca691287813b6f101b207272786f0cb39c65 Mon Sep 17 00:00:00 2001 From: Naveen Mamindlapalli Date: Wed, 19 Jul 2023 16:34:40 +0530 Subject: octeontx2-pf: implement transmit schedular allocation algorithm unlike strict priority, where number of classes are limited to max 8, there is no restriction on the number of dwrr child nodes unless the count increases the max number of child nodes supported. Hardware expects strict priority transmit schedular indexes mapped to their priority. This patch adds defines transmit schedular allocation algorithm such that the above requirement is honored. Signed-off-by: Naveen Mamindlapalli Signed-off-by: Hariprasad Kelam Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/nic/qos.c | 136 ++++++++++++++++++++++- drivers/net/ethernet/marvell/octeontx2/nic/qos.h | 6 + 2 files changed, 136 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c index d3a76c5ccda8..919cd01b7f02 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c @@ -19,6 +19,7 @@ #define OTX2_QOS_CLASS_NONE 0 #define OTX2_QOS_DEFAULT_PRIO 0xF #define OTX2_QOS_INVALID_SQ 0xFFFF +#define OTX2_QOS_INVALID_TXSCHQ_IDX 0xFFFF static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf) { @@ -315,9 +316,14 @@ static void otx2_qos_fill_cfg_tl(struct otx2_qos_node *parent, list_for_each_entry(node, &parent->child_list, list) { otx2_qos_fill_cfg_tl(node, cfg); - cfg->schq_contig[node->level]++; otx2_qos_fill_cfg_schq(node, cfg); } + + /* Assign the required number of transmit schedular queues under the + * given class + */ + cfg->schq_contig[parent->level - 1] += parent->child_dwrr_cnt + + parent->max_static_prio + 1; } static void otx2_qos_prepare_txschq_cfg(struct otx2_nic *pfvf, @@ -401,9 +407,13 @@ static int otx2_qos_add_child_node(struct otx2_qos_node *parent, struct otx2_qos_node *tmp_node; struct list_head *tmp; + if (node->prio > parent->max_static_prio) + parent->max_static_prio = node->prio; + for (tmp = head->next; tmp != head; tmp = tmp->next) { tmp_node = list_entry(tmp, struct otx2_qos_node, list); - if (tmp_node->prio == node->prio) + if (tmp_node->prio == node->prio && + tmp_node->is_static) return -EEXIST; if (tmp_node->prio > node->prio) { list_add_tail(&node->list, tmp); @@ -476,6 +486,7 @@ otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf, node->rate = otx2_convert_rate(rate); node->ceil = otx2_convert_rate(ceil); node->prio = prio; + node->is_static = true; __set_bit(qid, pfvf->qos.qos_sq_bmap); @@ -628,6 +639,21 @@ out: return rc; } +static void otx2_qos_free_unused_txschq(struct otx2_nic *pfvf, + struct otx2_qos_cfg *cfg) +{ + int lvl, idx, schq; + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) { + if (!cfg->schq_index_used[lvl][idx]) { + schq = cfg->schq_contig_list[lvl][idx]; + otx2_txschq_free_one(pfvf, lvl, schq); + } + } + } +} + static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf, struct otx2_qos_node *node, struct otx2_qos_cfg *cfg) @@ -652,9 +678,11 @@ static void otx2_qos_txschq_fill_cfg_tl(struct otx2_nic *pfvf, list_for_each_entry(tmp, &node->child_list, list) { otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg); cnt = cfg->static_node_pos[tmp->level]; - tmp->schq = cfg->schq_contig_list[tmp->level][cnt]; + tmp->schq = cfg->schq_contig_list[tmp->level][tmp->txschq_idx]; + cfg->schq_index_used[tmp->level][tmp->txschq_idx] = true; if (cnt == 0) - node->prio_anchor = tmp->schq; + node->prio_anchor = + cfg->schq_contig_list[tmp->level][0]; cfg->static_node_pos[tmp->level]++; otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg); } @@ -667,9 +695,87 @@ static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf, mutex_lock(&pfvf->qos.qos_lock); otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg); otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg); + otx2_qos_free_unused_txschq(pfvf, cfg); mutex_unlock(&pfvf->qos.qos_lock); } +static void __otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf, + struct otx2_qos_node *tmp, + unsigned long *child_idx_bmap, + int child_cnt) +{ + int idx; + + if (tmp->txschq_idx != OTX2_QOS_INVALID_TXSCHQ_IDX) + return; + + /* assign static nodes 1:1 prio mapping first, then remaining nodes */ + for (idx = 0; idx < child_cnt; idx++) { + if (tmp->is_static && tmp->prio == idx && + !test_bit(idx, child_idx_bmap)) { + tmp->txschq_idx = idx; + set_bit(idx, child_idx_bmap); + return; + } else if (!tmp->is_static && idx >= tmp->prio && + !test_bit(idx, child_idx_bmap)) { + tmp->txschq_idx = idx; + set_bit(idx, child_idx_bmap); + return; + } + } +} + +static int otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + unsigned long *child_idx_bmap; + struct otx2_qos_node *tmp; + int child_cnt; + + list_for_each_entry(tmp, &node->child_list, list) + tmp->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX; + + /* allocate child index array */ + child_cnt = node->child_dwrr_cnt + node->max_static_prio + 1; + child_idx_bmap = kcalloc(BITS_TO_LONGS(child_cnt), + sizeof(unsigned long), + GFP_KERNEL); + if (!child_idx_bmap) + return -ENOMEM; + + list_for_each_entry(tmp, &node->child_list, list) + otx2_qos_assign_base_idx_tl(pfvf, tmp); + + /* assign base index of static priority children first */ + list_for_each_entry(tmp, &node->child_list, list) { + if (!tmp->is_static) + continue; + __otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap, + child_cnt); + } + + /* assign base index of dwrr priority children */ + list_for_each_entry(tmp, &node->child_list, list) + __otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap, + child_cnt); + + kfree(child_idx_bmap); + + return 0; +} + +static int otx2_qos_assign_base_idx(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + int ret = 0; + + mutex_lock(&pfvf->qos.qos_lock); + ret = otx2_qos_assign_base_idx_tl(pfvf, node); + mutex_unlock(&pfvf->qos.qos_lock); + + return ret; +} + static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf, struct otx2_qos_node *node, struct otx2_qos_cfg *cfg) @@ -761,8 +867,10 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg) for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) { - schq = cfg->schq_contig_list[lvl][idx]; - otx2_txschq_free_one(pfvf, lvl, schq); + if (cfg->schq_index_used[lvl][idx]) { + schq = cfg->schq_contig_list[lvl][idx]; + otx2_txschq_free_one(pfvf, lvl, schq); + } } } } @@ -838,6 +946,10 @@ static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf, if (ret) return -ENOSPC; + ret = otx2_qos_assign_base_idx(pfvf, node); + if (ret) + return -ENOMEM; + if (!(pfvf->netdev->flags & IFF_UP)) { otx2_qos_txschq_fill_cfg(pfvf, node, cfg); return 0; @@ -995,6 +1107,7 @@ static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, if (ret) goto out; + parent->child_static_cnt++; set_bit(prio, parent->prio_bmap); /* read current txschq configuration */ @@ -1067,6 +1180,7 @@ free_node: free_old_cfg: kfree(old_cfg); reset_prio: + parent->child_static_cnt--; clear_bit(prio, parent->prio_bmap); out: return ret; @@ -1105,6 +1219,7 @@ static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, goto out; } + node->child_static_cnt++; set_bit(prio, node->prio_bmap); /* store the qid to assign to leaf node */ @@ -1178,6 +1293,7 @@ free_node: free_old_cfg: kfree(old_cfg); reset_prio: + node->child_static_cnt--; clear_bit(prio, node->prio_bmap); out: return ret; @@ -1207,6 +1323,10 @@ static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid, otx2_qos_destroy_node(pfvf, node); pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + parent->child_static_cnt--; + if (!parent->child_static_cnt) + parent->max_static_prio = 0; + clear_bit(prio, parent->prio_bmap); return 0; @@ -1245,6 +1365,10 @@ static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force otx2_qos_destroy_node(pfvf, node); pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + parent->child_static_cnt--; + if (!parent->child_static_cnt) + parent->max_static_prio = 0; + clear_bit(prio, parent->prio_bmap); /* create downstream txschq entries to parent */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h index 19773284be27..faa7c24675d1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h @@ -35,6 +35,7 @@ struct otx2_qos_cfg { int dwrr_node_pos[NIX_TXSCH_LVL_CNT]; u16 schq_contig_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; u16 schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; + bool schq_index_used[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; }; struct otx2_qos { @@ -62,7 +63,12 @@ struct otx2_qos_node { u16 schq; /* hw txschq */ u16 qid; u16 prio_anchor; + u16 max_static_prio; + u16 child_dwrr_cnt; + u16 child_static_cnt; + u16 txschq_idx; /* txschq allocation index */ u8 level; + bool is_static; }; -- cgit From 9fe63d5f1da939855bdfaebfd9e95c96938b6411 Mon Sep 17 00:00:00 2001 From: Naveen Mamindlapalli Date: Wed, 19 Jul 2023 16:34:41 +0530 Subject: sch_htb: Allow HTB quantum parameter in offload mode The current implementation of HTB offload returns the EINVAL error for quantum parameter. This patch removes the error returning checks for 'quantum' parameter and populates its value to tc_htb_qopt_offload structure such that driver can use the same. Add quantum parameter check in mlx5 driver, as mlx5 devices are not capable of supporting the quantum parameter when htb offload is used. Report error if quantum parameter is set to a non-default value. Signed-off-by: Naveen Mamindlapalli Signed-off-by: Hariprasad Kelam Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en/qos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c index 1874c2f0587f..244bc15a42ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c @@ -379,9 +379,9 @@ int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb_ if (!htb && htb_qopt->command != TC_HTB_CREATE) return -EINVAL; - if (htb_qopt->prio) { + if (htb_qopt->prio || htb_qopt->quantum) { NL_SET_ERR_MSG_MOD(htb_qopt->extack, - "prio parameter is not supported by device with HTB offload enabled."); + "prio and quantum parameters are not supported by device with HTB offload enabled."); return -EOPNOTSUPP; } -- cgit From 47a9656f168a4b76a1e069ed8a67924ea8c1ac43 Mon Sep 17 00:00:00 2001 From: Naveen Mamindlapalli Date: Wed, 19 Jul 2023 16:34:42 +0530 Subject: octeontx2-pf: htb offload support for Round Robin scheduling When multiple traffic flows reach Transmit level with the same priority, with Round robin scheduling traffic flow with the highest quantum value is picked. With this support, the user can add multiple classes with the same priority and different quantum. This patch does necessary changes to support the same. Signed-off-by: Naveen Mamindlapalli Signed-off-by: Hariprasad Kelam Signed-off-by: David S. Miller --- .../ethernet/marvell/octeontx2/nic/otx2_common.c | 1 + .../ethernet/marvell/octeontx2/nic/otx2_common.h | 1 + drivers/net/ethernet/marvell/octeontx2/nic/qos.c | 280 ++++++++++++++++++--- drivers/net/ethernet/marvell/octeontx2/nic/qos.h | 5 +- 4 files changed, 247 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 77c8f650f7ac..8cdd92dd9762 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -774,6 +774,7 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf) rsp->schq_list[lvl][schq]; pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl; + pfvf->hw.txschq_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio; return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index ba8091131ec0..37d792f18809 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -224,6 +224,7 @@ struct otx2_hw { /* NIX */ u8 txschq_link_cfg_lvl; + u8 txschq_aggr_lvl_rr_prio; u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; u16 matchall_ipolicer; u32 dwrr_mtu; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c index 919cd01b7f02..1e77bbf5d22a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c @@ -20,6 +20,8 @@ #define OTX2_QOS_DEFAULT_PRIO 0xF #define OTX2_QOS_INVALID_SQ 0xFFFF #define OTX2_QOS_INVALID_TXSCHQ_IDX 0xFFFF +#define CN10K_MAX_RR_WEIGHT GENMASK_ULL(13, 0) +#define OTX2_MAX_RR_QUANTUM GENMASK_ULL(23, 0) static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf) { @@ -66,11 +68,24 @@ static void otx2_qos_get_regaddr(struct otx2_qos_node *node, } } +static int otx2_qos_quantum_to_dwrr_weight(struct otx2_nic *pfvf, u32 quantum) +{ + u32 weight; + + weight = quantum / pfvf->hw.dwrr_mtu; + if (quantum % pfvf->hw.dwrr_mtu) + weight += 1; + + return weight; +} + static void otx2_config_sched_shaping(struct otx2_nic *pfvf, struct otx2_qos_node *node, struct nix_txschq_config *cfg, int *num_regs) { + u32 rr_weight; + u32 quantum; u64 maxrate; otx2_qos_get_regaddr(node, cfg, *num_regs); @@ -87,8 +102,17 @@ static void otx2_config_sched_shaping(struct otx2_nic *pfvf, return; } - /* configure priority */ - cfg->regval[*num_regs] = (node->schq - node->parent->prio_anchor) << 24; + /* configure priority/quantum */ + if (node->is_static) { + cfg->regval[*num_regs] = + (node->schq - node->parent->prio_anchor) << 24; + } else { + quantum = node->quantum ? + node->quantum : pfvf->tx_max_pktlen; + rr_weight = otx2_qos_quantum_to_dwrr_weight(pfvf, quantum); + cfg->regval[*num_regs] = node->parent->child_dwrr_prio << 24 | + rr_weight; + } (*num_regs)++; /* configure PIR */ @@ -196,9 +220,8 @@ static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf, cfg->reg[0] = NIX_AF_TL1X_TOPOLOGY(parent->schq); cfg->regval[0] = (u64)parent->prio_anchor << 32; - if (parent->level == NIX_TXSCH_LVL_TL1) - cfg->regval[0] |= (u64)TXSCH_TL1_DFLT_RR_PRIO << 1; - + cfg->regval[0] |= ((parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO) ? + parent->child_dwrr_prio : 0) << 1; cfg->num_regs++; rc = otx2_sync_mbox_msg(&pfvf->mbox); @@ -384,10 +407,12 @@ otx2_qos_alloc_root(struct otx2_nic *pfvf) return ERR_PTR(-ENOMEM); node->parent = NULL; - if (!is_otx2_vf(pfvf->pcifunc)) + if (!is_otx2_vf(pfvf->pcifunc)) { node->level = NIX_TXSCH_LVL_TL1; - else + } else { node->level = NIX_TXSCH_LVL_TL2; + node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO; + } WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER); node->classid = OTX2_QOS_ROOT_CLASSID; @@ -444,6 +469,10 @@ static int otx2_qos_alloc_txschq_node(struct otx2_nic *pfvf, txschq_node->rate = 0; txschq_node->ceil = 0; txschq_node->prio = 0; + txschq_node->quantum = 0; + txschq_node->is_static = true; + txschq_node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO; + txschq_node->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX; mutex_lock(&pfvf->qos.qos_lock); list_add_tail(&txschq_node->list, &node->child_schq_list); @@ -469,7 +498,7 @@ static struct otx2_qos_node * otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf, struct otx2_qos_node *parent, u16 classid, u32 prio, u64 rate, u64 ceil, - u16 qid) + u32 quantum, u16 qid, bool static_cfg) { struct otx2_qos_node *node; int err; @@ -486,7 +515,10 @@ otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf, node->rate = otx2_convert_rate(rate); node->ceil = otx2_convert_rate(ceil); node->prio = prio; - node->is_static = true; + node->quantum = quantum; + node->is_static = static_cfg; + node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO; + node->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX; __set_bit(qid, pfvf->qos.qos_sq_bmap); @@ -633,6 +665,7 @@ static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf, } pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl; + pfvf->hw.txschq_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio; out: mutex_unlock(&mbox->lock); @@ -1006,6 +1039,13 @@ static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defc goto free_root_node; } + /* Update TL1 RR PRIO */ + if (root->level == NIX_TXSCH_LVL_TL1) { + root->child_dwrr_prio = pfvf->hw.txschq_aggr_lvl_rr_prio; + netdev_dbg(pfvf->netdev, + "TL1 DWRR Priority %d\n", root->child_dwrr_prio); + } + if (!(pfvf->netdev->flags & IFF_UP) || root->level == NIX_TXSCH_LVL_TL1) { root->schq = new_cfg->schq_list[root->level][0]; @@ -1052,37 +1092,126 @@ static int otx2_qos_root_destroy(struct otx2_nic *pfvf) return 0; } +static int otx2_qos_validate_quantum(struct otx2_nic *pfvf, u32 quantum) +{ + u32 rr_weight = otx2_qos_quantum_to_dwrr_weight(pfvf, quantum); + int err = 0; + + /* Max Round robin weight supported by octeontx2 and CN10K + * is different. Validate accordingly + */ + if (is_dev_otx2(pfvf->pdev)) + err = (rr_weight > OTX2_MAX_RR_QUANTUM) ? -EINVAL : 0; + else if (rr_weight > CN10K_MAX_RR_WEIGHT) + err = -EINVAL; + + return err; +} + +static int otx2_qos_validate_dwrr_cfg(struct otx2_qos_node *parent, + struct netlink_ext_ack *extack, + struct otx2_nic *pfvf, + u64 prio, u64 quantum) +{ + int err; + + err = otx2_qos_validate_quantum(pfvf, quantum); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported quantum value"); + return err; + } + + if (parent->child_dwrr_prio == OTX2_QOS_DEFAULT_PRIO) { + parent->child_dwrr_prio = prio; + } else if (prio != parent->child_dwrr_prio) { + NL_SET_ERR_MSG_MOD(extack, "Only one DWRR group is allowed"); + return -EOPNOTSUPP; + } + + return 0; +} + static int otx2_qos_validate_configuration(struct otx2_qos_node *parent, struct netlink_ext_ack *extack, struct otx2_nic *pfvf, - u64 prio) + u64 prio, bool static_cfg) { - if (test_bit(prio, parent->prio_bmap)) { - NL_SET_ERR_MSG_MOD(extack, - "Static priority child with same priority exists"); + if (prio == parent->child_dwrr_prio && static_cfg) { + NL_SET_ERR_MSG_MOD(extack, "DWRR child group with same priority exists"); return -EEXIST; } - if (prio == TXSCH_TL1_DFLT_RR_PRIO) { + if (static_cfg && test_bit(prio, parent->prio_bmap)) { NL_SET_ERR_MSG_MOD(extack, - "Priority is reserved for Round Robin"); - return -EINVAL; + "Static priority child with same priority exists"); + return -EEXIST; } return 0; } +static void otx2_reset_dwrr_prio(struct otx2_qos_node *parent, u64 prio) +{ + /* For PF, root node dwrr priority is static */ + if (parent->level == NIX_TXSCH_LVL_TL1) + return; + + if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO) { + parent->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO; + clear_bit(prio, parent->prio_bmap); + } +} + +static bool is_qos_node_dwrr(struct otx2_qos_node *parent, + struct otx2_nic *pfvf, + u64 prio) +{ + struct otx2_qos_node *node; + bool ret = false; + + if (parent->child_dwrr_prio == prio) + return true; + + mutex_lock(&pfvf->qos.qos_lock); + list_for_each_entry(node, &parent->child_list, list) { + if (prio == node->prio) { + if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO && + parent->child_dwrr_prio != prio) + continue; + + if (otx2_qos_validate_quantum(pfvf, node->quantum)) { + netdev_err(pfvf->netdev, + "Unsupported quantum value for existing classid=0x%x quantum=%d prio=%d", + node->classid, node->quantum, + node->prio); + break; + } + /* mark old node as dwrr */ + node->is_static = false; + parent->child_dwrr_cnt++; + parent->child_static_cnt--; + ret = true; + break; + } + } + mutex_unlock(&pfvf->qos.qos_lock); + + return ret; +} + static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, u32 parent_classid, u64 rate, u64 ceil, - u64 prio, struct netlink_ext_ack *extack) + u64 prio, u32 quantum, + struct netlink_ext_ack *extack) { struct otx2_qos_cfg *old_cfg, *new_cfg; struct otx2_qos_node *node, *parent; int qid, ret, err; + bool static_cfg; netdev_dbg(pfvf->netdev, - "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld\n", - classid, parent_classid, rate, ceil, prio); + "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld quantum=%d\n", + classid, parent_classid, rate, ceil, prio, quantum); if (prio > OTX2_QOS_MAX_PRIO) { NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7"); @@ -1090,6 +1219,12 @@ static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, goto out; } + if (!quantum || quantum > INT_MAX) { + NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes"); + ret = -EOPNOTSUPP; + goto out; + } + /* get parent node */ parent = otx2_sw_node_find(pfvf, parent_classid); if (!parent) { @@ -1103,11 +1238,24 @@ static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, goto out; } - ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio); + static_cfg = !is_qos_node_dwrr(parent, pfvf, prio); + ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio, + static_cfg); if (ret) goto out; - parent->child_static_cnt++; + if (!static_cfg) { + ret = otx2_qos_validate_dwrr_cfg(parent, extack, pfvf, prio, + quantum); + if (ret) + goto out; + } + + if (static_cfg) + parent->child_static_cnt++; + else + parent->child_dwrr_cnt++; + set_bit(prio, parent->prio_bmap); /* read current txschq configuration */ @@ -1132,7 +1280,7 @@ static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, /* allocate and initialize a new child node */ node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate, - ceil, qid); + ceil, quantum, qid, static_cfg); if (IS_ERR(node)) { NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node"); ret = PTR_ERR(node); @@ -1180,7 +1328,11 @@ free_node: free_old_cfg: kfree(old_cfg); reset_prio: - parent->child_static_cnt--; + if (static_cfg) + parent->child_static_cnt--; + else + parent->child_dwrr_cnt--; + clear_bit(prio, parent->prio_bmap); out: return ret; @@ -1188,10 +1340,11 @@ out: static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, u16 child_classid, u64 rate, u64 ceil, u64 prio, - struct netlink_ext_ack *extack) + u32 quantum, struct netlink_ext_ack *extack) { struct otx2_qos_cfg *old_cfg, *new_cfg; struct otx2_qos_node *node, *child; + bool static_cfg; int ret, err; u16 qid; @@ -1205,6 +1358,12 @@ static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, goto out; } + if (!quantum || quantum > INT_MAX) { + NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes"); + ret = -EOPNOTSUPP; + goto out; + } + /* find node related to classid */ node = otx2_sw_node_find(pfvf, classid); if (!node) { @@ -1219,7 +1378,19 @@ static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, goto out; } - node->child_static_cnt++; + static_cfg = !is_qos_node_dwrr(node, pfvf, prio); + if (!static_cfg) { + ret = otx2_qos_validate_dwrr_cfg(node, extack, pfvf, prio, + quantum); + if (ret) + goto out; + } + + if (static_cfg) + node->child_static_cnt++; + else + node->child_dwrr_cnt++; + set_bit(prio, node->prio_bmap); /* store the qid to assign to leaf node */ @@ -1242,7 +1413,8 @@ static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, /* allocate and initialize a new child node */ child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid, - prio, rate, ceil, qid); + prio, rate, ceil, quantum, + qid, static_cfg); if (IS_ERR(child)) { NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node"); ret = PTR_ERR(child); @@ -1293,7 +1465,10 @@ free_node: free_old_cfg: kfree(old_cfg); reset_prio: - node->child_static_cnt--; + if (static_cfg) + node->child_static_cnt--; + else + node->child_dwrr_cnt--; clear_bit(prio, node->prio_bmap); out: return ret; @@ -1303,6 +1478,7 @@ static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid, struct netlink_ext_ack *extack) { struct otx2_qos_node *node, *parent; + int dwrr_del_node = false; u64 prio; u16 qid; @@ -1318,17 +1494,28 @@ static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid, prio = node->prio; qid = node->qid; + if (!node->is_static) + dwrr_del_node = true; + otx2_qos_disable_sq(pfvf, node->qid); otx2_qos_destroy_node(pfvf, node); pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; - parent->child_static_cnt--; + if (dwrr_del_node) { + parent->child_dwrr_cnt--; + } else { + parent->child_static_cnt--; + clear_bit(prio, parent->prio_bmap); + } + + /* Reset DWRR priority if all dwrr nodes are deleted */ + if (!parent->child_dwrr_cnt) + otx2_reset_dwrr_prio(parent, prio); + if (!parent->child_static_cnt) parent->max_static_prio = 0; - clear_bit(prio, parent->prio_bmap); - return 0; } @@ -1337,6 +1524,7 @@ static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force { struct otx2_qos_node *node, *parent; struct otx2_qos_cfg *new_cfg; + int dwrr_del_node = false; u64 prio; int err; u16 qid; @@ -1361,16 +1549,27 @@ static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force return -ENOENT; } + if (!node->is_static) + dwrr_del_node = true; + /* destroy the leaf node */ otx2_qos_destroy_node(pfvf, node); pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; - parent->child_static_cnt--; + if (dwrr_del_node) { + parent->child_dwrr_cnt--; + } else { + parent->child_static_cnt--; + clear_bit(prio, parent->prio_bmap); + } + + /* Reset DWRR priority if all dwrr nodes are deleted */ + if (!parent->child_dwrr_cnt) + otx2_reset_dwrr_prio(parent, prio); + if (!parent->child_static_cnt) parent->max_static_prio = 0; - clear_bit(prio, parent->prio_bmap); - /* create downstream txschq entries to parent */ err = otx2_qos_alloc_txschq_node(pfvf, parent); if (err) { @@ -1422,10 +1621,12 @@ void otx2_qos_config_txschq(struct otx2_nic *pfvf) if (!root) return; - err = otx2_qos_txschq_config(pfvf, root); - if (err) { - netdev_err(pfvf->netdev, "Error update txschq configuration\n"); - goto root_destroy; + if (root->level != NIX_TXSCH_LVL_TL1) { + err = otx2_qos_txschq_config(pfvf, root); + if (err) { + netdev_err(pfvf->netdev, "Error update txschq configuration\n"); + goto root_destroy; + } } err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL); @@ -1458,7 +1659,8 @@ int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb) res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid, htb->parent_classid, htb->rate, htb->ceil, - htb->prio, htb->extack); + htb->prio, htb->quantum, + htb->extack); if (res < 0) return res; htb->qid = res; @@ -1467,7 +1669,7 @@ int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb) return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid, htb->classid, htb->rate, htb->ceil, htb->prio, - htb->extack); + htb->quantum, htb->extack); case TC_HTB_LEAF_DEL: return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack); case TC_HTB_LEAF_DEL_LAST: diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h index faa7c24675d1..221bd0438f60 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h @@ -60,12 +60,15 @@ struct otx2_qos_node { u64 ceil; u32 classid; u32 prio; - u16 schq; /* hw txschq */ + u32 quantum; + /* hw txschq */ + u16 schq; u16 qid; u16 prio_anchor; u16 max_static_prio; u16 child_dwrr_cnt; u16 child_static_cnt; + u16 child_dwrr_prio; u16 txschq_idx; /* txschq allocation index */ u8 level; bool is_static; -- cgit From b03f68ba26c85671c6734b14ea37a5955b0fb8d3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Jul 2023 18:04:06 -0700 Subject: eth: tsnep: let page recycling happen with skbs tsnep builds an skb with napi_build_skb() and then calls page_pool_release_page() for the page in which that skb's head sits. Use recycling instead, recycling of heads works just fine. Reviewed-by: Yunsheng Lin Link: https://lore.kernel.org/r/20230720010409.1967072-2-kuba@kernel.org Reviewed-by: Alexander Lobakin Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/engleder/tsnep_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c index 84751bb303a6..079f9f6ae21a 100644 --- a/drivers/net/ethernet/engleder/tsnep_main.c +++ b/drivers/net/ethernet/engleder/tsnep_main.c @@ -1333,7 +1333,7 @@ static void tsnep_rx_page(struct tsnep_rx *rx, struct napi_struct *napi, skb = tsnep_build_skb(rx, page, length); if (skb) { - page_pool_release_page(rx->page_pool, page); + skb_mark_for_recycle(skb); rx->packets++; rx->bytes += length; -- cgit From 98e2727c79d007d99a026eb66f481908e66af263 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Jul 2023 18:04:07 -0700 Subject: eth: stmmac: let page recycling happen with skbs stmmac removes pages from the page pool after attaching them to skbs. Use page recycling instead. skb heads are always copied, and pages are always from page pool in this driver. We could as well mark all allocated skbs for recycling. Reviewed-by: Yunsheng Lin Link: https://lore.kernel.org/r/20230720010409.1967072-3-kuba@kernel.org Reviewed-by: Alexander Lobakin Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e7ca52f0d2f2..e1f1c034d325 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -5441,7 +5441,7 @@ read_again: priv->dma_conf.dma_buf_sz); /* Data payload appended into SKB */ - page_pool_release_page(rx_q->page_pool, buf->page); + skb_mark_for_recycle(skb); buf->page = NULL; } @@ -5453,7 +5453,7 @@ read_again: priv->dma_conf.dma_buf_sz); /* Data payload appended into SKB */ - page_pool_release_page(rx_q->page_pool, buf->sec_page); + skb_mark_for_recycle(skb); buf->sec_page = NULL; } -- cgit From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 From: Samin Guo Date: Thu, 20 Jul 2023 19:15:09 +0800 Subject: net: phy: motorcomm: Add pad drive strength cfg support The motorcomm phy (YT8531) supports the ability to adjust the drive strength of the rx_clk/rx_data, and the default strength may not be suitable for all boards. So add configurable options to better match the boards.(e.g. StarFive VisionFive 2) When we configure the drive strength, we need to read the current LDO voltage value to ensure that it is a legal value at that LDO voltage. Reviewed-by: Hal Feng Signed-off-by: Samin Guo Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 2fa5a90e073b..7a11fdb687cc 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -163,6 +163,10 @@ #define YT8521_CHIP_CONFIG_REG 0xA001 #define YT8521_CCR_SW_RST BIT(15) +#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) +#define YT8531_LDO_VOL_3V3 0x0 +#define YT8531_LDO_VOL_1V8 0x2 + /* 1b0 disable 1.9ns rxc clock delay *default* * 1b1 enable 1.9ns rxc clock delay */ @@ -236,6 +240,12 @@ */ #define YTPHY_WCR_TYPE_PULSE BIT(0) +#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 +#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) +#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ +#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ +#define YT8531_RGMII_RX_DS_DEFAULT 0x3 + #define YTPHY_SYNCE_CFG_REG 0xA012 #define YT8521_SCR_SYNCE_ENABLE BIT(5) /* 1b0 output 25m clock @@ -834,6 +844,110 @@ static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) return ret; } +/** + * struct ytphy_ldo_vol_map - map a current value to a register value + * @vol: ldo voltage + * @ds: value in the register + * @cur: value in device configuration + */ +struct ytphy_ldo_vol_map { + u32 vol; + u32 ds; + u32 cur; +}; + +static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { + {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, + {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, + {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, +}; + +static u32 yt8531_get_ldo_vol(struct phy_device *phydev) +{ + u32 val; + + val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); + val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); + + return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; +} + +static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) +{ + u32 vol; + int i; + + vol = yt8531_get_ldo_vol(phydev); + for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { + if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) + return yt8531_ldo_vol[i].ds; + } + + return -EINVAL; +} + +static int yt8531_set_ds(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + u32 ds_field_low, ds_field_hi, val; + int ret, ds; + + /* set rgmii rx clk driver strength */ + if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { + ds = yt8531_get_ds_map(phydev, val); + if (ds < 0) + return dev_err_probe(&phydev->mdio.dev, ds, + "No matching current value was found.\n"); + } else { + ds = YT8531_RGMII_RX_DS_DEFAULT; + } + + ret = ytphy_modify_ext_with_lock(phydev, + YTPHY_PAD_DRIVE_STRENGTH_REG, + YT8531_RGMII_RXC_DS_MASK, + FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); + if (ret < 0) + return ret; + + /* set rgmii rx data driver strength */ + if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { + ds = yt8531_get_ds_map(phydev, val); + if (ds < 0) + return dev_err_probe(&phydev->mdio.dev, ds, + "No matching current value was found.\n"); + } else { + ds = YT8531_RGMII_RX_DS_DEFAULT; + } + + ds_field_hi = FIELD_GET(BIT(2), ds); + ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); + + ds_field_low = FIELD_GET(GENMASK(1, 0), ds); + ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); + + ret = ytphy_modify_ext_with_lock(phydev, + YTPHY_PAD_DRIVE_STRENGTH_REG, + YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, + ds_field_low | ds_field_hi); + if (ret < 0) + return ret; + + return 0; +} + /** * yt8521_probe() - read chip config then set suitable polling_mode * @phydev: a pointer to a &struct phy_device @@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy_device *phydev) return ret; } + ret = yt8531_set_ds(phydev); + if (ret < 0) + return ret; + return 0; } -- cgit From 87d7a9f3734fb314a15b579137cd9d69892b36aa Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 20 Jul 2023 12:08:13 -0700 Subject: ionic: extract common bits from ionic_remove Pull out a chunk of code from ionic_remove() that will be common in teardown paths. Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- .../net/ethernet/pensando/ionic/ionic_bus_pci.c | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index ab7d217b98b3..2bc3cab3967d 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -213,6 +213,13 @@ out: return ret; } +static void ionic_clear_pci(struct ionic *ionic) +{ + ionic_unmap_bars(ionic); + pci_release_regions(ionic->pdev); + pci_disable_device(ionic->pdev); +} + static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; @@ -249,20 +256,20 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_request_regions(pdev, IONIC_DRV_NAME); if (err) { dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err); - goto err_out_pci_disable_device; + goto err_out_clear_pci; } pcie_print_link_status(pdev); err = ionic_map_bars(ionic); if (err) - goto err_out_pci_release_regions; + goto err_out_clear_pci; /* Configure the device */ err = ionic_setup(ionic); if (err) { dev_err(dev, "Cannot setup device: %d, aborting\n", err); - goto err_out_unmap_bars; + goto err_out_clear_pci; } pci_set_master(pdev); @@ -353,12 +360,8 @@ err_out_reset: ionic_reset(ionic); err_out_teardown: ionic_dev_teardown(ionic); -err_out_unmap_bars: - ionic_unmap_bars(ionic); -err_out_pci_release_regions: - pci_release_regions(pdev); -err_out_pci_disable_device: - pci_disable_device(pdev); +err_out_clear_pci: + ionic_clear_pci(ionic); err_out_debugfs_del_dev: ionic_debugfs_del_dev(ionic); err_out_clear_drvdata: @@ -386,9 +389,7 @@ static void ionic_remove(struct pci_dev *pdev) ionic_port_reset(ionic); ionic_reset(ionic); ionic_dev_teardown(ionic); - ionic_unmap_bars(ionic); - pci_release_regions(pdev); - pci_disable_device(pdev); + ionic_clear_pci(ionic); ionic_debugfs_del_dev(ionic); mutex_destroy(&ionic->dev_cmd_lock); ionic_devlink_free(ionic); -- cgit From 0de38d9f1dba2336f84799824af08263fc407dd1 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 20 Jul 2023 12:08:14 -0700 Subject: ionic: extract common bits from ionic_probe Pull out some chunks of code from ionic_probe() that will be common in rebuild paths. Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- .../net/ethernet/pensando/ionic/ionic_bus_pci.c | 84 +++++++++++++--------- 1 file changed, 49 insertions(+), 35 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index 2bc3cab3967d..bcce613449c2 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -220,30 +220,12 @@ static void ionic_clear_pci(struct ionic *ionic) pci_disable_device(ionic->pdev); } -static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int ionic_setup_one(struct ionic *ionic) { - struct device *dev = &pdev->dev; - struct ionic *ionic; - int num_vfs; + struct pci_dev *pdev = ionic->pdev; + struct device *dev = ionic->dev; int err; - ionic = ionic_devlink_alloc(dev); - if (!ionic) - return -ENOMEM; - - ionic->pdev = pdev; - ionic->dev = dev; - pci_set_drvdata(pdev, ionic); - mutex_init(&ionic->dev_cmd_lock); - - /* Query system for DMA addressing limitation for the device. */ - err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(IONIC_ADDR_LEN)); - if (err) { - dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n", - err); - goto err_out_clear_drvdata; - } - ionic_debugfs_add_dev(ionic); /* Setup PCI device */ @@ -258,7 +240,6 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err); goto err_out_clear_pci; } - pcie_print_link_status(pdev); err = ionic_map_bars(ionic); @@ -286,24 +267,64 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_teardown; } - /* Configure the ports */ + /* Configure the port */ err = ionic_port_identify(ionic); if (err) { dev_err(dev, "Cannot identify port: %d, aborting\n", err); - goto err_out_reset; + goto err_out_teardown; } err = ionic_port_init(ionic); if (err) { dev_err(dev, "Cannot init port: %d, aborting\n", err); - goto err_out_reset; + goto err_out_teardown; + } + + return 0; + +err_out_teardown: + ionic_dev_teardown(ionic); +err_out_clear_pci: + ionic_clear_pci(ionic); +err_out_debugfs_del_dev: + ionic_debugfs_del_dev(ionic); + + return err; +} + +static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct device *dev = &pdev->dev; + struct ionic *ionic; + int num_vfs; + int err; + + ionic = ionic_devlink_alloc(dev); + if (!ionic) + return -ENOMEM; + + ionic->pdev = pdev; + ionic->dev = dev; + pci_set_drvdata(pdev, ionic); + mutex_init(&ionic->dev_cmd_lock); + + /* Query system for DMA addressing limitation for the device. */ + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(IONIC_ADDR_LEN)); + if (err) { + dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n", + err); + goto err_out; } + err = ionic_setup_one(ionic); + if (err) + goto err_out; + /* Allocate and init the LIF */ err = ionic_lif_size(ionic); if (err) { dev_err(dev, "Cannot size LIF: %d, aborting\n", err); - goto err_out_port_reset; + goto err_out_pci; } err = ionic_lif_alloc(ionic); @@ -354,17 +375,10 @@ err_out_free_lifs: ionic->lif = NULL; err_out_free_irqs: ionic_bus_free_irq_vectors(ionic); -err_out_port_reset: - ionic_port_reset(ionic); -err_out_reset: - ionic_reset(ionic); -err_out_teardown: +err_out_pci: ionic_dev_teardown(ionic); -err_out_clear_pci: ionic_clear_pci(ionic); -err_out_debugfs_del_dev: - ionic_debugfs_del_dev(ionic); -err_out_clear_drvdata: +err_out: mutex_destroy(&ionic->dev_cmd_lock); ionic_devlink_free(ionic); -- cgit From 30d2e073964dbc7b7e1e8ded12924a8f0cc5cedf Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 20 Jul 2023 12:08:15 -0700 Subject: ionic: pull out common bits from fw_up Pull out some code from ionic_lif_handle_fw_up() that can be used in the coming FLR recovery patch. Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- drivers/net/ethernet/pensando/ionic/ionic_lif.c | 64 ++++++++++++++++--------- 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 612b0015dc43..2d03c1b995bc 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -3266,27 +3266,11 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif) dev_info(ionic->dev, "FW Down: LIFs stopped\n"); } -static void ionic_lif_handle_fw_up(struct ionic_lif *lif) +static int ionic_restart_lif(struct ionic_lif *lif) { struct ionic *ionic = lif->ionic; int err; - if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) - return; - - dev_info(ionic->dev, "FW Up: restarting LIFs\n"); - - ionic_init_devinfo(ionic); - err = ionic_identify(ionic); - if (err) - goto err_out; - err = ionic_port_identify(ionic); - if (err) - goto err_out; - err = ionic_port_init(ionic); - if (err) - goto err_out; - mutex_lock(&lif->queue_lock); if (test_and_clear_bit(IONIC_LIF_F_BROKEN, lif->state)) @@ -3322,12 +3306,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) clear_bit(IONIC_LIF_F_FW_RESET, lif->state); ionic_link_status_check_request(lif, CAN_SLEEP); netif_device_attach(lif->netdev); - dev_info(ionic->dev, "FW Up: LIFs restarted\n"); - - /* restore the hardware timestamping queues */ - ionic_lif_hwstamp_replay(lif); - return; + return 0; err_txrx_free: ionic_txrx_free(lif); @@ -3337,6 +3317,46 @@ err_qcqs_free: ionic_qcqs_free(lif); err_unlock: mutex_unlock(&lif->queue_lock); + + return err; +} + +static void ionic_lif_handle_fw_up(struct ionic_lif *lif) +{ + struct ionic *ionic = lif->ionic; + int err; + + if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return; + + dev_info(ionic->dev, "FW Up: restarting LIFs\n"); + + /* This is a little different from what happens at + * probe time because the LIF already exists so we + * just need to reanimate it. + */ + ionic_init_devinfo(ionic); + err = ionic_identify(ionic); + if (err) + goto err_out; + err = ionic_port_identify(ionic); + if (err) + goto err_out; + err = ionic_port_init(ionic); + if (err) + goto err_out; + + err = ionic_restart_lif(lif); + if (err) + goto err_out; + + dev_info(ionic->dev, "FW Up: LIFs restarted\n"); + + /* restore the hardware timestamping queues */ + ionic_lif_hwstamp_replay(lif); + + return; + err_out: dev_err(ionic->dev, "FW Up: LIFs restart failed - err %d\n", err); } -- cgit From a79b559e99bea6e3284366265d1c63b28ff0ca2e Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 20 Jul 2023 12:08:16 -0700 Subject: ionic: add FLR recovery support Add support for the PCI reset handlers in order to manage an FLR event. Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- .../net/ethernet/pensando/ionic/ionic_bus_pci.c | 53 ++++++++++++++++++++++ drivers/net/ethernet/pensando/ionic/ionic_lif.c | 8 ++-- drivers/net/ethernet/pensando/ionic/ionic_lif.h | 5 ++ 3 files changed, 62 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index bcce613449c2..d6ce113a4210 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -409,12 +409,65 @@ static void ionic_remove(struct pci_dev *pdev) ionic_devlink_free(ionic); } +static void ionic_reset_prepare(struct pci_dev *pdev) +{ + struct ionic *ionic = pci_get_drvdata(pdev); + struct ionic_lif *lif = ionic->lif; + + dev_dbg(ionic->dev, "%s: device stopping\n", __func__); + + del_timer_sync(&ionic->watchdog_timer); + cancel_work_sync(&lif->deferred.work); + + mutex_lock(&lif->queue_lock); + ionic_stop_queues_reconfig(lif); + ionic_txrx_free(lif); + ionic_lif_deinit(lif); + ionic_qcqs_free(lif); + mutex_unlock(&lif->queue_lock); + + ionic_dev_teardown(ionic); + ionic_clear_pci(ionic); + ionic_debugfs_del_dev(ionic); +} + +static void ionic_reset_done(struct pci_dev *pdev) +{ + struct ionic *ionic = pci_get_drvdata(pdev); + struct ionic_lif *lif = ionic->lif; + int err; + + err = ionic_setup_one(ionic); + if (err) + goto err_out; + + ionic_debugfs_add_sizes(ionic); + ionic_debugfs_add_lif(ionic->lif); + + err = ionic_restart_lif(lif); + if (err) + goto err_out; + + mod_timer(&ionic->watchdog_timer, jiffies + 1); + +err_out: + dev_dbg(ionic->dev, "%s: device recovery %s\n", + __func__, err ? "failed" : "done"); +} + +static const struct pci_error_handlers ionic_err_handler = { + /* FLR handling */ + .reset_prepare = ionic_reset_prepare, + .reset_done = ionic_reset_done, +}; + static struct pci_driver ionic_driver = { .name = IONIC_DRV_NAME, .id_table = ionic_id_table, .probe = ionic_probe, .remove = ionic_remove, .sriov_configure = ionic_sriov_configure, + .err_handler = &ionic_err_handler }; int ionic_bus_register_driver(void) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 2d03c1b995bc..adc05f944c14 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -434,7 +434,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) } } -static void ionic_qcqs_free(struct ionic_lif *lif) +void ionic_qcqs_free(struct ionic_lif *lif) { struct device *dev = lif->ionic->dev; struct ionic_qcq *adminqcq; @@ -1754,7 +1754,7 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) return ionic_lif_addr_add(netdev_priv(netdev), mac); } -static void ionic_stop_queues_reconfig(struct ionic_lif *lif) +void ionic_stop_queues_reconfig(struct ionic_lif *lif) { /* Stop and clean the queues before reconfiguration */ netif_device_detach(lif->netdev); @@ -2009,7 +2009,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif) } } -static void ionic_txrx_free(struct ionic_lif *lif) +void ionic_txrx_free(struct ionic_lif *lif) { unsigned int i; @@ -3266,7 +3266,7 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif) dev_info(ionic->dev, "FW Down: LIFs stopped\n"); } -static int ionic_restart_lif(struct ionic_lif *lif) +int ionic_restart_lif(struct ionic_lif *lif) { struct ionic *ionic = lif->ionic; int err; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index fd2ea670e7d8..457c24195ca6 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -325,6 +325,11 @@ void ionic_lif_deinit(struct ionic_lif *lif); int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr); int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr); +void ionic_stop_queues_reconfig(struct ionic_lif *lif); +void ionic_txrx_free(struct ionic_lif *lif); +void ionic_qcqs_free(struct ionic_lif *lif); +int ionic_restart_lif(struct ionic_lif *lif); + int ionic_lif_register(struct ionic_lif *lif); void ionic_lif_unregister(struct ionic_lif *lif); int ionic_lif_identify(struct ionic *ionic, u8 lif_type, -- cgit From ee95d4420a2f4f02a2bf2b9ff0086ddc31965187 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:26 +0200 Subject: ice: Skip adv rules removal upon switchdev release Advanced rules for ctrl VSI will be removed anyway when the VSI will cleaned up, no need to do it explicitly. Reviewed-by: Paul Menzel Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 1 - drivers/net/ethernet/intel/ice/ice_switch.c | 53 ---------------------------- drivers/net/ethernet/intel/ice/ice_switch.h | 1 - 3 files changed, 55 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index ad0a007b7398..be5b22691f7c 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -503,7 +503,6 @@ static void ice_eswitch_disable_switchdev(struct ice_pf *pf) ice_eswitch_napi_disable(pf); ice_eswitch_release_env(pf); - ice_rem_adv_rule_for_vsi(&pf->hw, ctrl_vsi->idx); ice_eswitch_release_reprs(pf, ctrl_vsi); ice_vsi_release(ctrl_vsi); ice_repr_rem_from_all_vfs(pf); diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 6db4ca7978cb..81f45d7e76de 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -6532,59 +6532,6 @@ ice_rem_adv_rule_by_id(struct ice_hw *hw, return -ENOENT; } -/** - * ice_rem_adv_rule_for_vsi - removes existing advanced switch rules for a - * given VSI handle - * @hw: pointer to the hardware structure - * @vsi_handle: VSI handle for which we are supposed to remove all the rules. - * - * This function is used to remove all the rules for a given VSI and as soon - * as removing a rule fails, it will return immediately with the error code, - * else it will return success. - */ -int ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle) -{ - struct ice_adv_fltr_mgmt_list_entry *list_itr, *tmp_entry; - struct ice_vsi_list_map_info *map_info; - struct ice_adv_rule_info rinfo; - struct list_head *list_head; - struct ice_switch_info *sw; - int status; - u8 rid; - - sw = hw->switch_info; - for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) { - if (!sw->recp_list[rid].recp_created) - continue; - if (!sw->recp_list[rid].adv_rule) - continue; - - list_head = &sw->recp_list[rid].filt_rules; - list_for_each_entry_safe(list_itr, tmp_entry, list_head, - list_entry) { - rinfo = list_itr->rule_info; - - if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) { - map_info = list_itr->vsi_list_info; - if (!map_info) - continue; - - if (!test_bit(vsi_handle, map_info->vsi_map)) - continue; - } else if (rinfo.sw_act.vsi_handle != vsi_handle) { - continue; - } - - rinfo.sw_act.vsi_handle = vsi_handle; - status = ice_rem_adv_rule(hw, list_itr->lkups, - list_itr->lkups_cnt, &rinfo); - if (status) - return status; - } - } - return 0; -} - /** * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index c84b56fe84a5..db08509805ce 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -379,7 +379,6 @@ int ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, bool rm_vlan_promisc); -int ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle); int ice_rem_adv_rule_by_id(struct ice_hw *hw, struct ice_rule_query_data *remove_entry); -- cgit From 2571a3fa6251662e5201372f889bf93f234c8261 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:27 +0200 Subject: ice: Prohibit rx mode change in switchdev mode Don't allow to change promisc mode in switchdev mode. When switchdev is configured, PF netdev is set to be a default VSI. This is needed for the slow-path to work correctly. All the unmatched packets will be directed to PF netdev. It is possible that this setting might be overwritten by ndo_set_rx_mode. Prevent this by checking if switchdev is enabled in ice_set_rx_mode. Reviewed-by: Paul Menzel Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 4f70f5553c80..d1f2077676e4 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -5704,7 +5704,7 @@ static void ice_set_rx_mode(struct net_device *netdev) struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_vsi *vsi = np->vsi; - if (!vsi) + if (!vsi || ice_is_switchdev_running(vsi->back)) return; /* Set the flags to synchronize filters -- cgit From 7aa529a69e92b9aff585e569d5003f7c15d8d60b Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:28 +0200 Subject: ice: Don't tx before switchdev is fully configured There is possibility that ice_eswitch_port_start_xmit might be called while some resources are still not allocated which might cause NULL pointer dereference. Fix this by checking if switchdev configuration was finished. Reviewed-by: Paul Menzel Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index be5b22691f7c..15a4c148c28b 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -331,6 +331,9 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev) np = netdev_priv(netdev); vsi = np->vsi; + if (!vsi || !ice_is_switchdev_running(vsi->back)) + return NETDEV_TX_BUSY; + if (ice_is_reset_in_progress(vsi->back->state) || test_bit(ICE_VF_DIS, vsi->back->state)) return NETDEV_TX_BUSY; -- cgit From 6ab1155798c356630a7ad1e4baae44eb6414f5ba Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:29 +0200 Subject: ice: Disable vlan pruning for uplink VSI In switchdev mode, uplink VSI is configured to be default VSI which means it will receive all unmatched packets. In order to receive vlan packets we need to disable vlan pruning as well. This is done by dis_rx_filtering vlan op. Reviewed-by: Paul Menzel Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index 15a4c148c28b..bfd003135fc8 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -103,6 +103,10 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) rule_added = true; } + vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi); + if (vlan_ops->dis_rx_filtering(uplink_vsi)) + goto err_dis_rx; + if (ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_set_allow_override)) goto err_override_uplink; @@ -114,6 +118,8 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) err_override_control: ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); err_override_uplink: + vlan_ops->ena_rx_filtering(uplink_vsi); +err_dis_rx: if (rule_added) ice_clear_dflt_vsi(uplink_vsi); err_def_rx: @@ -381,9 +387,13 @@ static void ice_eswitch_release_env(struct ice_pf *pf) { struct ice_vsi *uplink_vsi = pf->switchdev.uplink_vsi; struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi; + struct ice_vsi_vlan_ops *vlan_ops; + + vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi); ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override); ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); + vlan_ops->ena_rx_filtering(uplink_vsi); ice_clear_dflt_vsi(uplink_vsi); ice_fltr_add_mac_and_broadcast(uplink_vsi, uplink_vsi->port_info->mac.perm_addr, -- cgit From 6c0f4441d83b1efd311acbab266246aee6e46bea Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:30 +0200 Subject: ice: Unset src prune on uplink VSI In switchdev mode uplink VSI is supposed to receive all packets that were not matched by existing filters. If ICE_AQ_VSI_SW_FLAG_LOCAL_LB bit is unset and we have a filter associated with uplink VSI which matches on dst mac equal to MAC1, then packets with src mac equal to MAC1 will be pruned from reaching uplink VSI. Fix this by updating uplink VSI with ICE_AQ_VSI_SW_FLAG_LOCAL_LB bit set when configuring switchdev mode. Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 6 ++++++ drivers/net/ethernet/intel/ice/ice_lib.c | 25 +++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_lib.h | 1 + 3 files changed, 32 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index bfd003135fc8..4fe235da1182 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -113,8 +113,13 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) if (ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_set_allow_override)) goto err_override_control; + if (ice_vsi_update_local_lb(uplink_vsi, true)) + goto err_override_local_lb; + return 0; +err_override_local_lb: + ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override); err_override_control: ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); err_override_uplink: @@ -391,6 +396,7 @@ static void ice_eswitch_release_env(struct ice_pf *pf) vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi); + ice_vsi_update_local_lb(uplink_vsi, false); ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override); ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); vlan_ops->ena_rx_filtering(uplink_vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 0054d7e64ec3..a43c23c80565 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -4076,3 +4076,28 @@ void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx) { ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; } + +/** + * ice_vsi_update_local_lb - update sw block in VSI with local loopback bit + * @vsi: pointer to VSI structure + * @set: set or unset the bit + */ +int +ice_vsi_update_local_lb(struct ice_vsi *vsi, bool set) +{ + struct ice_vsi_ctx ctx = { + .info = vsi->info, + }; + + ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); + if (set) + ctx.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_LOCAL_LB; + else + ctx.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_LOCAL_LB; + + if (ice_update_vsi(&vsi->back->hw, vsi->idx, &ctx, NULL)) + return -ENODEV; + + vsi->info = ctx.info; + return 0; +} diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index e985766e6bb5..1628385a9672 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -157,6 +157,7 @@ void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx); void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx); void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx); +int ice_vsi_update_local_lb(struct ice_vsi *vsi, bool set); int ice_vsi_add_vlan_zero(struct ice_vsi *vsi); int ice_vsi_del_vlan_zero(struct ice_vsi *vsi); bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi); -- cgit From f6e8fb55e5af9a506d2e50d1079a231ce95ca215 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:31 +0200 Subject: ice: Implement basic eswitch bridge setup With this patch, ice driver is able to track if the port representors or uplink port were added to the linux bridge in switchdev mode. Listen for NETDEV_CHANGEUPPER events in order to detect this. ice_esw_br data structure reflects the linux bridge and stores all the ports of the bridge (ice_esw_br_port) in xarray, it's created when the first port is added to the bridge and freed once the last port is removed. Note that only one bridge is supported per eswitch. Bridge port (ice_esw_br_port) can be either a VF port representor port or uplink port (ice_esw_br_port_type). In both cases bridge port holds a reference to the VSI, VF's VSI in case of the PR and uplink VSI in case of the uplink. VSI's index is used as an index to the xarray in which ports are stored. Add a check which prevents configuring switchdev mode if uplink is already added to any bridge. This is needed because we need to listen for NETDEV_CHANGEUPPER events to record if the uplink was added to the bridge. Netdevice notifier is registered after eswitch mode is changed to switchdev. Reviewed-by: Simon Horman Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/Makefile | 2 +- drivers/net/ethernet/intel/ice/ice.h | 4 +- drivers/net/ethernet/intel/ice/ice_eswitch.c | 26 +- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 384 ++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 42 +++ drivers/net/ethernet/intel/ice/ice_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_repr.c | 2 +- drivers/net/ethernet/intel/ice/ice_repr.h | 3 +- 8 files changed, 456 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/intel/ice/ice_eswitch_br.c create mode 100644 drivers/net/ethernet/intel/ice/ice_eswitch_br.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile index 817977e3039d..960277d78e09 100644 --- a/drivers/net/ethernet/intel/ice/Makefile +++ b/drivers/net/ethernet/intel/ice/Makefile @@ -47,5 +47,5 @@ ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o -ice-$(CONFIG_ICE_SWITCHDEV) += ice_eswitch.o +ice-$(CONFIG_ICE_SWITCHDEV) += ice_eswitch.o ice_eswitch_br.o ice-$(CONFIG_GNSS) += ice_gnss.o diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 4ba3d99439a0..8918a4b836a2 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -517,6 +517,7 @@ enum ice_misc_thread_tasks { struct ice_switchdev_info { struct ice_vsi *control_vsi; struct ice_vsi *uplink_vsi; + struct ice_esw_br_offloads *br_offloads; bool is_running; }; @@ -626,6 +627,7 @@ struct ice_pf { struct ice_lag *lag; /* Link Aggregation information */ struct ice_switchdev_info switchdev; + struct ice_esw_br_port *br_port; #define ICE_INVALID_AGG_NODE_ID 0 #define ICE_PF_AGG_NODE_ID_START 1 @@ -853,7 +855,7 @@ static inline bool ice_is_adq_active(struct ice_pf *pf) return false; } -bool netif_is_ice(struct net_device *dev); +bool netif_is_ice(const struct net_device *dev); int ice_vsi_setup_tx_rings(struct ice_vsi *vsi); int ice_vsi_setup_rx_rings(struct ice_vsi *vsi); int ice_vsi_open_ctrl(struct ice_vsi *vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index 4fe235da1182..9a53a5e5d73e 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -4,6 +4,7 @@ #include "ice.h" #include "ice_lib.h" #include "ice_eswitch.h" +#include "ice_eswitch_br.h" #include "ice_fltr.h" #include "ice_repr.h" #include "ice_devlink.h" @@ -317,6 +318,9 @@ void ice_eswitch_update_repr(struct ice_vsi *vsi) repr->src_vsi = vsi; repr->dst->u.port_info.port_id = vsi->vsi_num; + if (repr->br_port) + repr->br_port->vsi = vsi; + ret = ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof); if (ret) { ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); @@ -474,16 +478,24 @@ static void ice_eswitch_napi_disable(struct ice_pf *pf) */ static int ice_eswitch_enable_switchdev(struct ice_pf *pf) { - struct ice_vsi *ctrl_vsi; + struct ice_vsi *ctrl_vsi, *uplink_vsi; + + uplink_vsi = ice_get_main_vsi(pf); + if (!uplink_vsi) + return -ENODEV; + + if (netif_is_any_bridge_port(uplink_vsi->netdev)) { + dev_err(ice_pf_to_dev(pf), + "Uplink port cannot be a bridge port\n"); + return -EINVAL; + } pf->switchdev.control_vsi = ice_eswitch_vsi_setup(pf, pf->hw.port_info); if (!pf->switchdev.control_vsi) return -ENODEV; ctrl_vsi = pf->switchdev.control_vsi; - pf->switchdev.uplink_vsi = ice_get_main_vsi(pf); - if (!pf->switchdev.uplink_vsi) - goto err_vsi; + pf->switchdev.uplink_vsi = uplink_vsi; if (ice_eswitch_setup_env(pf)) goto err_vsi; @@ -499,10 +511,15 @@ static int ice_eswitch_enable_switchdev(struct ice_pf *pf) if (ice_vsi_open(ctrl_vsi)) goto err_setup_reprs; + if (ice_eswitch_br_offloads_init(pf)) + goto err_br_offloads; + ice_eswitch_napi_enable(pf); return 0; +err_br_offloads: + ice_vsi_close(ctrl_vsi); err_setup_reprs: ice_repr_rem_from_all_vfs(pf); err_repr_add: @@ -521,6 +538,7 @@ static void ice_eswitch_disable_switchdev(struct ice_pf *pf) struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi; ice_eswitch_napi_disable(pf); + ice_eswitch_br_offloads_deinit(pf); ice_eswitch_release_env(pf); ice_eswitch_release_reprs(pf, ctrl_vsi); ice_vsi_release(ctrl_vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c new file mode 100644 index 000000000000..dbc077447ea1 --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2023, Intel Corporation. */ + +#include "ice.h" +#include "ice_eswitch_br.h" +#include "ice_repr.h" + +static bool ice_eswitch_br_is_dev_valid(const struct net_device *dev) +{ + /* Accept only PF netdev and PRs */ + return ice_is_port_repr_netdev(dev) || netif_is_ice(dev); +} + +static struct ice_esw_br_port * +ice_eswitch_br_netdev_to_port(struct net_device *dev) +{ + if (ice_is_port_repr_netdev(dev)) { + struct ice_repr *repr = ice_netdev_to_repr(dev); + + return repr->br_port; + } else if (netif_is_ice(dev)) { + struct ice_pf *pf = ice_netdev_to_pf(dev); + + return pf->br_port; + } + + return NULL; +} + +static void +ice_eswitch_br_port_deinit(struct ice_esw_br *bridge, + struct ice_esw_br_port *br_port) +{ + struct ice_vsi *vsi = br_port->vsi; + + if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back) + vsi->back->br_port = NULL; + else if (vsi->vf && vsi->vf->repr) + vsi->vf->repr->br_port = NULL; + + xa_erase(&bridge->ports, br_port->vsi_idx); + kfree(br_port); +} + +static struct ice_esw_br_port * +ice_eswitch_br_port_init(struct ice_esw_br *bridge) +{ + struct ice_esw_br_port *br_port; + + br_port = kzalloc(sizeof(*br_port), GFP_KERNEL); + if (!br_port) + return ERR_PTR(-ENOMEM); + + br_port->bridge = bridge; + + return br_port; +} + +static int +ice_eswitch_br_vf_repr_port_init(struct ice_esw_br *bridge, + struct ice_repr *repr) +{ + struct ice_esw_br_port *br_port; + int err; + + br_port = ice_eswitch_br_port_init(bridge); + if (IS_ERR(br_port)) + return PTR_ERR(br_port); + + br_port->vsi = repr->src_vsi; + br_port->vsi_idx = br_port->vsi->idx; + br_port->type = ICE_ESWITCH_BR_VF_REPR_PORT; + repr->br_port = br_port; + + err = xa_insert(&bridge->ports, br_port->vsi_idx, br_port, GFP_KERNEL); + if (err) { + ice_eswitch_br_port_deinit(bridge, br_port); + return err; + } + + return 0; +} + +static int +ice_eswitch_br_uplink_port_init(struct ice_esw_br *bridge, struct ice_pf *pf) +{ + struct ice_vsi *vsi = pf->switchdev.uplink_vsi; + struct ice_esw_br_port *br_port; + int err; + + br_port = ice_eswitch_br_port_init(bridge); + if (IS_ERR(br_port)) + return PTR_ERR(br_port); + + br_port->vsi = vsi; + br_port->vsi_idx = br_port->vsi->idx; + br_port->type = ICE_ESWITCH_BR_UPLINK_PORT; + pf->br_port = br_port; + + err = xa_insert(&bridge->ports, br_port->vsi_idx, br_port, GFP_KERNEL); + if (err) { + ice_eswitch_br_port_deinit(bridge, br_port); + return err; + } + + return 0; +} + +static void +ice_eswitch_br_ports_flush(struct ice_esw_br *bridge) +{ + struct ice_esw_br_port *port; + unsigned long i; + + xa_for_each(&bridge->ports, i, port) + ice_eswitch_br_port_deinit(bridge, port); +} + +static void +ice_eswitch_br_deinit(struct ice_esw_br_offloads *br_offloads, + struct ice_esw_br *bridge) +{ + if (!bridge) + return; + + /* Cleanup all the ports that were added asynchronously + * through NETDEV_CHANGEUPPER event. + */ + ice_eswitch_br_ports_flush(bridge); + WARN_ON(!xa_empty(&bridge->ports)); + xa_destroy(&bridge->ports); + br_offloads->bridge = NULL; + kfree(bridge); +} + +static struct ice_esw_br * +ice_eswitch_br_init(struct ice_esw_br_offloads *br_offloads, int ifindex) +{ + struct ice_esw_br *bridge; + + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return ERR_PTR(-ENOMEM); + + bridge->br_offloads = br_offloads; + bridge->ifindex = ifindex; + xa_init(&bridge->ports); + br_offloads->bridge = bridge; + + return bridge; +} + +static struct ice_esw_br * +ice_eswitch_br_get(struct ice_esw_br_offloads *br_offloads, int ifindex, + struct netlink_ext_ack *extack) +{ + struct ice_esw_br *bridge = br_offloads->bridge; + + if (bridge) { + if (bridge->ifindex != ifindex) { + NL_SET_ERR_MSG_MOD(extack, + "Only one bridge is supported per eswitch"); + return ERR_PTR(-EOPNOTSUPP); + } + return bridge; + } + + /* Create the bridge if it doesn't exist yet */ + bridge = ice_eswitch_br_init(br_offloads, ifindex); + if (IS_ERR(bridge)) + NL_SET_ERR_MSG_MOD(extack, "Failed to init the bridge"); + + return bridge; +} + +static void +ice_eswitch_br_verify_deinit(struct ice_esw_br_offloads *br_offloads, + struct ice_esw_br *bridge) +{ + /* Remove the bridge if it exists and there are no ports left */ + if (!bridge || !xa_empty(&bridge->ports)) + return; + + ice_eswitch_br_deinit(br_offloads, bridge); +} + +static int +ice_eswitch_br_port_unlink(struct ice_esw_br_offloads *br_offloads, + struct net_device *dev, int ifindex, + struct netlink_ext_ack *extack) +{ + struct ice_esw_br_port *br_port = ice_eswitch_br_netdev_to_port(dev); + struct ice_esw_br *bridge; + + if (!br_port) { + NL_SET_ERR_MSG_MOD(extack, + "Port representor is not attached to any bridge"); + return -EINVAL; + } + + if (br_port->bridge->ifindex != ifindex) { + NL_SET_ERR_MSG_MOD(extack, + "Port representor is attached to another bridge"); + return -EINVAL; + } + + bridge = br_port->bridge; + + ice_eswitch_br_port_deinit(br_port->bridge, br_port); + ice_eswitch_br_verify_deinit(br_offloads, bridge); + + return 0; +} + +static int +ice_eswitch_br_port_link(struct ice_esw_br_offloads *br_offloads, + struct net_device *dev, int ifindex, + struct netlink_ext_ack *extack) +{ + struct ice_esw_br *bridge; + int err; + + if (ice_eswitch_br_netdev_to_port(dev)) { + NL_SET_ERR_MSG_MOD(extack, + "Port is already attached to the bridge"); + return -EINVAL; + } + + bridge = ice_eswitch_br_get(br_offloads, ifindex, extack); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + + if (ice_is_port_repr_netdev(dev)) { + struct ice_repr *repr = ice_netdev_to_repr(dev); + + err = ice_eswitch_br_vf_repr_port_init(bridge, repr); + } else { + struct ice_pf *pf = ice_netdev_to_pf(dev); + + err = ice_eswitch_br_uplink_port_init(bridge, pf); + } + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to init bridge port"); + goto err_port_init; + } + + return 0; + +err_port_init: + ice_eswitch_br_verify_deinit(br_offloads, bridge); + return err; +} + +static int +ice_eswitch_br_port_changeupper(struct notifier_block *nb, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info = ptr; + struct ice_esw_br_offloads *br_offloads; + struct netlink_ext_ack *extack; + struct net_device *upper; + + br_offloads = ice_nb_to_br_offloads(nb, netdev_nb); + + if (!ice_eswitch_br_is_dev_valid(dev)) + return 0; + + upper = info->upper_dev; + if (!netif_is_bridge_master(upper)) + return 0; + + extack = netdev_notifier_info_to_extack(&info->info); + + if (info->linking) + return ice_eswitch_br_port_link(br_offloads, dev, + upper->ifindex, extack); + else + return ice_eswitch_br_port_unlink(br_offloads, dev, + upper->ifindex, extack); +} + +static int +ice_eswitch_br_port_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + int err = 0; + + switch (event) { + case NETDEV_CHANGEUPPER: + err = ice_eswitch_br_port_changeupper(nb, ptr); + break; + } + + return notifier_from_errno(err); +} + +static void +ice_eswitch_br_offloads_dealloc(struct ice_pf *pf) +{ + struct ice_esw_br_offloads *br_offloads = pf->switchdev.br_offloads; + + ASSERT_RTNL(); + + if (!br_offloads) + return; + + ice_eswitch_br_deinit(br_offloads, br_offloads->bridge); + + pf->switchdev.br_offloads = NULL; + kfree(br_offloads); +} + +static struct ice_esw_br_offloads * +ice_eswitch_br_offloads_alloc(struct ice_pf *pf) +{ + struct ice_esw_br_offloads *br_offloads; + + ASSERT_RTNL(); + + if (pf->switchdev.br_offloads) + return ERR_PTR(-EEXIST); + + br_offloads = kzalloc(sizeof(*br_offloads), GFP_KERNEL); + if (!br_offloads) + return ERR_PTR(-ENOMEM); + + pf->switchdev.br_offloads = br_offloads; + br_offloads->pf = pf; + + return br_offloads; +} + +void +ice_eswitch_br_offloads_deinit(struct ice_pf *pf) +{ + struct ice_esw_br_offloads *br_offloads; + + br_offloads = pf->switchdev.br_offloads; + if (!br_offloads) + return; + + unregister_netdevice_notifier(&br_offloads->netdev_nb); + /* Although notifier block is unregistered just before, + * so we don't get any new events, some events might be + * already in progress. Hold the rtnl lock and wait for + * them to finished. + */ + rtnl_lock(); + ice_eswitch_br_offloads_dealloc(pf); + rtnl_unlock(); +} + +int +ice_eswitch_br_offloads_init(struct ice_pf *pf) +{ + struct ice_esw_br_offloads *br_offloads; + struct device *dev = ice_pf_to_dev(pf); + int err; + + rtnl_lock(); + br_offloads = ice_eswitch_br_offloads_alloc(pf); + rtnl_unlock(); + if (IS_ERR(br_offloads)) { + dev_err(dev, "Failed to init eswitch bridge\n"); + return PTR_ERR(br_offloads); + } + + br_offloads->netdev_nb.notifier_call = ice_eswitch_br_port_event; + err = register_netdevice_notifier(&br_offloads->netdev_nb); + if (err) { + dev_err(dev, + "Failed to register bridge port event notifier\n"); + goto err_reg_netdev_nb; + } + + return 0; + +err_reg_netdev_nb: + rtnl_lock(); + ice_eswitch_br_offloads_dealloc(pf); + rtnl_unlock(); + + return err; +} diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h new file mode 100644 index 000000000000..3ad28a17298f --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2023, Intel Corporation. */ + +#ifndef _ICE_ESWITCH_BR_H_ +#define _ICE_ESWITCH_BR_H_ + +enum ice_esw_br_port_type { + ICE_ESWITCH_BR_UPLINK_PORT = 0, + ICE_ESWITCH_BR_VF_REPR_PORT = 1, +}; + +struct ice_esw_br_port { + struct ice_esw_br *bridge; + struct ice_vsi *vsi; + enum ice_esw_br_port_type type; + u16 vsi_idx; +}; + +struct ice_esw_br { + struct ice_esw_br_offloads *br_offloads; + struct xarray ports; + + int ifindex; +}; + +struct ice_esw_br_offloads { + struct ice_pf *pf; + struct ice_esw_br *bridge; + struct notifier_block netdev_nb; +}; + +#define ice_nb_to_br_offloads(nb, nb_name) \ + container_of(nb, \ + struct ice_esw_br_offloads, \ + nb_name) + +void +ice_eswitch_br_offloads_deinit(struct ice_pf *pf); +int +ice_eswitch_br_offloads_init(struct ice_pf *pf); + +#endif /* _ICE_ESWITCH_BR_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index d1f2077676e4..9b36cce306b8 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -80,7 +80,7 @@ ice_indr_setup_tc_cb(struct net_device *netdev, struct Qdisc *sch, void *data, void (*cleanup)(struct flow_block_cb *block_cb)); -bool netif_is_ice(struct net_device *dev) +bool netif_is_ice(const struct net_device *dev) { return dev && (dev->netdev_ops == &ice_netdev_ops); } diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c index e30e12321abd..c686ac0935eb 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.c +++ b/drivers/net/ethernet/intel/ice/ice_repr.c @@ -254,7 +254,7 @@ static const struct net_device_ops ice_repr_netdev_ops = { * ice_is_port_repr_netdev - Check if a given netdevice is a port representor netdev * @netdev: pointer to netdev */ -bool ice_is_port_repr_netdev(struct net_device *netdev) +bool ice_is_port_repr_netdev(const struct net_device *netdev) { return netdev && (netdev->netdev_ops == &ice_repr_netdev_ops); } diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h index 9c2a6f496b3b..e1ee2d2c1d2d 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.h +++ b/drivers/net/ethernet/intel/ice/ice_repr.h @@ -12,6 +12,7 @@ struct ice_repr { struct ice_q_vector *q_vector; struct net_device *netdev; struct metadata_dst *dst; + struct ice_esw_br_port *br_port; #ifdef CONFIG_ICE_SWITCHDEV /* info about slow path rule */ struct ice_rule_query_data sp_rule; @@ -27,5 +28,5 @@ void ice_repr_stop_tx_queues(struct ice_repr *repr); void ice_repr_set_traffic_vsi(struct ice_repr *repr, struct ice_vsi *vsi); struct ice_repr *ice_netdev_to_repr(struct net_device *netdev); -bool ice_is_port_repr_netdev(struct net_device *netdev); +bool ice_is_port_repr_netdev(const struct net_device *netdev); #endif -- cgit From 7c945a1a8e5fb84195f74813b5d24c924b694932 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Wed, 12 Jul 2023 13:03:32 +0200 Subject: ice: Switchdev FDB events support Listen for SWITCHDEV_FDB_{ADD|DEL}_TO_DEVICE events while in switchdev mode. Accept these events on both uplink and VF PR ports. Add HW rules in newly created workqueue. FDB entries are stored in rhashtable for lookup when removing the entry and in the list for cleanup purpose. Direction of the HW rule depends on the type of the ports on which the FDB event was received: ICE_ESWITCH_BR_UPLINK_PORT: TX rule that forwards the packet to the LAN (egress). ICE_ESWITCH_BR_VF_REPR_PORT: RX rule that forwards the packet to the VF associated with the port representor. In both cases the rule matches on the dst mac address. All the FDB entries are stored in the bridge structure. When the port is removed all the FDB entries associated with this port are removed as well. This is achieved thanks to the reference to the port that FDB entry holds. In the fwd rule we use only one lookup type (MAC address) but lkups_cnt variable is already introduced because we will have more lookups in the subsequent patches. Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 433 ++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 45 +++ 2 files changed, 478 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index dbc077447ea1..49b3ca5e956e 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -4,6 +4,14 @@ #include "ice.h" #include "ice_eswitch_br.h" #include "ice_repr.h" +#include "ice_switch.h" + +static const struct rhashtable_params ice_fdb_ht_params = { + .key_offset = offsetof(struct ice_esw_br_fdb_entry, data), + .key_len = sizeof(struct ice_esw_br_fdb_data), + .head_offset = offsetof(struct ice_esw_br_fdb_entry, ht_node), + .automatic_shrinking = true, +}; static bool ice_eswitch_br_is_dev_valid(const struct net_device *dev) { @@ -27,12 +35,405 @@ ice_eswitch_br_netdev_to_port(struct net_device *dev) return NULL; } +static void +ice_eswitch_br_ingress_rule_setup(struct ice_adv_rule_info *rule_info, + u8 pf_id, u16 vf_vsi_idx) +{ + rule_info->sw_act.vsi_handle = vf_vsi_idx; + rule_info->sw_act.flag |= ICE_FLTR_RX; + rule_info->sw_act.src = pf_id; + rule_info->priority = 5; +} + +static void +ice_eswitch_br_egress_rule_setup(struct ice_adv_rule_info *rule_info, + u16 pf_vsi_idx) +{ + rule_info->sw_act.vsi_handle = pf_vsi_idx; + rule_info->sw_act.flag |= ICE_FLTR_TX; + rule_info->flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE; + rule_info->flags_info.act_valid = true; + rule_info->priority = 5; +} + +static int +ice_eswitch_br_rule_delete(struct ice_hw *hw, struct ice_rule_query_data *rule) +{ + int err; + + if (!rule) + return -EINVAL; + + err = ice_rem_adv_rule_by_id(hw, rule); + kfree(rule); + + return err; +} + +static struct ice_rule_query_data * +ice_eswitch_br_fwd_rule_create(struct ice_hw *hw, int vsi_idx, int port_type, + const unsigned char *mac) +{ + struct ice_adv_rule_info rule_info = { 0 }; + struct ice_rule_query_data *rule; + struct ice_adv_lkup_elem *list; + u16 lkups_cnt = 1; + int err; + + rule = kzalloc(sizeof(*rule), GFP_KERNEL); + if (!rule) + return ERR_PTR(-ENOMEM); + + list = kcalloc(lkups_cnt, sizeof(*list), GFP_ATOMIC); + if (!list) { + err = -ENOMEM; + goto err_list_alloc; + } + + switch (port_type) { + case ICE_ESWITCH_BR_UPLINK_PORT: + ice_eswitch_br_egress_rule_setup(&rule_info, vsi_idx); + break; + case ICE_ESWITCH_BR_VF_REPR_PORT: + ice_eswitch_br_ingress_rule_setup(&rule_info, hw->pf_id, + vsi_idx); + break; + default: + err = -EINVAL; + goto err_add_rule; + } + + list[0].type = ICE_MAC_OFOS; + ether_addr_copy(list[0].h_u.eth_hdr.dst_addr, mac); + eth_broadcast_addr(list[0].m_u.eth_hdr.dst_addr); + + rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; + + err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, rule); + if (err) + goto err_add_rule; + + kfree(list); + + return rule; + +err_add_rule: + kfree(list); +err_list_alloc: + kfree(rule); + + return ERR_PTR(err); +} + +static struct ice_esw_br_flow * +ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, + int port_type, const unsigned char *mac) +{ + struct ice_rule_query_data *fwd_rule; + struct ice_esw_br_flow *flow; + int err; + + flow = kzalloc(sizeof(*flow), GFP_KERNEL); + if (!flow) + return ERR_PTR(-ENOMEM); + + fwd_rule = ice_eswitch_br_fwd_rule_create(hw, vsi_idx, port_type, mac); + err = PTR_ERR_OR_ZERO(fwd_rule); + if (err) { + dev_err(dev, "Failed to create eswitch bridge %sgress forward rule, err: %d\n", + port_type == ICE_ESWITCH_BR_UPLINK_PORT ? "e" : "in", + err); + goto err_fwd_rule; + } + + flow->fwd_rule = fwd_rule; + + return flow; + +err_fwd_rule: + kfree(flow); + + return ERR_PTR(err); +} + +static struct ice_esw_br_fdb_entry * +ice_eswitch_br_fdb_find(struct ice_esw_br *bridge, const unsigned char *mac, + u16 vid) +{ + struct ice_esw_br_fdb_data data = { + .vid = vid, + }; + + ether_addr_copy(data.addr, mac); + return rhashtable_lookup_fast(&bridge->fdb_ht, &data, + ice_fdb_ht_params); +} + +static void +ice_eswitch_br_flow_delete(struct ice_pf *pf, struct ice_esw_br_flow *flow) +{ + struct device *dev = ice_pf_to_dev(pf); + int err; + + err = ice_eswitch_br_rule_delete(&pf->hw, flow->fwd_rule); + if (err) + dev_err(dev, "Failed to delete FDB forward rule, err: %d\n", + err); + + kfree(flow); +} + +static void +ice_eswitch_br_fdb_entry_delete(struct ice_esw_br *bridge, + struct ice_esw_br_fdb_entry *fdb_entry) +{ + struct ice_pf *pf = bridge->br_offloads->pf; + + rhashtable_remove_fast(&bridge->fdb_ht, &fdb_entry->ht_node, + ice_fdb_ht_params); + list_del(&fdb_entry->list); + + ice_eswitch_br_flow_delete(pf, fdb_entry->flow); + + kfree(fdb_entry); +} + +static void +ice_eswitch_br_fdb_offload_notify(struct net_device *dev, + const unsigned char *mac, u16 vid, + unsigned long val) +{ + struct switchdev_notifier_fdb_info fdb_info = { + .addr = mac, + .vid = vid, + .offloaded = true, + }; + + call_switchdev_notifiers(val, dev, &fdb_info.info, NULL); +} + +static void +ice_eswitch_br_fdb_entry_notify_and_cleanup(struct ice_esw_br *bridge, + struct ice_esw_br_fdb_entry *entry) +{ + if (!(entry->flags & ICE_ESWITCH_BR_FDB_ADDED_BY_USER)) + ice_eswitch_br_fdb_offload_notify(entry->dev, entry->data.addr, + entry->data.vid, + SWITCHDEV_FDB_DEL_TO_BRIDGE); + ice_eswitch_br_fdb_entry_delete(bridge, entry); +} + +static void +ice_eswitch_br_fdb_entry_find_and_delete(struct ice_esw_br *bridge, + const unsigned char *mac, u16 vid) +{ + struct ice_pf *pf = bridge->br_offloads->pf; + struct ice_esw_br_fdb_entry *fdb_entry; + struct device *dev = ice_pf_to_dev(pf); + + fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid); + if (!fdb_entry) { + dev_err(dev, "FDB entry with mac: %pM and vid: %u not found\n", + mac, vid); + return; + } + + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry); +} + +static void +ice_eswitch_br_fdb_entry_create(struct net_device *netdev, + struct ice_esw_br_port *br_port, + bool added_by_user, + const unsigned char *mac, u16 vid) +{ + struct ice_esw_br *bridge = br_port->bridge; + struct ice_pf *pf = bridge->br_offloads->pf; + struct device *dev = ice_pf_to_dev(pf); + struct ice_esw_br_fdb_entry *fdb_entry; + struct ice_esw_br_flow *flow; + struct ice_hw *hw = &pf->hw; + unsigned long event; + int err; + + fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid); + if (fdb_entry) + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry); + + fdb_entry = kzalloc(sizeof(*fdb_entry), GFP_KERNEL); + if (!fdb_entry) { + err = -ENOMEM; + goto err_exit; + } + + flow = ice_eswitch_br_flow_create(dev, hw, br_port->vsi_idx, + br_port->type, mac); + if (IS_ERR(flow)) { + err = PTR_ERR(flow); + goto err_add_flow; + } + + ether_addr_copy(fdb_entry->data.addr, mac); + fdb_entry->data.vid = vid; + fdb_entry->br_port = br_port; + fdb_entry->flow = flow; + fdb_entry->dev = netdev; + event = SWITCHDEV_FDB_ADD_TO_BRIDGE; + + if (added_by_user) { + fdb_entry->flags |= ICE_ESWITCH_BR_FDB_ADDED_BY_USER; + event = SWITCHDEV_FDB_OFFLOADED; + } + + err = rhashtable_insert_fast(&bridge->fdb_ht, &fdb_entry->ht_node, + ice_fdb_ht_params); + if (err) + goto err_fdb_insert; + + list_add(&fdb_entry->list, &bridge->fdb_list); + + ice_eswitch_br_fdb_offload_notify(netdev, mac, vid, event); + + return; + +err_fdb_insert: + ice_eswitch_br_flow_delete(pf, flow); +err_add_flow: + kfree(fdb_entry); +err_exit: + dev_err(dev, "Failed to create fdb entry, err: %d\n", err); +} + +static void +ice_eswitch_br_fdb_work_dealloc(struct ice_esw_br_fdb_work *fdb_work) +{ + kfree(fdb_work->fdb_info.addr); + kfree(fdb_work); +} + +static void +ice_eswitch_br_fdb_event_work(struct work_struct *work) +{ + struct ice_esw_br_fdb_work *fdb_work = ice_work_to_fdb_work(work); + bool added_by_user = fdb_work->fdb_info.added_by_user; + const unsigned char *mac = fdb_work->fdb_info.addr; + u16 vid = fdb_work->fdb_info.vid; + struct ice_esw_br_port *br_port; + + rtnl_lock(); + + br_port = ice_eswitch_br_netdev_to_port(fdb_work->dev); + if (!br_port) + goto err_exit; + + switch (fdb_work->event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: + ice_eswitch_br_fdb_entry_create(fdb_work->dev, br_port, + added_by_user, mac, vid); + break; + case SWITCHDEV_FDB_DEL_TO_DEVICE: + ice_eswitch_br_fdb_entry_find_and_delete(br_port->bridge, + mac, vid); + break; + default: + goto err_exit; + } + +err_exit: + rtnl_unlock(); + dev_put(fdb_work->dev); + ice_eswitch_br_fdb_work_dealloc(fdb_work); +} + +static struct ice_esw_br_fdb_work * +ice_eswitch_br_fdb_work_alloc(struct switchdev_notifier_fdb_info *fdb_info, + struct net_device *dev, + unsigned long event) +{ + struct ice_esw_br_fdb_work *work; + unsigned char *mac; + + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return ERR_PTR(-ENOMEM); + + INIT_WORK(&work->work, ice_eswitch_br_fdb_event_work); + memcpy(&work->fdb_info, fdb_info, sizeof(work->fdb_info)); + + mac = kzalloc(ETH_ALEN, GFP_ATOMIC); + if (!mac) { + kfree(work); + return ERR_PTR(-ENOMEM); + } + + ether_addr_copy(mac, fdb_info->addr); + work->fdb_info.addr = mac; + work->event = event; + work->dev = dev; + + return work; +} + +static int +ice_eswitch_br_switchdev_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + struct switchdev_notifier_fdb_info *fdb_info; + struct switchdev_notifier_info *info = ptr; + struct ice_esw_br_offloads *br_offloads; + struct ice_esw_br_fdb_work *work; + struct netlink_ext_ack *extack; + struct net_device *upper; + + br_offloads = ice_nb_to_br_offloads(nb, switchdev_nb); + extack = switchdev_notifier_info_to_extack(ptr); + + upper = netdev_master_upper_dev_get_rcu(dev); + if (!upper) + return NOTIFY_DONE; + + if (!netif_is_bridge_master(upper)) + return NOTIFY_DONE; + + if (!ice_eswitch_br_is_dev_valid(dev)) + return NOTIFY_DONE; + + if (!ice_eswitch_br_netdev_to_port(dev)) + return NOTIFY_DONE; + + switch (event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: + case SWITCHDEV_FDB_DEL_TO_DEVICE: + fdb_info = container_of(info, typeof(*fdb_info), info); + + work = ice_eswitch_br_fdb_work_alloc(fdb_info, dev, event); + if (IS_ERR(work)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to init switchdev fdb work"); + return notifier_from_errno(PTR_ERR(work)); + } + dev_hold(dev); + + queue_work(br_offloads->wq, &work->work); + break; + default: + break; + } + return NOTIFY_DONE; +} + static void ice_eswitch_br_port_deinit(struct ice_esw_br *bridge, struct ice_esw_br_port *br_port) { + struct ice_esw_br_fdb_entry *fdb_entry, *tmp; struct ice_vsi *vsi = br_port->vsi; + list_for_each_entry_safe(fdb_entry, tmp, &bridge->fdb_list, list) { + if (br_port == fdb_entry->br_port) + ice_eswitch_br_fdb_entry_delete(bridge, fdb_entry); + } + if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back) vsi->back->br_port = NULL; else if (vsi->vf && vsi->vf->repr) @@ -129,6 +530,8 @@ ice_eswitch_br_deinit(struct ice_esw_br_offloads *br_offloads, ice_eswitch_br_ports_flush(bridge); WARN_ON(!xa_empty(&bridge->ports)); xa_destroy(&bridge->ports); + rhashtable_destroy(&bridge->fdb_ht); + br_offloads->bridge = NULL; kfree(bridge); } @@ -137,11 +540,19 @@ static struct ice_esw_br * ice_eswitch_br_init(struct ice_esw_br_offloads *br_offloads, int ifindex) { struct ice_esw_br *bridge; + int err; bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return ERR_PTR(-ENOMEM); + err = rhashtable_init(&bridge->fdb_ht, &ice_fdb_ht_params); + if (err) { + kfree(bridge); + return ERR_PTR(err); + } + + INIT_LIST_HEAD(&bridge->fdb_list); bridge->br_offloads = br_offloads; bridge->ifindex = ifindex; xa_init(&bridge->ports); @@ -340,6 +751,8 @@ ice_eswitch_br_offloads_deinit(struct ice_pf *pf) return; unregister_netdevice_notifier(&br_offloads->netdev_nb); + unregister_switchdev_notifier(&br_offloads->switchdev_nb); + destroy_workqueue(br_offloads->wq); /* Although notifier block is unregistered just before, * so we don't get any new events, some events might be * already in progress. Hold the rtnl lock and wait for @@ -365,6 +778,22 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf) return PTR_ERR(br_offloads); } + br_offloads->wq = alloc_ordered_workqueue("ice_bridge_wq", 0); + if (!br_offloads->wq) { + err = -ENOMEM; + dev_err(dev, "Failed to allocate bridge workqueue\n"); + goto err_alloc_wq; + } + + br_offloads->switchdev_nb.notifier_call = + ice_eswitch_br_switchdev_event; + err = register_switchdev_notifier(&br_offloads->switchdev_nb); + if (err) { + dev_err(dev, + "Failed to register switchdev notifier\n"); + goto err_reg_switchdev_nb; + } + br_offloads->netdev_nb.notifier_call = ice_eswitch_br_port_event; err = register_netdevice_notifier(&br_offloads->netdev_nb); if (err) { @@ -376,6 +805,10 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf) return 0; err_reg_netdev_nb: + unregister_switchdev_notifier(&br_offloads->switchdev_nb); +err_reg_switchdev_nb: + destroy_workqueue(br_offloads->wq); +err_alloc_wq: rtnl_lock(); ice_eswitch_br_offloads_dealloc(pf); rtnl_unlock(); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h index 3ad28a17298f..e1b4eda7a890 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -4,6 +4,33 @@ #ifndef _ICE_ESWITCH_BR_H_ #define _ICE_ESWITCH_BR_H_ +#include + +struct ice_esw_br_fdb_data { + unsigned char addr[ETH_ALEN]; + u16 vid; +}; + +struct ice_esw_br_flow { + struct ice_rule_query_data *fwd_rule; +}; + +enum { + ICE_ESWITCH_BR_FDB_ADDED_BY_USER = BIT(0), +}; + +struct ice_esw_br_fdb_entry { + struct ice_esw_br_fdb_data data; + struct rhash_head ht_node; + struct list_head list; + + int flags; + + struct net_device *dev; + struct ice_esw_br_port *br_port; + struct ice_esw_br_flow *flow; +}; + enum ice_esw_br_port_type { ICE_ESWITCH_BR_UPLINK_PORT = 0, ICE_ESWITCH_BR_VF_REPR_PORT = 1, @@ -20,6 +47,9 @@ struct ice_esw_br { struct ice_esw_br_offloads *br_offloads; struct xarray ports; + struct rhashtable fdb_ht; + struct list_head fdb_list; + int ifindex; }; @@ -27,6 +57,16 @@ struct ice_esw_br_offloads { struct ice_pf *pf; struct ice_esw_br *bridge; struct notifier_block netdev_nb; + struct notifier_block switchdev_nb; + + struct workqueue_struct *wq; +}; + +struct ice_esw_br_fdb_work { + struct work_struct work; + struct switchdev_notifier_fdb_info fdb_info; + struct net_device *dev; + unsigned long event; }; #define ice_nb_to_br_offloads(nb, nb_name) \ @@ -34,6 +74,11 @@ struct ice_esw_br_offloads { struct ice_esw_br_offloads, \ nb_name) +#define ice_work_to_fdb_work(w) \ + container_of(w, \ + struct ice_esw_br_fdb_work, \ + work) + void ice_eswitch_br_offloads_deinit(struct ice_pf *pf); int -- cgit From bccd9bce29e0d0ac3d0705cc2e58fffe16179d12 Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Wed, 12 Jul 2023 13:03:33 +0200 Subject: ice: Add guard rule when creating FDB in switchdev Introduce new "guard" rule upon FDB entry creation. It matches on src_mac, has valid bit unset, allow_pass_l2 set and has a nop action. Previously introduced "forward" rule matches on dst_mac, has valid bit set, need_pass_l2 set and has a forward action. With these rules, a packet will be offloaded only if FDB exists in both directions (RX and TX). Let's assume link partner sends a packet to VF1: src_mac = LP_MAC, dst_mac = is VF1_MAC. Bridge adds FDB, two rules are created: 1. Guard rule matching on src_mac == LP_MAC 2. Forward rule matching on dst_mac == LP_MAC Now VF1 responds with src_mac = VF1_MAC, dst_mac = LP_MAC. Before this change, only one rule with dst_mac == LP_MAC would have existed, and the packet would have been offloaded, meaning the bridge wouldn't add FDB in the opposite direction. Now, the forward rule matches (dst_mac == LP_MAC), but it has need_pass_l2 set an there is no guard rule with src_mac == VF1_MAC, so the packet goes through slow-path and the bridge adds FDB. Two rules are created: 1. Guard rule matching on src_mac == VF1_MAC 2. Forward rule matching on dst_mac == VF1_MAC Further packets in both directions will be offloaded. The same example is true in opposite direction (i.e. VF1 is the first to send a packet out). Reviewed-by: Simon Horman Signed-off-by: Marcin Szycik Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 64 +++++++++++++++- drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 1 + drivers/net/ethernet/intel/ice/ice_switch.c | 97 ++++++++++++++++--------- drivers/net/ethernet/intel/ice/ice_switch.h | 5 ++ drivers/net/ethernet/intel/ice/ice_type.h | 1 + 5 files changed, 132 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 49b3ca5e956e..297d0eb45dde 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -107,6 +107,8 @@ ice_eswitch_br_fwd_rule_create(struct ice_hw *hw, int vsi_idx, int port_type, ether_addr_copy(list[0].h_u.eth_hdr.dst_addr, mac); eth_broadcast_addr(list[0].m_u.eth_hdr.dst_addr); + rule_info.need_pass_l2 = true; + rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, rule); @@ -125,11 +127,54 @@ err_list_alloc: return ERR_PTR(err); } +static struct ice_rule_query_data * +ice_eswitch_br_guard_rule_create(struct ice_hw *hw, u16 vsi_idx, + const unsigned char *mac) +{ + struct ice_adv_rule_info rule_info = { 0 }; + struct ice_rule_query_data *rule; + struct ice_adv_lkup_elem *list; + const u16 lkups_cnt = 1; + int err = -ENOMEM; + + rule = kzalloc(sizeof(*rule), GFP_KERNEL); + if (!rule) + goto err_exit; + + list = kcalloc(lkups_cnt, sizeof(*list), GFP_ATOMIC); + if (!list) + goto err_list_alloc; + + list[0].type = ICE_MAC_OFOS; + ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac); + eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr); + + rule_info.allow_pass_l2 = true; + rule_info.sw_act.vsi_handle = vsi_idx; + rule_info.sw_act.fltr_act = ICE_NOP; + rule_info.priority = 5; + + err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, rule); + if (err) + goto err_add_rule; + + kfree(list); + + return rule; + +err_add_rule: + kfree(list); +err_list_alloc: + kfree(rule); +err_exit: + return ERR_PTR(err); +} + static struct ice_esw_br_flow * ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, int port_type, const unsigned char *mac) { - struct ice_rule_query_data *fwd_rule; + struct ice_rule_query_data *fwd_rule, *guard_rule; struct ice_esw_br_flow *flow; int err; @@ -146,10 +191,22 @@ ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, goto err_fwd_rule; } + guard_rule = ice_eswitch_br_guard_rule_create(hw, vsi_idx, mac); + err = PTR_ERR_OR_ZERO(guard_rule); + if (err) { + dev_err(dev, "Failed to create eswitch bridge %sgress guard rule, err: %d\n", + port_type == ICE_ESWITCH_BR_UPLINK_PORT ? "e" : "in", + err); + goto err_guard_rule; + } + flow->fwd_rule = fwd_rule; + flow->guard_rule = guard_rule; return flow; +err_guard_rule: + ice_eswitch_br_rule_delete(hw, fwd_rule); err_fwd_rule: kfree(flow); @@ -180,6 +237,11 @@ ice_eswitch_br_flow_delete(struct ice_pf *pf, struct ice_esw_br_flow *flow) dev_err(dev, "Failed to delete FDB forward rule, err: %d\n", err); + err = ice_eswitch_br_rule_delete(&pf->hw, flow->guard_rule); + if (err) + dev_err(dev, "Failed to delete FDB guard rule, err: %d\n", + err); + kfree(flow); } diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h index e1b4eda7a890..d0dcf66ff08b 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -13,6 +13,7 @@ struct ice_esw_br_fdb_data { struct ice_esw_br_flow { struct ice_rule_query_data *fwd_rule; + struct ice_rule_query_data *guard_rule; }; enum { diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 81f45d7e76de..813fef5fd748 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -2272,6 +2272,10 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid, /* Propagate some data to the recipe database */ recps[idx].is_root = !!is_root; recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; + recps[idx].need_pass_l2 = root_bufs.content.act_ctrl & + ICE_AQ_RECIPE_ACT_NEED_PASS_L2; + recps[idx].allow_pass_l2 = root_bufs.content.act_ctrl & + ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2; bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS); if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) { recps[idx].chain_idx = root_bufs.content.result_indx & @@ -4613,13 +4617,13 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { * ice_find_recp - find a recipe * @hw: pointer to the hardware structure * @lkup_exts: extension sequence to match - * @tun_type: type of recipe tunnel + * @rinfo: information regarding the rule e.g. priority and action info * * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found. */ static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts, - enum ice_sw_tunnel_type tun_type) + const struct ice_adv_rule_info *rinfo) { bool refresh_required = true; struct ice_sw_recipe *recp; @@ -4680,9 +4684,12 @@ ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts, } /* If for "i"th recipe the found was never set to false * then it means we found our match - * Also tun type of recipe needs to be checked + * Also tun type and *_pass_l2 of recipe needs to be + * checked */ - if (found && recp[i].tun_type == tun_type) + if (found && recp[i].tun_type == rinfo->tun_type && + recp[i].need_pass_l2 == rinfo->need_pass_l2 && + recp[i].allow_pass_l2 == rinfo->allow_pass_l2) return i; /* Return the recipe ID */ } } @@ -4952,6 +4959,7 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, unsigned long *profiles) { DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS); + struct ice_aqc_recipe_content *content; struct ice_aqc_recipe_data_elem *tmp; struct ice_aqc_recipe_data_elem *buf; struct ice_recp_grp_entry *entry; @@ -5012,6 +5020,8 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, if (status) goto err_unroll; + content = &buf[recps].content; + /* Clear the result index of the located recipe, as this will be * updated, if needed, later in the recipe creation process. */ @@ -5022,26 +5032,24 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, /* if the recipe is a non-root recipe RID should be programmed * as 0 for the rules to be applied correctly. */ - buf[recps].content.rid = 0; - memset(&buf[recps].content.lkup_indx, 0, - sizeof(buf[recps].content.lkup_indx)); + content->rid = 0; + memset(&content->lkup_indx, 0, + sizeof(content->lkup_indx)); /* All recipes use look-up index 0 to match switch ID. */ - buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; - buf[recps].content.mask[0] = - cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); + content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; + content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); /* Setup lkup_indx 1..4 to INVALID/ignore and set the mask * to be 0 */ for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { - buf[recps].content.lkup_indx[i] = 0x80; - buf[recps].content.mask[i] = 0; + content->lkup_indx[i] = 0x80; + content->mask[i] = 0; } for (i = 0; i < entry->r_group.n_val_pairs; i++) { - buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i]; - buf[recps].content.mask[i + 1] = - cpu_to_le16(entry->fv_mask[i]); + content->lkup_indx[i + 1] = entry->fv_idx[i]; + content->mask[i + 1] = cpu_to_le16(entry->fv_mask[i]); } if (rm->n_grp_count > 1) { @@ -5055,7 +5063,7 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, } entry->chain_idx = chain_idx; - buf[recps].content.result_indx = + content->result_indx = ICE_AQ_RECIPE_RESULT_EN | ((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) & ICE_AQ_RECIPE_RESULT_DATA_M); @@ -5069,7 +5077,13 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, ICE_MAX_NUM_RECIPES); set_bit(buf[recps].recipe_indx, (unsigned long *)buf[recps].recipe_bitmap); - buf[recps].content.act_ctrl_fwd_priority = rm->priority; + content->act_ctrl_fwd_priority = rm->priority; + + if (rm->need_pass_l2) + content->act_ctrl |= ICE_AQ_RECIPE_ACT_NEED_PASS_L2; + + if (rm->allow_pass_l2) + content->act_ctrl |= ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2; recps++; } @@ -5107,9 +5121,11 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, if (status) goto err_unroll; + content = &buf[recps].content; + buf[recps].recipe_indx = (u8)rid; - buf[recps].content.rid = (u8)rid; - buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT; + content->rid = (u8)rid; + content->rid |= ICE_AQ_RECIPE_ID_IS_ROOT; /* the new entry created should also be part of rg_list to * make sure we have complete recipe */ @@ -5121,16 +5137,13 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, goto err_unroll; } last_chain_entry->rid = rid; - memset(&buf[recps].content.lkup_indx, 0, - sizeof(buf[recps].content.lkup_indx)); + memset(&content->lkup_indx, 0, sizeof(content->lkup_indx)); /* All recipes use look-up index 0 to match switch ID. */ - buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; - buf[recps].content.mask[0] = - cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); + content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; + content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { - buf[recps].content.lkup_indx[i] = - ICE_AQ_RECIPE_LKUP_IGNORE; - buf[recps].content.mask[i] = 0; + content->lkup_indx[i] = ICE_AQ_RECIPE_LKUP_IGNORE; + content->mask[i] = 0; } i = 1; @@ -5142,8 +5155,8 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND; list_for_each_entry(entry, &rm->rg_list, l_entry) { last_chain_entry->fv_idx[i] = entry->chain_idx; - buf[recps].content.lkup_indx[i] = entry->chain_idx; - buf[recps].content.mask[i++] = cpu_to_le16(0xFFFF); + content->lkup_indx[i] = entry->chain_idx; + content->mask[i++] = cpu_to_le16(0xFFFF); set_bit(entry->rid, rm->r_bitmap); } list_add(&last_chain_entry->l_entry, &rm->rg_list); @@ -5155,7 +5168,7 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, status = -EINVAL; goto err_unroll; } - buf[recps].content.act_ctrl_fwd_priority = rm->priority; + content->act_ctrl_fwd_priority = rm->priority; recps++; rm->root_rid = (u8)rid; @@ -5220,6 +5233,8 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority; recp->n_grp_count = rm->n_grp_count; recp->tun_type = rm->tun_type; + recp->need_pass_l2 = rm->need_pass_l2; + recp->allow_pass_l2 = rm->allow_pass_l2; recp->recp_created = true; } rm->root_buf = buf; @@ -5388,6 +5403,9 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, /* set the recipe priority if specified */ rm->priority = (u8)rinfo->priority; + rm->need_pass_l2 = rinfo->need_pass_l2; + rm->allow_pass_l2 = rinfo->allow_pass_l2; + /* Find offsets from the field vector. Pick the first one for all the * recipes. */ @@ -5403,7 +5421,7 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, } /* Look for a recipe which matches our requested fv / mask list */ - *rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type); + *rid = ice_find_recp(hw, lkup_exts, rinfo); if (*rid < ICE_MAX_NUM_RECIPES) /* Success if found a recipe that match the existing criteria */ goto err_unroll; @@ -5839,7 +5857,9 @@ static bool ice_rules_equal(const struct ice_adv_rule_info *first, return first->sw_act.flag == second->sw_act.flag && first->tun_type == second->tun_type && first->vlan_type == second->vlan_type && - first->src_vsi == second->src_vsi; + first->src_vsi == second->src_vsi && + first->need_pass_l2 == second->need_pass_l2 && + first->allow_pass_l2 == second->allow_pass_l2; } /** @@ -6078,7 +6098,8 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || rinfo->sw_act.fltr_act == ICE_FWD_TO_Q || rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP || - rinfo->sw_act.fltr_act == ICE_DROP_PACKET)) { + rinfo->sw_act.fltr_act == ICE_DROP_PACKET || + rinfo->sw_act.fltr_act == ICE_NOP)) { status = -EIO; goto free_pkt_profile; } @@ -6089,7 +6110,8 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, goto free_pkt_profile; } - if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) + if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || + rinfo->sw_act.fltr_act == ICE_NOP) rinfo->sw_act.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); @@ -6159,6 +6181,11 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | ICE_SINGLE_ACT_VALID_BIT; break; + case ICE_NOP: + act |= FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M, + rinfo->sw_act.fwd_id.hw_vsi_id); + act &= ~ICE_SINGLE_ACT_VALID_BIT; + break; default: status = -EIO; goto err_ice_add_adv_rule; @@ -6439,7 +6466,7 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, return -EIO; } - rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type); + rid = ice_find_recp(hw, &lkup_exts, rinfo); /* If did not find a recipe that match the existing criteria */ if (rid == ICE_MAX_NUM_RECIPES) return -EINVAL; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index db08509805ce..10f5a0ae199e 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -191,6 +191,8 @@ struct ice_adv_rule_info { u16 vlan_type; u16 fltr_rule_id; u32 priority; + u16 need_pass_l2:1; + u16 allow_pass_l2:1; u16 src_vsi; struct ice_sw_act_ctrl sw_act; struct ice_adv_rule_flags_info flags_info; @@ -254,6 +256,9 @@ struct ice_sw_recipe { */ u8 priority; + u8 need_pass_l2:1; + u8 allow_pass_l2:1; + struct list_head rg_list; /* AQ buffer associated with this recipe */ diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index a09556e57803..df9171a1a34f 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -1033,6 +1033,7 @@ enum ice_sw_fwd_act_type { ICE_FWD_TO_Q, ICE_FWD_TO_QGRP, ICE_DROP_PACKET, + ICE_NOP, ICE_INVAL_ACT }; -- cgit From e9dda2cfab820f76c40932bda629aaeed71eec74 Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Wed, 12 Jul 2023 13:03:34 +0200 Subject: ice: Add VLAN FDB support in switchdev mode Add support for matching on VLAN tag in bridge offloads. Currently only trunk mode is supported. To enable VLAN filtering (existing FDB entries will be deleted): ip link set $BR type bridge vlan_filtering 1 To add VLANs to bridge in trunk mode: bridge vlan add dev $PF1 vid 110-111 bridge vlan add dev $VF1_PR vid 110-111 Signed-off-by: Marcin Szycik Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 304 +++++++++++++++++++++++- drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 21 ++ 2 files changed, 317 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 297d0eb45dde..151b40857515 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -70,16 +70,34 @@ ice_eswitch_br_rule_delete(struct ice_hw *hw, struct ice_rule_query_data *rule) return err; } +static u16 +ice_eswitch_br_get_lkups_cnt(u16 vid) +{ + return ice_eswitch_br_is_vid_valid(vid) ? 2 : 1; +} + +static void +ice_eswitch_br_add_vlan_lkup(struct ice_adv_lkup_elem *list, u16 vid) +{ + if (ice_eswitch_br_is_vid_valid(vid)) { + list[1].type = ICE_VLAN_OFOS; + list[1].h_u.vlan_hdr.vlan = cpu_to_be16(vid & VLAN_VID_MASK); + list[1].m_u.vlan_hdr.vlan = cpu_to_be16(0xFFFF); + } +} + static struct ice_rule_query_data * ice_eswitch_br_fwd_rule_create(struct ice_hw *hw, int vsi_idx, int port_type, - const unsigned char *mac) + const unsigned char *mac, u16 vid) { struct ice_adv_rule_info rule_info = { 0 }; struct ice_rule_query_data *rule; struct ice_adv_lkup_elem *list; - u16 lkups_cnt = 1; + u16 lkups_cnt; int err; + lkups_cnt = ice_eswitch_br_get_lkups_cnt(vid); + rule = kzalloc(sizeof(*rule), GFP_KERNEL); if (!rule) return ERR_PTR(-ENOMEM); @@ -107,6 +125,8 @@ ice_eswitch_br_fwd_rule_create(struct ice_hw *hw, int vsi_idx, int port_type, ether_addr_copy(list[0].h_u.eth_hdr.dst_addr, mac); eth_broadcast_addr(list[0].m_u.eth_hdr.dst_addr); + ice_eswitch_br_add_vlan_lkup(list, vid); + rule_info.need_pass_l2 = true; rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; @@ -129,13 +149,15 @@ err_list_alloc: static struct ice_rule_query_data * ice_eswitch_br_guard_rule_create(struct ice_hw *hw, u16 vsi_idx, - const unsigned char *mac) + const unsigned char *mac, u16 vid) { struct ice_adv_rule_info rule_info = { 0 }; struct ice_rule_query_data *rule; struct ice_adv_lkup_elem *list; - const u16 lkups_cnt = 1; int err = -ENOMEM; + u16 lkups_cnt; + + lkups_cnt = ice_eswitch_br_get_lkups_cnt(vid); rule = kzalloc(sizeof(*rule), GFP_KERNEL); if (!rule) @@ -149,6 +171,8 @@ ice_eswitch_br_guard_rule_create(struct ice_hw *hw, u16 vsi_idx, ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac); eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr); + ice_eswitch_br_add_vlan_lkup(list, vid); + rule_info.allow_pass_l2 = true; rule_info.sw_act.vsi_handle = vsi_idx; rule_info.sw_act.fltr_act = ICE_NOP; @@ -172,7 +196,7 @@ err_exit: static struct ice_esw_br_flow * ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, - int port_type, const unsigned char *mac) + int port_type, const unsigned char *mac, u16 vid) { struct ice_rule_query_data *fwd_rule, *guard_rule; struct ice_esw_br_flow *flow; @@ -182,7 +206,8 @@ ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, if (!flow) return ERR_PTR(-ENOMEM); - fwd_rule = ice_eswitch_br_fwd_rule_create(hw, vsi_idx, port_type, mac); + fwd_rule = ice_eswitch_br_fwd_rule_create(hw, vsi_idx, port_type, mac, + vid); err = PTR_ERR_OR_ZERO(fwd_rule); if (err) { dev_err(dev, "Failed to create eswitch bridge %sgress forward rule, err: %d\n", @@ -191,7 +216,7 @@ ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx, goto err_fwd_rule; } - guard_rule = ice_eswitch_br_guard_rule_create(hw, vsi_idx, mac); + guard_rule = ice_eswitch_br_guard_rule_create(hw, vsi_idx, mac, vid); err = PTR_ERR_OR_ZERO(guard_rule); if (err) { dev_err(dev, "Failed to create eswitch bridge %sgress guard rule, err: %d\n", @@ -245,6 +270,30 @@ ice_eswitch_br_flow_delete(struct ice_pf *pf, struct ice_esw_br_flow *flow) kfree(flow); } +static struct ice_esw_br_vlan * +ice_esw_br_port_vlan_lookup(struct ice_esw_br *bridge, u16 vsi_idx, u16 vid) +{ + struct ice_pf *pf = bridge->br_offloads->pf; + struct device *dev = ice_pf_to_dev(pf); + struct ice_esw_br_port *port; + struct ice_esw_br_vlan *vlan; + + port = xa_load(&bridge->ports, vsi_idx); + if (!port) { + dev_info(dev, "Bridge port lookup failed (vsi=%u)\n", vsi_idx); + return ERR_PTR(-EINVAL); + } + + vlan = xa_load(&port->vlans, vid); + if (!vlan) { + dev_info(dev, "Bridge port vlan metadata lookup failed (vsi=%u)\n", + vsi_idx); + return ERR_PTR(-EINVAL); + } + + return vlan; +} + static void ice_eswitch_br_fdb_entry_delete(struct ice_esw_br *bridge, struct ice_esw_br_fdb_entry *fdb_entry) @@ -314,10 +363,25 @@ ice_eswitch_br_fdb_entry_create(struct net_device *netdev, struct device *dev = ice_pf_to_dev(pf); struct ice_esw_br_fdb_entry *fdb_entry; struct ice_esw_br_flow *flow; + struct ice_esw_br_vlan *vlan; struct ice_hw *hw = &pf->hw; unsigned long event; int err; + /* untagged filtering is not yet supported */ + if (!(bridge->flags & ICE_ESWITCH_BR_VLAN_FILTERING) && vid) + return; + + if ((bridge->flags & ICE_ESWITCH_BR_VLAN_FILTERING)) { + vlan = ice_esw_br_port_vlan_lookup(bridge, br_port->vsi_idx, + vid); + if (IS_ERR(vlan)) { + dev_err(dev, "Failed to find vlan lookup, err: %ld\n", + PTR_ERR(vlan)); + return; + } + } + fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid); if (fdb_entry) ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry); @@ -329,7 +393,7 @@ ice_eswitch_br_fdb_entry_create(struct net_device *netdev, } flow = ice_eswitch_br_flow_create(dev, hw, br_port->vsi_idx, - br_port->type, mac); + br_port->type, mac, vid); if (IS_ERR(flow)) { err = PTR_ERR(flow); goto err_add_flow; @@ -484,6 +548,215 @@ ice_eswitch_br_switchdev_event(struct notifier_block *nb, return NOTIFY_DONE; } +static void ice_eswitch_br_fdb_flush(struct ice_esw_br *bridge) +{ + struct ice_esw_br_fdb_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, entry); +} + +static void +ice_eswitch_br_vlan_filtering_set(struct ice_esw_br *bridge, bool enable) +{ + if (enable == !!(bridge->flags & ICE_ESWITCH_BR_VLAN_FILTERING)) + return; + + ice_eswitch_br_fdb_flush(bridge); + if (enable) + bridge->flags |= ICE_ESWITCH_BR_VLAN_FILTERING; + else + bridge->flags &= ~ICE_ESWITCH_BR_VLAN_FILTERING; +} + +static void +ice_eswitch_br_vlan_cleanup(struct ice_esw_br_port *port, + struct ice_esw_br_vlan *vlan) +{ + struct ice_esw_br_fdb_entry *fdb_entry, *tmp; + struct ice_esw_br *bridge = port->bridge; + + list_for_each_entry_safe(fdb_entry, tmp, &bridge->fdb_list, list) { + if (vlan->vid == fdb_entry->data.vid) + ice_eswitch_br_fdb_entry_delete(bridge, fdb_entry); + } + + xa_erase(&port->vlans, vlan->vid); + kfree(vlan); +} + +static void ice_eswitch_br_port_vlans_flush(struct ice_esw_br_port *port) +{ + struct ice_esw_br_vlan *vlan; + unsigned long index; + + xa_for_each(&port->vlans, index, vlan) + ice_eswitch_br_vlan_cleanup(port, vlan); +} + +static struct ice_esw_br_vlan * +ice_eswitch_br_vlan_create(u16 vid, u16 flags, struct ice_esw_br_port *port) +{ + struct ice_esw_br_vlan *vlan; + int err; + + vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); + if (!vlan) + return ERR_PTR(-ENOMEM); + + vlan->vid = vid; + vlan->flags = flags; + + err = xa_insert(&port->vlans, vlan->vid, vlan, GFP_KERNEL); + if (err) { + kfree(vlan); + return ERR_PTR(err); + } + + return vlan; +} + +static int +ice_eswitch_br_port_vlan_add(struct ice_esw_br *bridge, u16 vsi_idx, u16 vid, + u16 flags, struct netlink_ext_ack *extack) +{ + struct ice_esw_br_port *port; + struct ice_esw_br_vlan *vlan; + + port = xa_load(&bridge->ports, vsi_idx); + if (!port) + return -EINVAL; + + vlan = xa_load(&port->vlans, vid); + if (vlan) { + if (vlan->flags == flags) + return 0; + + ice_eswitch_br_vlan_cleanup(port, vlan); + } + + vlan = ice_eswitch_br_vlan_create(vid, flags, port); + if (IS_ERR(vlan)) { + NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to create VLAN entry, vid: %u, vsi: %u", + vid, vsi_idx); + return PTR_ERR(vlan); + } + + return 0; +} + +static void +ice_eswitch_br_port_vlan_del(struct ice_esw_br *bridge, u16 vsi_idx, u16 vid) +{ + struct ice_esw_br_port *port; + struct ice_esw_br_vlan *vlan; + + port = xa_load(&bridge->ports, vsi_idx); + if (!port) + return; + + vlan = xa_load(&port->vlans, vid); + if (!vlan) + return; + + ice_eswitch_br_vlan_cleanup(port, vlan); +} + +static int +ice_eswitch_br_port_obj_add(struct net_device *netdev, const void *ctx, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) +{ + struct ice_esw_br_port *br_port = ice_eswitch_br_netdev_to_port(netdev); + struct switchdev_obj_port_vlan *vlan; + int err; + + if (!br_port) + return -EINVAL; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); + err = ice_eswitch_br_port_vlan_add(br_port->bridge, + br_port->vsi_idx, vlan->vid, + vlan->flags, extack); + return err; + default: + return -EOPNOTSUPP; + } +} + +static int +ice_eswitch_br_port_obj_del(struct net_device *netdev, const void *ctx, + const struct switchdev_obj *obj) +{ + struct ice_esw_br_port *br_port = ice_eswitch_br_netdev_to_port(netdev); + struct switchdev_obj_port_vlan *vlan; + + if (!br_port) + return -EINVAL; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); + ice_eswitch_br_port_vlan_del(br_port->bridge, br_port->vsi_idx, + vlan->vid); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int +ice_eswitch_br_port_obj_attr_set(struct net_device *netdev, const void *ctx, + const struct switchdev_attr *attr, + struct netlink_ext_ack *extack) +{ + struct ice_esw_br_port *br_port = ice_eswitch_br_netdev_to_port(netdev); + + if (!br_port) + return -EINVAL; + + switch (attr->id) { + case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: + ice_eswitch_br_vlan_filtering_set(br_port->bridge, + attr->u.vlan_filtering); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int +ice_eswitch_br_event_blocking(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + int err; + + switch (event) { + case SWITCHDEV_PORT_OBJ_ADD: + err = switchdev_handle_port_obj_add(dev, ptr, + ice_eswitch_br_is_dev_valid, + ice_eswitch_br_port_obj_add); + break; + case SWITCHDEV_PORT_OBJ_DEL: + err = switchdev_handle_port_obj_del(dev, ptr, + ice_eswitch_br_is_dev_valid, + ice_eswitch_br_port_obj_del); + break; + case SWITCHDEV_PORT_ATTR_SET: + err = switchdev_handle_port_attr_set(dev, ptr, + ice_eswitch_br_is_dev_valid, + ice_eswitch_br_port_obj_attr_set); + break; + default: + err = 0; + } + + return notifier_from_errno(err); +} + static void ice_eswitch_br_port_deinit(struct ice_esw_br *bridge, struct ice_esw_br_port *br_port) @@ -502,6 +775,7 @@ ice_eswitch_br_port_deinit(struct ice_esw_br *bridge, vsi->vf->repr->br_port = NULL; xa_erase(&bridge->ports, br_port->vsi_idx); + ice_eswitch_br_port_vlans_flush(br_port); kfree(br_port); } @@ -514,6 +788,8 @@ ice_eswitch_br_port_init(struct ice_esw_br *bridge) if (!br_port) return ERR_PTR(-ENOMEM); + xa_init(&br_port->vlans); + br_port->bridge = bridge; return br_port; @@ -813,6 +1089,7 @@ ice_eswitch_br_offloads_deinit(struct ice_pf *pf) return; unregister_netdevice_notifier(&br_offloads->netdev_nb); + unregister_switchdev_blocking_notifier(&br_offloads->switchdev_blk); unregister_switchdev_notifier(&br_offloads->switchdev_nb); destroy_workqueue(br_offloads->wq); /* Although notifier block is unregistered just before, @@ -856,6 +1133,15 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf) goto err_reg_switchdev_nb; } + br_offloads->switchdev_blk.notifier_call = + ice_eswitch_br_event_blocking; + err = register_switchdev_blocking_notifier(&br_offloads->switchdev_blk); + if (err) { + dev_err(dev, + "Failed to register bridge blocking switchdev notifier\n"); + goto err_reg_switchdev_blk; + } + br_offloads->netdev_nb.notifier_call = ice_eswitch_br_port_event; err = register_netdevice_notifier(&br_offloads->netdev_nb); if (err) { @@ -867,6 +1153,8 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf) return 0; err_reg_netdev_nb: + unregister_switchdev_blocking_notifier(&br_offloads->switchdev_blk); +err_reg_switchdev_blk: unregister_switchdev_notifier(&br_offloads->switchdev_nb); err_reg_switchdev_nb: destroy_workqueue(br_offloads->wq); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h index d0dcf66ff08b..fa1f77f76292 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -42,6 +42,11 @@ struct ice_esw_br_port { struct ice_vsi *vsi; enum ice_esw_br_port_type type; u16 vsi_idx; + struct xarray vlans; +}; + +enum { + ICE_ESWITCH_BR_VLAN_FILTERING = BIT(0), }; struct ice_esw_br { @@ -52,12 +57,14 @@ struct ice_esw_br { struct list_head fdb_list; int ifindex; + u32 flags; }; struct ice_esw_br_offloads { struct ice_pf *pf; struct ice_esw_br *bridge; struct notifier_block netdev_nb; + struct notifier_block switchdev_blk; struct notifier_block switchdev_nb; struct workqueue_struct *wq; @@ -70,6 +77,11 @@ struct ice_esw_br_fdb_work { unsigned long event; }; +struct ice_esw_br_vlan { + u16 vid; + u16 flags; +}; + #define ice_nb_to_br_offloads(nb, nb_name) \ container_of(nb, \ struct ice_esw_br_offloads, \ @@ -80,6 +92,15 @@ struct ice_esw_br_fdb_work { struct ice_esw_br_fdb_work, \ work) +static inline bool ice_eswitch_br_is_vid_valid(u16 vid) +{ + /* In trunk VLAN mode, for untagged traffic the bridge sends requests + * to offload VLAN 1 with pvid and untagged flags set. Since these + * flags are not supported, add a MAC filter instead. + */ + return vid > 1; +} + void ice_eswitch_br_offloads_deinit(struct ice_pf *pf); int -- cgit From 2946204b3fa84fda9b3b3048451fb9ffc977f434 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Wed, 12 Jul 2023 13:03:35 +0200 Subject: ice: implement bridge port vlan Port VLAN in this case means push and pop VLAN action on specific vid. There are a few limitation in hardware: - push and pop can't be used separately - if port VLAN is used there can't be any trunk VLANs, because pop action is done on all traffic received by VSI in port VLAN mode - port VLAN mode on uplink port isn't supported Reflect these limitations in code using dev_info to inform the user about unsupported configuration. In bridge mode there is a need to configure port vlan without resetting VFs. To do that implement ice_port_vlan_on/off() functions. They are only configuring correct vlan_ops to allow setting port vlan. We also need to clear port vlan without resetting the VF which is not supported right now. Change it by implementing clear_port_vlan ops. As previous VLAN configuration isn't always the same, store current config while creating port vlan and restore it in clear function. Configuration steps: - configure switchdev with bridge - #bridge vlan add dev eth0 vid 120 pvid untagged - #bridge vlan add dev eth1 vid 120 pvid untagged - ping from VF0 to VF1 Reviewed-by: Simon Horman Signed-off-by: Michal Swiatkowski Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 92 +++++++++- drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 1 + .../net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c | 186 ++++++++++++--------- .../net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.h | 4 + drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c | 84 +++++++++- drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h | 8 + drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h | 1 + 8 files changed, 287 insertions(+), 90 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 8918a4b836a2..9109006336f0 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -370,6 +370,7 @@ struct ice_vsi { u16 rx_buf_len; struct ice_aqc_vsi_props info; /* VSI properties */ + struct ice_vsi_vlan_info vlan_info; /* vlan config to be restored */ /* VSI stats */ struct rtnl_link_stats64 net_stats; diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 151b40857515..85143ad9eb1d 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -5,6 +5,8 @@ #include "ice_eswitch_br.h" #include "ice_repr.h" #include "ice_switch.h" +#include "ice_vlan.h" +#include "ice_vf_vsi_vlan_ops.h" static const struct rhashtable_params ice_fdb_ht_params = { .key_offset = offsetof(struct ice_esw_br_fdb_entry, data), @@ -569,6 +571,22 @@ ice_eswitch_br_vlan_filtering_set(struct ice_esw_br *bridge, bool enable) bridge->flags &= ~ICE_ESWITCH_BR_VLAN_FILTERING; } +static void +ice_eswitch_br_clear_pvid(struct ice_esw_br_port *port) +{ + struct ice_vlan port_vlan = ICE_VLAN(ETH_P_8021Q, port->pvid, 0); + struct ice_vsi_vlan_ops *vlan_ops; + + vlan_ops = ice_get_compat_vsi_vlan_ops(port->vsi); + + vlan_ops->del_vlan(port->vsi, &port_vlan); + vlan_ops->clear_port_vlan(port->vsi); + + ice_vf_vsi_disable_port_vlan(port->vsi); + + port->pvid = 0; +} + static void ice_eswitch_br_vlan_cleanup(struct ice_esw_br_port *port, struct ice_esw_br_vlan *vlan) @@ -582,6 +600,8 @@ ice_eswitch_br_vlan_cleanup(struct ice_esw_br_port *port, } xa_erase(&port->vlans, vlan->vid); + if (port->pvid == vlan->vid) + ice_eswitch_br_clear_pvid(port); kfree(vlan); } @@ -594,9 +614,50 @@ static void ice_eswitch_br_port_vlans_flush(struct ice_esw_br_port *port) ice_eswitch_br_vlan_cleanup(port, vlan); } +static int +ice_eswitch_br_set_pvid(struct ice_esw_br_port *port, + struct ice_esw_br_vlan *vlan) +{ + struct ice_vlan port_vlan = ICE_VLAN(ETH_P_8021Q, vlan->vid, 0); + struct device *dev = ice_pf_to_dev(port->vsi->back); + struct ice_vsi_vlan_ops *vlan_ops; + int err; + + if (port->pvid == vlan->vid || vlan->vid == 1) + return 0; + + /* Setting port vlan on uplink isn't supported by hw */ + if (port->type == ICE_ESWITCH_BR_UPLINK_PORT) + return -EOPNOTSUPP; + + if (port->pvid) { + dev_info(dev, + "Port VLAN (vsi=%u, vid=%u) already exists on the port, remove it before adding new one\n", + port->vsi_idx, port->pvid); + return -EEXIST; + } + + ice_vf_vsi_enable_port_vlan(port->vsi); + + vlan_ops = ice_get_compat_vsi_vlan_ops(port->vsi); + err = vlan_ops->set_port_vlan(port->vsi, &port_vlan); + if (err) + return err; + + err = vlan_ops->add_vlan(port->vsi, &port_vlan); + if (err) + return err; + + ice_eswitch_br_port_vlans_flush(port); + port->pvid = vlan->vid; + + return 0; +} + static struct ice_esw_br_vlan * ice_eswitch_br_vlan_create(u16 vid, u16 flags, struct ice_esw_br_port *port) { + struct device *dev = ice_pf_to_dev(port->vsi->back); struct ice_esw_br_vlan *vlan; int err; @@ -606,14 +667,30 @@ ice_eswitch_br_vlan_create(u16 vid, u16 flags, struct ice_esw_br_port *port) vlan->vid = vid; vlan->flags = flags; + if ((flags & BRIDGE_VLAN_INFO_PVID) && + (flags & BRIDGE_VLAN_INFO_UNTAGGED)) { + err = ice_eswitch_br_set_pvid(port, vlan); + if (err) + goto err_set_pvid; + } else if ((flags & BRIDGE_VLAN_INFO_PVID) || + (flags & BRIDGE_VLAN_INFO_UNTAGGED)) { + dev_info(dev, "VLAN push and pop are supported only simultaneously\n"); + err = -EOPNOTSUPP; + goto err_set_pvid; + } err = xa_insert(&port->vlans, vlan->vid, vlan, GFP_KERNEL); - if (err) { - kfree(vlan); - return ERR_PTR(err); - } + if (err) + goto err_insert; return vlan; + +err_insert: + if (port->pvid) + ice_eswitch_br_clear_pvid(port); +err_set_pvid: + kfree(vlan); + return ERR_PTR(err); } static int @@ -627,6 +704,13 @@ ice_eswitch_br_port_vlan_add(struct ice_esw_br *bridge, u16 vsi_idx, u16 vid, if (!port) return -EINVAL; + if (port->pvid) { + dev_info(ice_pf_to_dev(port->vsi->back), + "Port VLAN (vsi=%u, vid=%d) exists on the port, remove it to add trunk VLANs\n", + port->vsi_idx, port->pvid); + return -EEXIST; + } + vlan = xa_load(&port->vlans, vid); if (vlan) { if (vlan->flags == flags) diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h index fa1f77f76292..978e9ce8e277 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -42,6 +42,7 @@ struct ice_esw_br_port { struct ice_vsi *vsi; enum ice_esw_br_port_type type; u16 vsi_idx; + u16 pvid; struct xarray vlans; }; diff --git a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c index b1ffb81893d4..d7b10dc67f03 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c @@ -21,6 +21,99 @@ noop_vlan(struct ice_vsi __always_unused *vsi) return 0; } +static void ice_port_vlan_on(struct ice_vsi *vsi) +{ + struct ice_vsi_vlan_ops *vlan_ops; + struct ice_pf *pf = vsi->back; + + if (ice_is_dvm_ena(&pf->hw)) { + vlan_ops = &vsi->outer_vlan_ops; + + /* setup outer VLAN ops */ + vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan; + vlan_ops->clear_port_vlan = ice_vsi_clear_outer_port_vlan; + vlan_ops->clear_port_vlan = ice_vsi_clear_outer_port_vlan; + + /* setup inner VLAN ops */ + vlan_ops = &vsi->inner_vlan_ops; + vlan_ops->add_vlan = noop_vlan_arg; + vlan_ops->del_vlan = noop_vlan_arg; + vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping; + vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping; + vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; + vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; + } else { + vlan_ops = &vsi->inner_vlan_ops; + + vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan; + vlan_ops->clear_port_vlan = ice_vsi_clear_inner_port_vlan; + vlan_ops->clear_port_vlan = ice_vsi_clear_inner_port_vlan; + } + vlan_ops->ena_rx_filtering = ice_vsi_ena_rx_vlan_filtering; +} + +static void ice_port_vlan_off(struct ice_vsi *vsi) +{ + struct ice_vsi_vlan_ops *vlan_ops; + struct ice_pf *pf = vsi->back; + + /* setup inner VLAN ops */ + vlan_ops = &vsi->inner_vlan_ops; + + vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping; + vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping; + vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; + vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; + + if (ice_is_dvm_ena(&pf->hw)) { + vlan_ops = &vsi->outer_vlan_ops; + + vlan_ops->del_vlan = ice_vsi_del_vlan; + vlan_ops->ena_stripping = ice_vsi_ena_outer_stripping; + vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping; + vlan_ops->ena_insertion = ice_vsi_ena_outer_insertion; + vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion; + } else { + vlan_ops->del_vlan = ice_vsi_del_vlan; + } + + if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) + vlan_ops->ena_rx_filtering = noop_vlan; + else + vlan_ops->ena_rx_filtering = + ice_vsi_ena_rx_vlan_filtering; +} + +/** + * ice_vf_vsi_enable_port_vlan - Set VSI VLAN ops to support port VLAN + * @vsi: VF's VSI being configured + * + * The function won't create port VLAN, it only allows to create port VLAN + * using VLAN ops on the VF VSI. + */ +void ice_vf_vsi_enable_port_vlan(struct ice_vsi *vsi) +{ + if (WARN_ON_ONCE(!vsi->vf)) + return; + + ice_port_vlan_on(vsi); +} + +/** + * ice_vf_vsi_disable_port_vlan - Clear VSI support for creating port VLAN + * @vsi: VF's VSI being configured + * + * The function should be called after removing port VLAN on VSI + * (using VLAN ops) + */ +void ice_vf_vsi_disable_port_vlan(struct ice_vsi *vsi) +{ + if (WARN_ON_ONCE(!vsi->vf)) + return; + + ice_port_vlan_off(vsi); +} + /** * ice_vf_vsi_init_vlan_ops - Initialize default VSI VLAN ops for VF VSI * @vsi: VF's VSI being configured @@ -39,91 +132,18 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) if (WARN_ON(!vf)) return; - if (ice_is_dvm_ena(&pf->hw)) { - vlan_ops = &vsi->outer_vlan_ops; + if (ice_vf_is_port_vlan_ena(vf)) + ice_port_vlan_on(vsi); + else + ice_port_vlan_off(vsi); - /* outer VLAN ops regardless of port VLAN config */ - vlan_ops->add_vlan = ice_vsi_add_vlan; - vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; - vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; - - if (ice_vf_is_port_vlan_ena(vf)) { - /* setup outer VLAN ops */ - vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan; - /* all Rx traffic should be in the domain of the - * assigned port VLAN, so prevent disabling Rx VLAN - * filtering - */ - vlan_ops->dis_rx_filtering = noop_vlan; - vlan_ops->ena_rx_filtering = - ice_vsi_ena_rx_vlan_filtering; - - /* setup inner VLAN ops */ - vlan_ops = &vsi->inner_vlan_ops; - vlan_ops->add_vlan = noop_vlan_arg; - vlan_ops->del_vlan = noop_vlan_arg; - vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping; - vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping; - vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; - vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; - } else { - vlan_ops->dis_rx_filtering = - ice_vsi_dis_rx_vlan_filtering; - - if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) - vlan_ops->ena_rx_filtering = noop_vlan; - else - vlan_ops->ena_rx_filtering = - ice_vsi_ena_rx_vlan_filtering; - - vlan_ops->del_vlan = ice_vsi_del_vlan; - vlan_ops->ena_stripping = ice_vsi_ena_outer_stripping; - vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping; - vlan_ops->ena_insertion = ice_vsi_ena_outer_insertion; - vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion; - - /* setup inner VLAN ops */ - vlan_ops = &vsi->inner_vlan_ops; - - vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping; - vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping; - vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; - vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; - } - } else { - vlan_ops = &vsi->inner_vlan_ops; + vlan_ops = ice_is_dvm_ena(&pf->hw) ? + &vsi->outer_vlan_ops : &vsi->inner_vlan_ops; - /* inner VLAN ops regardless of port VLAN config */ - vlan_ops->add_vlan = ice_vsi_add_vlan; - vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering; - vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; - vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; - - if (ice_vf_is_port_vlan_ena(vf)) { - vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan; - vlan_ops->ena_rx_filtering = - ice_vsi_ena_rx_vlan_filtering; - /* all Rx traffic should be in the domain of the - * assigned port VLAN, so prevent disabling Rx VLAN - * filtering - */ - vlan_ops->dis_rx_filtering = noop_vlan; - } else { - vlan_ops->dis_rx_filtering = - ice_vsi_dis_rx_vlan_filtering; - if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags)) - vlan_ops->ena_rx_filtering = noop_vlan; - else - vlan_ops->ena_rx_filtering = - ice_vsi_ena_rx_vlan_filtering; - - vlan_ops->del_vlan = ice_vsi_del_vlan; - vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping; - vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping; - vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion; - vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion; - } - } + vlan_ops->add_vlan = ice_vsi_add_vlan; + vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering; + vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering; + vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.h b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.h index 875a4e615f39..df8aa09df3e3 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.h @@ -13,7 +13,11 @@ void ice_vf_vsi_cfg_svm_legacy_vlan_mode(struct ice_vsi *vsi); #ifdef CONFIG_PCI_IOV void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi); +void ice_vf_vsi_enable_port_vlan(struct ice_vsi *vsi); +void ice_vf_vsi_disable_port_vlan(struct ice_vsi *vsi); #else static inline void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) { } +static inline void ice_vf_vsi_enable_port_vlan(struct ice_vsi *vsi) { } +static inline void ice_vf_vsi_disable_port_vlan(struct ice_vsi *vsi) { } #endif /* CONFIG_PCI_IOV */ #endif /* _ICE_PF_VSI_VLAN_OPS_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c index 5b4a0abb4607..76266e709a39 100644 --- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c @@ -202,6 +202,24 @@ int ice_vsi_dis_inner_insertion(struct ice_vsi *vsi) return ice_vsi_manage_vlan_insertion(vsi); } +static void +ice_save_vlan_info(struct ice_aqc_vsi_props *info, + struct ice_vsi_vlan_info *vlan) +{ + vlan->sw_flags2 = info->sw_flags2; + vlan->inner_vlan_flags = info->inner_vlan_flags; + vlan->outer_vlan_flags = info->outer_vlan_flags; +} + +static void +ice_restore_vlan_info(struct ice_aqc_vsi_props *info, + struct ice_vsi_vlan_info *vlan) +{ + info->sw_flags2 = vlan->sw_flags2; + info->inner_vlan_flags = vlan->inner_vlan_flags; + info->outer_vlan_flags = vlan->outer_vlan_flags; +} + /** * __ice_vsi_set_inner_port_vlan - set port VLAN VSI context settings to enable a port VLAN * @vsi: the VSI to update @@ -218,6 +236,7 @@ static int __ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, u16 pvid_info) if (!ctxt) return -ENOMEM; + ice_save_vlan_info(&vsi->info, &vsi->vlan_info); ctxt->info = vsi->info; info = &ctxt->info; info->inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_TX_MODE_ACCEPTUNTAGGED | @@ -259,6 +278,33 @@ int ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) return __ice_vsi_set_inner_port_vlan(vsi, port_vlan_info); } +int ice_vsi_clear_inner_port_vlan(struct ice_vsi *vsi) +{ + struct ice_hw *hw = &vsi->back->hw; + struct ice_aqc_vsi_props *info; + struct ice_vsi_ctx *ctxt; + int ret; + + ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; + + ice_restore_vlan_info(&vsi->info, &vsi->vlan_info); + vsi->info.port_based_inner_vlan = 0; + ctxt->info = vsi->info; + info = &ctxt->info; + info->valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID | + ICE_AQ_VSI_PROP_SW_VALID); + + ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL); + if (ret) + dev_err(ice_hw_to_dev(hw), "update VSI for port VLAN failed, err %d aq_err %s\n", + ret, ice_aq_str(hw->adminq.sq_last_status)); + + kfree(ctxt); + return ret; +} + /** * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI * @vsi: VSI to enable or disable VLAN pruning on @@ -647,6 +693,7 @@ __ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, u16 vlan_info, u16 tpid) if (!ctxt) return -ENOMEM; + ice_save_vlan_info(&vsi->info, &vsi->vlan_info); ctxt->info = vsi->info; ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; @@ -689,9 +736,6 @@ __ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, u16 vlan_info, u16 tpid) * used if DVM is supported. Also, this function should never be called directly * as it should be part of ice_vsi_vlan_ops if it's needed. * - * This function does not support clearing the port VLAN as there is currently - * no use case for this. - * * Use the ice_vlan structure passed in to set this VSI in a port VLAN. */ int ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) @@ -705,3 +749,37 @@ int ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) return __ice_vsi_set_outer_port_vlan(vsi, port_vlan_info, vlan->tpid); } + +/** + * ice_vsi_clear_outer_port_vlan - clear outer port vlan + * @vsi: VSI to configure + * + * The function is restoring previously set vlan config (saved in + * vsi->vlan_info). Setting happens in port vlan configuration. + */ +int ice_vsi_clear_outer_port_vlan(struct ice_vsi *vsi) +{ + struct ice_hw *hw = &vsi->back->hw; + struct ice_vsi_ctx *ctxt; + int err; + + ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; + + ice_restore_vlan_info(&vsi->info, &vsi->vlan_info); + vsi->info.port_based_outer_vlan = 0; + ctxt->info = vsi->info; + + ctxt->info.valid_sections = + cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID | + ICE_AQ_VSI_PROP_SW_VALID); + + err = ice_update_vsi(hw, vsi->idx, ctxt, NULL); + if (err) + dev_err(ice_pf_to_dev(vsi->back), "update VSI for clearing outer port based VLAN failed, err %d aq_err %s\n", + err, ice_aq_str(hw->adminq.sq_last_status)); + + kfree(ctxt); + return err; +} diff --git a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h index f459909490ec..f0d84d11bd5b 100644 --- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h @@ -7,6 +7,12 @@ #include #include "ice_vlan.h" +struct ice_vsi_vlan_info { + u8 sw_flags2; + u8 inner_vlan_flags; + u8 outer_vlan_flags; +}; + struct ice_vsi; int ice_vsi_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan); @@ -17,6 +23,7 @@ int ice_vsi_dis_inner_stripping(struct ice_vsi *vsi); int ice_vsi_ena_inner_insertion(struct ice_vsi *vsi, u16 tpid); int ice_vsi_dis_inner_insertion(struct ice_vsi *vsi); int ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan); +int ice_vsi_clear_inner_port_vlan(struct ice_vsi *vsi); int ice_vsi_ena_rx_vlan_filtering(struct ice_vsi *vsi); int ice_vsi_dis_rx_vlan_filtering(struct ice_vsi *vsi); @@ -28,5 +35,6 @@ int ice_vsi_dis_outer_stripping(struct ice_vsi *vsi); int ice_vsi_ena_outer_insertion(struct ice_vsi *vsi, u16 tpid); int ice_vsi_dis_outer_insertion(struct ice_vsi *vsi); int ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan); +int ice_vsi_clear_outer_port_vlan(struct ice_vsi *vsi); #endif /* _ICE_VSI_VLAN_LIB_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h index 5b47568f6256..b2d2330dedcb 100644 --- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h +++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h @@ -21,6 +21,7 @@ struct ice_vsi_vlan_ops { int (*ena_tx_filtering)(struct ice_vsi *vsi); int (*dis_tx_filtering)(struct ice_vsi *vsi); int (*set_port_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan); + int (*clear_port_vlan)(struct ice_vsi *vsi); }; void ice_vsi_init_vlan_ops(struct ice_vsi *vsi); -- cgit From e42c6e0c902b34cdbf06a6d80009a0b3c32e3d37 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Wed, 12 Jul 2023 13:03:36 +0200 Subject: ice: implement static version of ageing Remove fdb entries always when ageing time expired. Allow user to set ageing time using port object attribute. Reviewed-by: Simon Horman Signed-off-by: Michal Swiatkowski Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 48 +++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_eswitch_br.h | 10 ++++++ 2 files changed, 58 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 85143ad9eb1d..157f0d01fdb1 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -8,6 +8,8 @@ #include "ice_vlan.h" #include "ice_vf_vsi_vlan_ops.h" +#define ICE_ESW_BRIDGE_UPDATE_INTERVAL msecs_to_jiffies(1000) + static const struct rhashtable_params ice_fdb_ht_params = { .key_offset = offsetof(struct ice_esw_br_fdb_entry, data), .key_len = sizeof(struct ice_esw_br_fdb_data), @@ -406,6 +408,7 @@ ice_eswitch_br_fdb_entry_create(struct net_device *netdev, fdb_entry->br_port = br_port; fdb_entry->flow = flow; fdb_entry->dev = netdev; + fdb_entry->last_use = jiffies; event = SWITCHDEV_FDB_ADD_TO_BRIDGE; if (added_by_user) { @@ -806,6 +809,10 @@ ice_eswitch_br_port_obj_attr_set(struct net_device *netdev, const void *ctx, ice_eswitch_br_vlan_filtering_set(br_port->bridge, attr->u.vlan_filtering); return 0; + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: + br_port->bridge->ageing_time = + clock_t_to_jiffies(attr->u.ageing_time); + return 0; default: return -EOPNOTSUPP; } @@ -977,6 +984,7 @@ ice_eswitch_br_init(struct ice_esw_br_offloads *br_offloads, int ifindex) INIT_LIST_HEAD(&bridge->fdb_list); bridge->br_offloads = br_offloads; bridge->ifindex = ifindex; + bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME); xa_init(&bridge->ports); br_offloads->bridge = bridge; @@ -1172,6 +1180,7 @@ ice_eswitch_br_offloads_deinit(struct ice_pf *pf) if (!br_offloads) return; + cancel_delayed_work_sync(&br_offloads->update_work); unregister_netdevice_notifier(&br_offloads->netdev_nb); unregister_switchdev_blocking_notifier(&br_offloads->switchdev_blk); unregister_switchdev_notifier(&br_offloads->switchdev_nb); @@ -1186,6 +1195,40 @@ ice_eswitch_br_offloads_deinit(struct ice_pf *pf) rtnl_unlock(); } +static void ice_eswitch_br_update(struct ice_esw_br_offloads *br_offloads) +{ + struct ice_esw_br *bridge = br_offloads->bridge; + struct ice_esw_br_fdb_entry *entry, *tmp; + + if (!bridge) + return; + + rtnl_lock(); + list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) { + if (entry->flags & ICE_ESWITCH_BR_FDB_ADDED_BY_USER) + continue; + + if (time_is_after_eq_jiffies(entry->last_use + + bridge->ageing_time)) + continue; + + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, entry); + } + rtnl_unlock(); +} + +static void ice_eswitch_br_update_work(struct work_struct *work) +{ + struct ice_esw_br_offloads *br_offloads; + + br_offloads = ice_work_to_br_offloads(work); + + ice_eswitch_br_update(br_offloads); + + queue_delayed_work(br_offloads->wq, &br_offloads->update_work, + ICE_ESW_BRIDGE_UPDATE_INTERVAL); +} + int ice_eswitch_br_offloads_init(struct ice_pf *pf) { @@ -1234,6 +1277,11 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf) goto err_reg_netdev_nb; } + INIT_DELAYED_WORK(&br_offloads->update_work, + ice_eswitch_br_update_work); + queue_delayed_work(br_offloads->wq, &br_offloads->update_work, + ICE_ESW_BRIDGE_UPDATE_INTERVAL); + return 0; err_reg_netdev_nb: diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h index 978e9ce8e277..85a8fadb2928 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h @@ -5,6 +5,7 @@ #define _ICE_ESWITCH_BR_H_ #include +#include struct ice_esw_br_fdb_data { unsigned char addr[ETH_ALEN]; @@ -30,6 +31,8 @@ struct ice_esw_br_fdb_entry { struct net_device *dev; struct ice_esw_br_port *br_port; struct ice_esw_br_flow *flow; + + unsigned long last_use; }; enum ice_esw_br_port_type { @@ -59,6 +62,7 @@ struct ice_esw_br { int ifindex; u32 flags; + unsigned long ageing_time; }; struct ice_esw_br_offloads { @@ -69,6 +73,7 @@ struct ice_esw_br_offloads { struct notifier_block switchdev_nb; struct workqueue_struct *wq; + struct delayed_work update_work; }; struct ice_esw_br_fdb_work { @@ -88,6 +93,11 @@ struct ice_esw_br_vlan { struct ice_esw_br_offloads, \ nb_name) +#define ice_work_to_br_offloads(w) \ + container_of(w, \ + struct ice_esw_br_offloads, \ + update_work.work) + #define ice_work_to_fdb_work(w) \ container_of(w, \ struct ice_esw_br_fdb_work, \ -- cgit From d129c2a245bfd59035cc661364b056c38f2bf18e Mon Sep 17 00:00:00 2001 From: Pawel Chmielewski Date: Wed, 12 Jul 2023 13:03:37 +0200 Subject: ice: add tracepoints for the switchdev bridge Add tracepoints for the following events: - Add FDB entry - Delete FDB entry - Create bridge VLAN - Cleanup bridge VLAN - Link port to the bridge - Unlink port from the bridge Signed-off-by: Pawel Chmielewski Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 10 +++ drivers/net/ethernet/intel/ice/ice_trace.h | 90 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 157f0d01fdb1..cc7357ed6e5f 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -7,6 +7,7 @@ #include "ice_switch.h" #include "ice_vlan.h" #include "ice_vf_vsi_vlan_ops.h" +#include "ice_trace.h" #define ICE_ESW_BRIDGE_UPDATE_INTERVAL msecs_to_jiffies(1000) @@ -353,6 +354,7 @@ ice_eswitch_br_fdb_entry_find_and_delete(struct ice_esw_br *bridge, return; } + trace_ice_eswitch_br_fdb_entry_find_and_delete(fdb_entry); ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry); } @@ -422,6 +424,7 @@ ice_eswitch_br_fdb_entry_create(struct net_device *netdev, goto err_fdb_insert; list_add(&fdb_entry->list, &bridge->fdb_list); + trace_ice_eswitch_br_fdb_entry_create(fdb_entry); ice_eswitch_br_fdb_offload_notify(netdev, mac, vid, event); @@ -597,6 +600,8 @@ ice_eswitch_br_vlan_cleanup(struct ice_esw_br_port *port, struct ice_esw_br_fdb_entry *fdb_entry, *tmp; struct ice_esw_br *bridge = port->bridge; + trace_ice_eswitch_br_vlan_cleanup(vlan); + list_for_each_entry_safe(fdb_entry, tmp, &bridge->fdb_list, list) { if (vlan->vid == fdb_entry->data.vid) ice_eswitch_br_fdb_entry_delete(bridge, fdb_entry); @@ -686,6 +691,8 @@ ice_eswitch_br_vlan_create(u16 vid, u16 flags, struct ice_esw_br_port *port) if (err) goto err_insert; + trace_ice_eswitch_br_vlan_create(vlan); + return vlan; err_insert: @@ -1047,6 +1054,7 @@ ice_eswitch_br_port_unlink(struct ice_esw_br_offloads *br_offloads, bridge = br_port->bridge; + trace_ice_eswitch_br_port_unlink(br_port); ice_eswitch_br_port_deinit(br_port->bridge, br_port); ice_eswitch_br_verify_deinit(br_offloads, bridge); @@ -1075,10 +1083,12 @@ ice_eswitch_br_port_link(struct ice_esw_br_offloads *br_offloads, struct ice_repr *repr = ice_netdev_to_repr(dev); err = ice_eswitch_br_vf_repr_port_init(bridge, repr); + trace_ice_eswitch_br_port_link(repr->br_port); } else { struct ice_pf *pf = ice_netdev_to_pf(dev); err = ice_eswitch_br_uplink_port_init(bridge, pf); + trace_ice_eswitch_br_port_link(pf->br_port); } if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to init bridge port"); diff --git a/drivers/net/ethernet/intel/ice/ice_trace.h b/drivers/net/ethernet/intel/ice/ice_trace.h index ae98d5a8ff60..b2f5c9fe0149 100644 --- a/drivers/net/ethernet/intel/ice/ice_trace.h +++ b/drivers/net/ethernet/intel/ice/ice_trace.h @@ -21,6 +21,7 @@ #define _ICE_TRACE_H_ #include +#include "ice_eswitch_br.h" /* ice_trace() macro enables shared code to refer to trace points * like: @@ -240,6 +241,95 @@ DEFINE_TX_TSTAMP_OP_EVENT(ice_tx_tstamp_fw_req); DEFINE_TX_TSTAMP_OP_EVENT(ice_tx_tstamp_fw_done); DEFINE_TX_TSTAMP_OP_EVENT(ice_tx_tstamp_complete); +DECLARE_EVENT_CLASS(ice_esw_br_fdb_template, + TP_PROTO(struct ice_esw_br_fdb_entry *fdb), + TP_ARGS(fdb), + TP_STRUCT__entry(__array(char, dev_name, IFNAMSIZ) + __array(unsigned char, addr, ETH_ALEN) + __field(u16, vid) + __field(int, flags)), + TP_fast_assign(strscpy(__entry->dev_name, + netdev_name(fdb->dev), + IFNAMSIZ); + memcpy(__entry->addr, fdb->data.addr, ETH_ALEN); + __entry->vid = fdb->data.vid; + __entry->flags = fdb->flags;), + TP_printk("net_device=%s addr=%pM vid=%u flags=%x", + __entry->dev_name, + __entry->addr, + __entry->vid, + __entry->flags) +); + +DEFINE_EVENT(ice_esw_br_fdb_template, + ice_eswitch_br_fdb_entry_create, + TP_PROTO(struct ice_esw_br_fdb_entry *fdb), + TP_ARGS(fdb) +); + +DEFINE_EVENT(ice_esw_br_fdb_template, + ice_eswitch_br_fdb_entry_find_and_delete, + TP_PROTO(struct ice_esw_br_fdb_entry *fdb), + TP_ARGS(fdb) +); + +DECLARE_EVENT_CLASS(ice_esw_br_vlan_template, + TP_PROTO(struct ice_esw_br_vlan *vlan), + TP_ARGS(vlan), + TP_STRUCT__entry(__field(u16, vid) + __field(u16, flags)), + TP_fast_assign(__entry->vid = vlan->vid; + __entry->flags = vlan->flags;), + TP_printk("vid=%u flags=%x", + __entry->vid, + __entry->flags) +); + +DEFINE_EVENT(ice_esw_br_vlan_template, + ice_eswitch_br_vlan_create, + TP_PROTO(struct ice_esw_br_vlan *vlan), + TP_ARGS(vlan) +); + +DEFINE_EVENT(ice_esw_br_vlan_template, + ice_eswitch_br_vlan_cleanup, + TP_PROTO(struct ice_esw_br_vlan *vlan), + TP_ARGS(vlan) +); + +#define ICE_ESW_BR_PORT_NAME_L 16 + +DECLARE_EVENT_CLASS(ice_esw_br_port_template, + TP_PROTO(struct ice_esw_br_port *port), + TP_ARGS(port), + TP_STRUCT__entry(__field(u16, vport_num) + __array(char, port_type, ICE_ESW_BR_PORT_NAME_L)), + TP_fast_assign(__entry->vport_num = port->vsi_idx; + if (port->type == ICE_ESWITCH_BR_UPLINK_PORT) + strscpy(__entry->port_type, + "Uplink", + ICE_ESW_BR_PORT_NAME_L); + else + strscpy(__entry->port_type, + "VF Representor", + ICE_ESW_BR_PORT_NAME_L);), + TP_printk("vport_num=%u port type=%s", + __entry->vport_num, + __entry->port_type) +); + +DEFINE_EVENT(ice_esw_br_port_template, + ice_eswitch_br_port_link, + TP_PROTO(struct ice_esw_br_port *port), + TP_ARGS(port) +); + +DEFINE_EVENT(ice_esw_br_port_template, + ice_eswitch_br_port_unlink, + TP_PROTO(struct ice_esw_br_port *port), + TP_ARGS(port) +); + /* End tracepoints */ #endif /* _ICE_TRACE_H_ */ -- cgit From 9f64b6e459d3eee73ca4ea6226653e008d1c1e61 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 21 Jul 2023 02:21:44 -0700 Subject: netconsole: Use sysfs_emit() instead of snprintf() According to the sysfs.rst documentation, _show() functions should only use sysfs_emit() instead of snprintf(). Since snprintf() shouldn't be used in the sysfs _show() path, replace it by sysfs_emit(). Suggested-by: Petr Mladek Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230721092146.4036622-1-leitao@debian.org Signed-off-by: Jakub Kicinski --- drivers/net/netconsole.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 31cbe02eda49..a3c53b8c9efc 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -260,32 +260,32 @@ static struct netconsole_target *to_target(struct config_item *item) static ssize_t enabled_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled); + return sysfs_emit(buf, "%d\n", to_target(item)->enabled); } static ssize_t extended_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended); + return sysfs_emit(buf, "%d\n", to_target(item)->extended); } static ssize_t release_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->release); + return sysfs_emit(buf, "%d\n", to_target(item)->release); } static ssize_t dev_name_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name); + return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name); } static ssize_t local_port_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port); + return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port); } static ssize_t remote_port_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port); + return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port); } static ssize_t local_ip_show(struct config_item *item, char *buf) @@ -293,9 +293,9 @@ static ssize_t local_ip_show(struct config_item *item, char *buf) struct netconsole_target *nt = to_target(item); if (nt->np.ipv6) - return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6); + return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6); else - return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip); + return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip); } static ssize_t remote_ip_show(struct config_item *item, char *buf) @@ -303,9 +303,9 @@ static ssize_t remote_ip_show(struct config_item *item, char *buf) struct netconsole_target *nt = to_target(item); if (nt->np.ipv6) - return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6); + return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6); else - return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip); + return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip); } static ssize_t local_mac_show(struct config_item *item, char *buf) @@ -313,12 +313,12 @@ static ssize_t local_mac_show(struct config_item *item, char *buf) struct net_device *dev = to_target(item)->np.dev; static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast); + return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast); } static ssize_t remote_mac_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac); + return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac); } /* -- cgit From 004a04b97bbcbb630421e44aadfe675fe6b4c460 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 21 Jul 2023 02:21:45 -0700 Subject: netconsole: Use kstrtobool() instead of kstrtoint() Replace kstrtoint() by kstrtobool() in the sysfs _store() functions. This improves the user usability and simplify the code. With this fix, it is now possible to use [YyNn] to set and unset a feature. Old behaviour is still unchanged. kstrtobool() is also safer and doesn't need the extra validation that is required when converting a string to bool (end field in the struct), which makes the code simpler. Suggested-by: Petr Mladek Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230721092146.4036622-2-leitao@debian.org Signed-off-by: Jakub Kicinski --- drivers/net/netconsole.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index a3c53b8c9efc..87f18aedd3bd 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -333,17 +333,15 @@ static ssize_t enabled_store(struct config_item *item, { struct netconsole_target *nt = to_target(item); unsigned long flags; - int enabled; + bool enabled; int err; mutex_lock(&dynamic_netconsole_mutex); - err = kstrtoint(buf, 10, &enabled); - if (err < 0) + err = kstrtobool(buf, &enabled); + if (err) goto out_unlock; err = -EINVAL; - if (enabled < 0 || enabled > 1) - goto out_unlock; if ((bool)enabled == nt->enabled) { pr_info("network logging has already %s\n", nt->enabled ? "started" : "stopped"); @@ -394,7 +392,7 @@ static ssize_t release_store(struct config_item *item, const char *buf, size_t count) { struct netconsole_target *nt = to_target(item); - int release; + bool release; int err; mutex_lock(&dynamic_netconsole_mutex); @@ -405,13 +403,9 @@ static ssize_t release_store(struct config_item *item, const char *buf, goto out_unlock; } - err = kstrtoint(buf, 10, &release); - if (err < 0) - goto out_unlock; - if (release < 0 || release > 1) { - err = -EINVAL; + err = kstrtobool(buf, &release); + if (err) goto out_unlock; - } nt->release = release; @@ -426,7 +420,7 @@ static ssize_t extended_store(struct config_item *item, const char *buf, size_t count) { struct netconsole_target *nt = to_target(item); - int extended; + bool extended; int err; mutex_lock(&dynamic_netconsole_mutex); @@ -437,13 +431,9 @@ static ssize_t extended_store(struct config_item *item, const char *buf, goto out_unlock; } - err = kstrtoint(buf, 10, &extended); - if (err < 0) - goto out_unlock; - if (extended < 0 || extended > 1) { - err = -EINVAL; + err = kstrtobool(buf, &extended); + if (err) goto out_unlock; - } nt->extended = extended; -- cgit From ec87f05402f592d27507e1aa6b2fd21c486f2cc0 Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Fri, 21 Jul 2023 10:09:25 +0530 Subject: octeontx2-af: Install TC filter rules in hardware based on priority As of today, hardware does not support installing tc filter rules based on priority. This patch adds support to install the hardware rules based on priority. The final hardware rules will not be dependent on rule installation order, it will be strictly priority based, same as software. Signed-off-by: Suman Ghosh Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230721043925.2627806-1-sumang@marvell.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 9 +- .../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 9 +- .../net/ethernet/marvell/octeontx2/af/rvu_switch.c | 6 +- .../ethernet/marvell/octeontx2/nic/otx2_common.h | 11 +- .../ethernet/marvell/octeontx2/nic/otx2_devlink.c | 1 - .../ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 1 + .../ethernet/marvell/octeontx2/nic/otx2_flows.c | 2 + .../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 320 +++++++++++++++------ 8 files changed, 255 insertions(+), 104 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index eba307eee2b2..ed66c5989102 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -235,7 +235,7 @@ M(NPC_GET_KEX_CFG, 0x600c, npc_get_kex_cfg, \ M(NPC_INSTALL_FLOW, 0x600d, npc_install_flow, \ npc_install_flow_req, npc_install_flow_rsp) \ M(NPC_DELETE_FLOW, 0x600e, npc_delete_flow, \ - npc_delete_flow_req, msg_rsp) \ + npc_delete_flow_req, npc_delete_flow_rsp) \ M(NPC_MCAM_READ_ENTRY, 0x600f, npc_mcam_read_entry, \ npc_mcam_read_entry_req, \ npc_mcam_read_entry_rsp) \ @@ -1491,6 +1491,8 @@ struct npc_install_flow_req { u8 vtag0_op; u16 vtag1_def; u8 vtag1_op; + /* old counter value */ + u16 cntr_val; }; struct npc_install_flow_rsp { @@ -1506,6 +1508,11 @@ struct npc_delete_flow_req { u8 all; /* PF + VFs */ }; +struct npc_delete_flow_rsp { + struct mbox_msghdr hdr; + u16 cntr_val; +}; + struct npc_mcam_read_entry_req { struct mbox_msghdr hdr; u16 entry; /* MCAM entry to read */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 952319453701..9c365cc3e736 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1192,7 +1192,7 @@ find_rule: write_req.enable_entry = (u8)enable; /* if counter is available then clear and use it */ if (req->set_cntr && rule->has_cntr) { - rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), 0x00); + rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val); write_req.set_cntr = 1; write_req.cntr = rule->cntr; } @@ -1407,12 +1407,13 @@ static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule, int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu, struct npc_delete_flow_req *req, - struct msg_rsp *rsp) + struct npc_delete_flow_rsp *rsp) { struct npc_mcam *mcam = &rvu->hw->mcam; struct rvu_npc_mcam_rule *iter, *tmp; u16 pcifunc = req->hdr.pcifunc; struct list_head del_list; + int blkaddr; INIT_LIST_HEAD(&del_list); @@ -1428,6 +1429,10 @@ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu, list_move_tail(&iter->list, &del_list); /* single rule */ } else if (req->entry == iter->entry) { + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr) + rsp->cntr_val = rvu_read64(rvu, blkaddr, + NPC_AF_MATCH_STATX(iter->cntr)); list_move_tail(&iter->list, &del_list); break; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c index 592b317f4637..854045ed3b06 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c @@ -158,6 +158,7 @@ void rvu_switch_enable(struct rvu *rvu) struct npc_mcam_alloc_entry_req alloc_req = { 0 }; struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 }; struct npc_delete_flow_req uninstall_req = { 0 }; + struct npc_delete_flow_rsp uninstall_rsp = { 0 }; struct npc_mcam_free_entry_req free_req = { 0 }; struct rvu_switch *rswitch = &rvu->rswitch; struct msg_rsp rsp; @@ -197,7 +198,7 @@ void rvu_switch_enable(struct rvu *rvu) uninstall_rules: uninstall_req.start = rswitch->start_entry; uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1; - rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp); + rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp); kfree(rswitch->entry2pcifunc); free_entries: free_req.all = 1; @@ -209,6 +210,7 @@ exit: void rvu_switch_disable(struct rvu *rvu) { struct npc_delete_flow_req uninstall_req = { 0 }; + struct npc_delete_flow_rsp uninstall_rsp = { 0 }; struct npc_mcam_free_entry_req free_req = { 0 }; struct rvu_switch *rswitch = &rvu->rswitch; struct rvu_hwinfo *hw = rvu->hw; @@ -250,7 +252,7 @@ void rvu_switch_disable(struct rvu *rvu) uninstall_req.start = rswitch->start_entry; uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1; free_req.all = 1; - rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp); + rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp); rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); rswitch->used_entries = 0; kfree(rswitch->entry2pcifunc); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 37d792f18809..25e99fd2e3fd 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -361,13 +361,8 @@ struct otx2_flow_config { struct list_head flow_list; u32 dmacflt_max_flows; u16 max_flows; -}; - -struct otx2_tc_info { - /* hash table to store TC offloaded flows */ - struct rhashtable flow_table; - struct rhashtable_params flow_ht_params; - unsigned long *tc_entries_bitmap; + struct list_head flow_list_tc; + bool ntuple; }; struct dev_hw_ops { @@ -492,7 +487,6 @@ struct otx2_nic { /* NPC MCAM */ struct otx2_flow_config *flow_cfg; struct otx2_mac_table *mac_table; - struct otx2_tc_info tc_info; u64 reset_count; struct work_struct reset_task; @@ -1064,7 +1058,6 @@ int otx2_init_tc(struct otx2_nic *nic); void otx2_shutdown_tc(struct otx2_nic *nic); int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, void *type_data); -int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic); /* CGX/RPM DMAC filters support */ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf); int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c index 63ef7c41d18d..4e1130496573 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c @@ -41,7 +41,6 @@ static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id, return 0; otx2_alloc_mcam_entries(pfvf, ctx->val.vu16); - otx2_tc_alloc_ent_bitmap(pfvf); return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index c47d91da32dc..9efcec549834 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -764,6 +764,7 @@ static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc) struct otx2_nic *pfvf = netdev_priv(dev); int ret = -EOPNOTSUPP; + pfvf->flow_cfg->ntuple = ntuple; switch (nfc->cmd) { case ETHTOOL_SRXFH: ret = otx2_set_rss_hash_opts(pfvf, nfc); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 2d7713a1a153..4762dbea64a1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -276,6 +276,7 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf) flow_cfg = pfvf->flow_cfg; INIT_LIST_HEAD(&flow_cfg->flow_list); + INIT_LIST_HEAD(&flow_cfg->flow_list_tc); flow_cfg->max_flows = 0; return 0; @@ -298,6 +299,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf) return -ENOMEM; INIT_LIST_HEAD(&pf->flow_cfg->flow_list); + INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc); /* Allocate bare minimum number of MCAM entries needed for * unicast and ntuple filters. diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 5e56b6c3e60a..1e6fc23eca4f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -34,9 +34,8 @@ struct otx2_tc_flow_stats { }; struct otx2_tc_flow { - struct rhash_head node; + struct list_head list; unsigned long cookie; - unsigned int bitpos; struct rcu_head rcu; struct otx2_tc_flow_stats stats; spinlock_t lock; /* lock for stats */ @@ -44,31 +43,10 @@ struct otx2_tc_flow { u16 entry; u16 leaf_profile; bool is_act_police; + u32 prio; + struct npc_install_flow_req req; }; -int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic) -{ - struct otx2_tc_info *tc = &nic->tc_info; - - if (!nic->flow_cfg->max_flows) - return 0; - - /* Max flows changed, free the existing bitmap */ - kfree(tc->tc_entries_bitmap); - - tc->tc_entries_bitmap = - kcalloc(BITS_TO_LONGS(nic->flow_cfg->max_flows), - sizeof(long), GFP_KERNEL); - if (!tc->tc_entries_bitmap) { - netdev_err(nic->netdev, - "Unable to alloc TC flow entries bitmap\n"); - return -ENOMEM; - } - - return 0; -} -EXPORT_SYMBOL(otx2_tc_alloc_ent_bitmap); - static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, u32 *burst_exp, u32 *burst_mantissa) { @@ -707,8 +685,117 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, return otx2_tc_parse_actions(nic, &rule->action, req, f, node); } -static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry) +static void otx2_destroy_tc_flow_list(struct otx2_nic *pfvf) +{ + struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; + struct otx2_tc_flow *iter, *tmp; + + if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC)) + return; + + list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list_tc, list) { + list_del(&iter->list); + kfree(iter); + flow_cfg->nr_flows--; + } +} + +static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg, + unsigned long cookie) +{ + struct otx2_tc_flow *tmp; + + list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) { + if (tmp->cookie == cookie) + return tmp; + } + + return NULL; +} + +static struct otx2_tc_flow *otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, + int index) { + struct otx2_tc_flow *tmp; + int i = 0; + + list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) { + if (i == index) + return tmp; + i++; + } + + return NULL; +} + +static void otx2_tc_del_from_flow_list(struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct list_head *pos, *n; + struct otx2_tc_flow *tmp; + + list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) { + tmp = list_entry(pos, struct otx2_tc_flow, list); + if (node == tmp) { + list_del(&node->list); + return; + } + } +} + +static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct list_head *pos, *n; + struct otx2_tc_flow *tmp; + int index = 0; + + /* If the flow list is empty then add the new node */ + if (list_empty(&flow_cfg->flow_list_tc)) { + list_add(&node->list, &flow_cfg->flow_list_tc); + return index; + } + + list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) { + tmp = list_entry(pos, struct otx2_tc_flow, list); + if (node->prio < tmp->prio) + break; + index++; + } + + list_add(&node->list, pos->prev); + return index; +} + +static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_install_flow_req *req) +{ + struct npc_install_flow_req *tmp_req; + int err; + + mutex_lock(&nic->mbox.lock); + tmp_req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); + if (!tmp_req) { + mutex_unlock(&nic->mbox.lock); + return -ENOMEM; + } + + memcpy(tmp_req, req, sizeof(struct npc_install_flow_req)); + /* Send message to AF */ + err = otx2_sync_mbox_msg(&nic->mbox); + if (err) { + netdev_err(nic->netdev, "Failed to install MCAM flow entry %d\n", + req->entry); + mutex_unlock(&nic->mbox.lock); + return -EFAULT; + } + + mutex_unlock(&nic->mbox.lock); + return 0; +} + +static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val) +{ + struct npc_delete_flow_rsp *rsp; struct npc_delete_flow_req *req; int err; @@ -729,22 +816,113 @@ static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry) mutex_unlock(&nic->mbox.lock); return -EFAULT; } + + if (cntr_val) { + rsp = (struct npc_delete_flow_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, + 0, &req->hdr); + if (IS_ERR(rsp)) { + netdev_err(nic->netdev, "Failed to get MCAM delete response for entry %d\n", + entry); + mutex_unlock(&nic->mbox.lock); + return -EFAULT; + } + + *cntr_val = rsp->cntr_val; + } + mutex_unlock(&nic->mbox.lock); + return 0; +} + +static int otx2_tc_update_mcam_table_del_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct list_head *pos, *n; + struct otx2_tc_flow *tmp; + int i = 0, index = 0; + u16 cntr_val; + + /* Find and delete the entry from the list and re-install + * all the entries from beginning to the index of the + * deleted entry to higher mcam indexes. + */ + list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) { + tmp = list_entry(pos, struct otx2_tc_flow, list); + if (node == tmp) { + list_del(&tmp->list); + break; + } + + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); + tmp->entry++; + tmp->req.entry = tmp->entry; + tmp->req.cntr_val = cntr_val; + index++; + } + + list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) { + if (i == index) + break; + + tmp = list_entry(pos, struct otx2_tc_flow, list); + otx2_add_mcam_flow_entry(nic, &tmp->req); + i++; + } return 0; } +static int otx2_tc_update_mcam_table_add_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + int mcam_idx = flow_cfg->max_flows - flow_cfg->nr_flows - 1; + struct otx2_tc_flow *tmp; + int list_idx, i; + u16 cntr_val; + + /* Find the index of the entry(list_idx) whose priority + * is greater than the new entry and re-install all + * the entries from beginning to list_idx to higher + * mcam indexes. + */ + list_idx = otx2_tc_add_to_flow_list(flow_cfg, node); + for (i = 0; i < list_idx; i++) { + tmp = otx2_tc_get_entry_by_index(flow_cfg, i); + if (!tmp) + return -ENOMEM; + + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); + tmp->entry = flow_cfg->flow_ent[mcam_idx]; + tmp->req.entry = tmp->entry; + tmp->req.cntr_val = cntr_val; + otx2_add_mcam_flow_entry(nic, &tmp->req); + mcam_idx++; + } + + return mcam_idx; +} + +static int otx2_tc_update_mcam_table(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node, + bool add_req) +{ + if (add_req) + return otx2_tc_update_mcam_table_add_req(nic, flow_cfg, node); + + return otx2_tc_update_mcam_table_del_req(nic, flow_cfg, node); +} + static int otx2_tc_del_flow(struct otx2_nic *nic, struct flow_cls_offload *tc_flow_cmd) { struct otx2_flow_config *flow_cfg = nic->flow_cfg; - struct otx2_tc_info *tc_info = &nic->tc_info; struct otx2_tc_flow *flow_node; int err; - flow_node = rhashtable_lookup_fast(&tc_info->flow_table, - &tc_flow_cmd->cookie, - tc_info->flow_ht_params); + flow_node = otx2_tc_get_entry_by_cookie(flow_cfg, tc_flow_cmd->cookie); if (!flow_node) { netdev_err(nic->netdev, "tc flow not found for cookie 0x%lx\n", tc_flow_cmd->cookie); @@ -772,16 +950,10 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, mutex_unlock(&nic->mbox.lock); } - otx2_del_mcam_flow_entry(nic, flow_node->entry); - - WARN_ON(rhashtable_remove_fast(&nic->tc_info.flow_table, - &flow_node->node, - nic->tc_info.flow_ht_params)); + otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); + otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); kfree_rcu(flow_node, rcu); - - clear_bit(flow_node->bitpos, tc_info->tc_entries_bitmap); flow_cfg->nr_flows--; - return 0; } @@ -790,15 +962,14 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, { struct netlink_ext_ack *extack = tc_flow_cmd->common.extack; struct otx2_flow_config *flow_cfg = nic->flow_cfg; - struct otx2_tc_info *tc_info = &nic->tc_info; struct otx2_tc_flow *new_node, *old_node; struct npc_install_flow_req *req, dummy; - int rc, err; + int rc, err, mcam_idx; if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)) return -ENOMEM; - if (bitmap_full(tc_info->tc_entries_bitmap, flow_cfg->max_flows)) { + if (flow_cfg->nr_flows == flow_cfg->max_flows) { NL_SET_ERR_MSG_MOD(extack, "Free MCAM entry not available to add the flow"); return -ENOMEM; @@ -810,6 +981,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, return -ENOMEM; spin_lock_init(&new_node->lock); new_node->cookie = tc_flow_cmd->cookie; + new_node->prio = tc_flow_cmd->common.prio; memset(&dummy, 0, sizeof(struct npc_install_flow_req)); @@ -820,12 +992,11 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, } /* If a flow exists with the same cookie, delete it */ - old_node = rhashtable_lookup_fast(&tc_info->flow_table, - &tc_flow_cmd->cookie, - tc_info->flow_ht_params); + old_node = otx2_tc_get_entry_by_cookie(flow_cfg, tc_flow_cmd->cookie); if (old_node) otx2_tc_del_flow(nic, tc_flow_cmd); + mcam_idx = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true); mutex_lock(&nic->mbox.lock); req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); if (!req) { @@ -836,11 +1007,8 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr)); memcpy(req, &dummy, sizeof(struct npc_install_flow_req)); - - new_node->bitpos = find_first_zero_bit(tc_info->tc_entries_bitmap, - flow_cfg->max_flows); req->channel = nic->hw.rx_chan_base; - req->entry = flow_cfg->flow_ent[flow_cfg->max_flows - new_node->bitpos - 1]; + req->entry = flow_cfg->flow_ent[mcam_idx]; req->intf = NIX_INTF_RX; req->set_cntr = 1; new_node->entry = req->entry; @@ -850,26 +1018,18 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to install MCAM flow entry"); mutex_unlock(&nic->mbox.lock); - kfree_rcu(new_node, rcu); goto free_leaf; } - mutex_unlock(&nic->mbox.lock); - /* add new flow to flow-table */ - rc = rhashtable_insert_fast(&nic->tc_info.flow_table, &new_node->node, - nic->tc_info.flow_ht_params); - if (rc) { - otx2_del_mcam_flow_entry(nic, req->entry); - kfree_rcu(new_node, rcu); - goto free_leaf; - } + mutex_unlock(&nic->mbox.lock); + memcpy(&new_node->req, req, sizeof(struct npc_install_flow_req)); - set_bit(new_node->bitpos, tc_info->tc_entries_bitmap); flow_cfg->nr_flows++; - return 0; free_leaf: + otx2_tc_del_from_flow_list(flow_cfg, new_node); + kfree_rcu(new_node, rcu); if (new_node->is_act_police) { mutex_lock(&nic->mbox.lock); @@ -896,16 +1056,13 @@ free_leaf: static int otx2_tc_get_flow_stats(struct otx2_nic *nic, struct flow_cls_offload *tc_flow_cmd) { - struct otx2_tc_info *tc_info = &nic->tc_info; struct npc_mcam_get_stats_req *req; struct npc_mcam_get_stats_rsp *rsp; struct otx2_tc_flow_stats *stats; struct otx2_tc_flow *flow_node; int err; - flow_node = rhashtable_lookup_fast(&tc_info->flow_table, - &tc_flow_cmd->cookie, - tc_info->flow_ht_params); + flow_node = otx2_tc_get_entry_by_cookie(nic->flow_cfg, tc_flow_cmd->cookie); if (!flow_node) { netdev_info(nic->netdev, "tc flow not found for cookie %lx", tc_flow_cmd->cookie); @@ -1053,12 +1210,20 @@ static int otx2_setup_tc_block_ingress_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { struct otx2_nic *nic = cb_priv; + bool ntuple; if (!tc_cls_can_offload_and_chain0(nic->netdev, type_data)) return -EOPNOTSUPP; + ntuple = nic->netdev->features & NETIF_F_NTUPLE; switch (type) { case TC_SETUP_CLSFLOWER: + if (ntuple) { + netdev_warn(nic->netdev, + "Can't install TC flower offload rule when NTUPLE is active"); + return -EOPNOTSUPP; + } + return otx2_setup_tc_cls_flower(nic, type_data); case TC_SETUP_CLSMATCHALL: return otx2_setup_tc_ingress_matchall(nic, type_data); @@ -1143,18 +1308,8 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, } EXPORT_SYMBOL(otx2_setup_tc); -static const struct rhashtable_params tc_flow_ht_params = { - .head_offset = offsetof(struct otx2_tc_flow, node), - .key_offset = offsetof(struct otx2_tc_flow, cookie), - .key_len = sizeof(((struct otx2_tc_flow *)0)->cookie), - .automatic_shrinking = true, -}; - int otx2_init_tc(struct otx2_nic *nic) { - struct otx2_tc_info *tc = &nic->tc_info; - int err; - /* Exclude receive queue 0 being used for police action */ set_bit(0, &nic->rq_bmap); @@ -1164,25 +1319,12 @@ int otx2_init_tc(struct otx2_nic *nic) return -EINVAL; } - err = otx2_tc_alloc_ent_bitmap(nic); - if (err) - return err; - - tc->flow_ht_params = tc_flow_ht_params; - err = rhashtable_init(&tc->flow_table, &tc->flow_ht_params); - if (err) { - kfree(tc->tc_entries_bitmap); - tc->tc_entries_bitmap = NULL; - } - return err; + return 0; } EXPORT_SYMBOL(otx2_init_tc); void otx2_shutdown_tc(struct otx2_nic *nic) { - struct otx2_tc_info *tc = &nic->tc_info; - - kfree(tc->tc_entries_bitmap); - rhashtable_destroy(&tc->flow_table); + otx2_destroy_tc_flow_list(nic); } EXPORT_SYMBOL(otx2_shutdown_tc); -- cgit From 76a4cb755cf911ad5acdb82f7228a9e22addf52b Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 22 Jul 2023 21:32:49 +0100 Subject: net: ethernet: mtk_eth_soc: remove incorrect PLL configuration MT7623 GMAC0 attempts to configure the system clocking according to the required speed in the .mac_config callback for non-SGMII, non-baseX and non-TRGMII modes. state->speed setting has never been reliable in the .mac_config callback - there are cases where this is not the link speed, particularly via ethtool paths, so this has always been unreliable (as detailed in phylink's documentation.) There is the additional issue that mtk_gmac0_rgmii_adjust() will only be called if state->interface changes, which means it only configures the system clocking on the very first .mac_config call, which will be made when the network device is first brought up before any link is established. Essentially, this code is incredibly buggy, and probably never worked. Moreover, checking the in-kernel DT files, it seems no platform makes use of this code path. Therefore, let's remove it, and disable interface modes for port 0 that are not SGMII, 1000base-X, 2500base-X or TRGMII on the MT7623. Reviewed-by: Daniel Golle Tested-by: Daniel Golle Tested-by: Frank Wunderlich Signed-off-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 59 ++++++++--------------------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + 2 files changed, 17 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 18a8aca7944d..fe8b7e38decc 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -385,10 +385,8 @@ static int mt7621_gmac0_rgmii_adjust(struct mtk_eth *eth, } static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, - phy_interface_t interface, int speed) + phy_interface_t interface) { - unsigned long rate; - u32 tck, rck, intf; int ret; if (interface == PHY_INTERFACE_MODE_TRGMII) { @@ -399,30 +397,7 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, return; } - if (speed == SPEED_1000) { - intf = INTF_MODE_RGMII_1000; - rate = 250000000; - rck = RCK_CTRL_RGMII_1000; - tck = TCK_CTRL_RGMII_1000; - } else { - intf = INTF_MODE_RGMII_10_100; - rate = 500000000; - rck = RCK_CTRL_RGMII_10_100; - tck = TCK_CTRL_RGMII_10_100; - } - - mtk_w32(eth, intf, INTF_MODE); - - regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0, - ETHSYS_TRGMII_CLK_SEL362_5, - ETHSYS_TRGMII_CLK_SEL362_5); - - ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], rate); - if (ret) - dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret); - - mtk_w32(eth, rck, TRGMII_RCK_CTRL); - mtk_w32(eth, tck, TRGMII_TCK_CTRL); + dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); } static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, @@ -498,17 +473,8 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, state->interface)) goto err_phy; } else { - /* FIXME: this is incorrect. Not only does it - * use state->speed (which is not guaranteed - * to be correct) but it also makes use of it - * in a code path that will only be reachable - * when the PHY interface mode changes, not - * when the speed changes. Consequently, RGMII - * is probably broken. - */ mtk_gmac0_rgmii_adjust(mac->hw, - state->interface, - state->speed); + state->interface); /* mt7623_pad_clk_setup */ for (i = 0 ; i < NUM_TRGMII_CTRL; i++) @@ -4366,13 +4332,19 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; - __set_bit(PHY_INTERFACE_MODE_MII, - mac->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_GMII, - mac->phylink_config.supported_interfaces); + /* MT7623 gmac0 is now missing its speed-specific PLL configuration + * in its .mac_config method (since state->speed is not valid there. + * Disable support for MII, GMII and RGMII. + */ + if (!mac->hw->soc->disable_pll_modes || mac->id != 0) { + __set_bit(PHY_INTERFACE_MODE_MII, + mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_GMII, + mac->phylink_config.supported_interfaces); - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) - phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) + phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); + } if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) __set_bit(PHY_INTERFACE_MODE_TRGMII, @@ -4845,6 +4817,7 @@ static const struct mtk_soc_data mt7623_data = { .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 707445f6bcb1..28adda0c90c0 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -1030,6 +1030,7 @@ struct mtk_soc_data { u16 foe_entry_size; netdev_features_t hw_features; bool has_accounting; + bool disable_pll_modes; struct { u32 txd_size; u32 rxd_size; -- cgit From 28e1737d2544536c23fc71d3a7f24ce8c9f08eb1 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 22 Jul 2023 21:32:54 +0100 Subject: net: ethernet: mtk_eth_soc: remove mac_pcs_get_state and modernise Remove the .mac_pcs_get_state function, since as far as I can tell is never called - no DT appears to specify an in-band-status management nor SFP support for this driver. Removal of this, along with the previous patch to remove the incorrect clocking configuration, means that the driver becomes non-legacy, so we can remove the "legacy_pre_march2020" status from this driver. Reviewed-by: Daniel Golle Tested-by: Daniel Golle Tested-by: Frank Wunderlich Signed-off-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 ----------------------------- 1 file changed, 35 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index fe8b7e38decc..7490d48000c2 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -568,38 +568,6 @@ static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, return 0; } -static void mtk_mac_pcs_get_state(struct phylink_config *config, - struct phylink_link_state *state) -{ - struct mtk_mac *mac = container_of(config, struct mtk_mac, - phylink_config); - u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id)); - - state->link = (pmsr & MAC_MSR_LINK); - state->duplex = (pmsr & MAC_MSR_DPX) >> 1; - - switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) { - case 0: - state->speed = SPEED_10; - break; - case MAC_MSR_SPEED_100: - state->speed = SPEED_100; - break; - case MAC_MSR_SPEED_1000: - state->speed = SPEED_1000; - break; - default: - state->speed = SPEED_UNKNOWN; - break; - } - - state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); - if (pmsr & MAC_MSR_RX_FC) - state->pause |= MLO_PAUSE_RX; - if (pmsr & MAC_MSR_TX_FC) - state->pause |= MLO_PAUSE_TX; -} - static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface) { @@ -722,7 +690,6 @@ static void mtk_mac_link_up(struct phylink_config *config, static const struct phylink_mac_ops mtk_phylink_ops = { .mac_select_pcs = mtk_mac_select_pcs, - .mac_pcs_get_state = mtk_mac_pcs_get_state, .mac_config = mtk_mac_config, .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, @@ -4327,8 +4294,6 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->phylink_config.dev = ð->netdev[id]->dev; mac->phylink_config.type = PHYLINK_NETDEV; - /* This driver makes use of state->speed in mac_config */ - mac->phylink_config.legacy_pre_march2020 = true; mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; -- cgit From 4d72c3bb60dd9d5ea180f157bac72b4458112282 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 22 Jul 2023 21:32:59 +0100 Subject: net: phylink: strip out pre-March 2020 legacy code Strip out all the pre-March 2020 legacy code from phylink now that the last user of it is gone. Reviewed-by: Daniel Golle Tested-by: Daniel Golle Tested-by: Frank Wunderlich Signed-off-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/phy/phylink.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index f07e496319b4..df413fb15088 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1198,13 +1198,6 @@ static int phylink_change_inband_advert(struct phylink *pl) if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) return 0; - if (!pl->pcs && pl->config->legacy_pre_march2020) { - /* Legacy method */ - phylink_mac_config(pl, &pl->link_config); - phylink_pcs_an_restart(pl); - return 0; - } - phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__, phylink_an_mode_str(pl->cur_link_an_mode), phy_modes(pl->link_config.interface), @@ -1257,9 +1250,6 @@ static void phylink_mac_pcs_get_state(struct phylink *pl, if (pl->pcs) pl->pcs->ops->pcs_get_state(pl->pcs, state); - else if (pl->mac_ops->mac_pcs_get_state && - pl->config->legacy_pre_march2020) - pl->mac_ops->mac_pcs_get_state(pl->config, state); else state->link = 0; } @@ -1492,13 +1482,6 @@ static void phylink_resolve(struct work_struct *w) } phylink_major_config(pl, false, &link_state); pl->link_config.interface = link_state.interface; - } else if (!pl->pcs && pl->config->legacy_pre_march2020) { - /* The interface remains unchanged, only the speed, - * duplex or pause settings have changed. Call the - * old mac_config() method to configure the MAC/PCS - * only if we do not have a legacy MAC driver. - */ - phylink_mac_config(pl, &link_state); } } @@ -3513,7 +3496,7 @@ static void phylink_decode_usgmii_word(struct phylink_link_state *state, * * Parse the Clause 37 or Cisco SGMII link partner negotiation word into * the phylink @state structure. This is suitable to be used for implementing - * the mac_pcs_get_state() member of the struct phylink_mac_ops structure if + * the pcs_get_state() member of the struct phylink_pcs_ops structure if * accessing @bmsr and @lpa cannot be done with MDIO directly. */ void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, @@ -3563,7 +3546,7 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_decode_state); * Read the MAC PCS state from the MII device configured in @config and * parse the Clause 37 or Cisco SGMII link partner negotiation word into * the phylink @state structure. This is suitable to be directly plugged - * into the mac_pcs_get_state() member of the struct phylink_mac_ops + * into the pcs_get_state() member of the struct phylink_pcs_ops * structure. */ void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, @@ -3674,8 +3657,8 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_config); * clause 37 negotiation. * * Restart the clause 37 negotiation with the link partner. This is - * suitable to be directly plugged into the mac_pcs_get_state() member - * of the struct phylink_mac_ops structure. + * suitable to be directly plugged into the pcs_get_state() member + * of the struct phylink_pcs_ops structure. */ void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs) { -- cgit From c5714f68a76bcad3d2dbaafc5a7e98096f3b4c75 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 22 Jul 2023 21:33:05 +0100 Subject: net: phylink: explicitly invalidate link_state members in mac_config Explicitly invalidate the phylink_link_state structure members in mac_config that do not contain reliable information for this function, thereby preventing their future incorrect use. Reviewed-by: Daniel Golle Tested-by: Daniel Golle Tested-by: Frank Wunderlich Signed-off-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/phy/phylink.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index df413fb15088..4f1c8bb199e9 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1066,17 +1066,24 @@ static void phylink_pcs_poll_start(struct phylink *pl) static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { + struct phylink_link_state st = *state; + + /* Stop drivers incorrectly using these */ + linkmode_zero(st.lp_advertising); + st.speed = SPEED_UNKNOWN; + st.duplex = DUPLEX_UNKNOWN; + st.an_complete = false; + st.link = false; + phylink_dbg(pl, - "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u\n", + "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n", __func__, phylink_an_mode_str(pl->cur_link_an_mode), - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), - phy_rate_matching_to_str(state->rate_matching), - __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, - state->pause, state->link); - - pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); + phy_modes(st.interface), + phy_rate_matching_to_str(st.rate_matching), + __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising, + st.pause); + + pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st); } static void phylink_pcs_an_restart(struct phylink *pl) -- cgit From 4acea83a849a04c4b88bf2ee7bcecfcc2f502a24 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Wed, 19 Jul 2023 12:26:54 +0300 Subject: net/mlx5e: Check for IPsec NAT-T support Set relevant IPsec capability to indicate if flow steering supports UDP encapsulation and decapsulation of IPsec ESP packets. Signed-off-by: Leon Romanovsky Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index 4e9887171508..b382b0cad7f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -110,6 +110,7 @@ enum mlx5_ipsec_cap { MLX5_IPSEC_CAP_ROCE = 1 << 3, MLX5_IPSEC_CAP_PRIO = 1 << 4, MLX5_IPSEC_CAP_TUNNEL = 1 << 5, + MLX5_IPSEC_CAP_ESPINUDP = 1 << 6, }; struct mlx5e_priv; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index a3554bde3e07..5ff06263c5bd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -54,6 +54,12 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_l3_esp_tunnel_to_l2)) caps |= MLX5_IPSEC_CAP_TUNNEL; + + if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, + reformat_add_esp_transport_over_udp) && + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + reformat_del_esp_transport_over_udp)) + caps |= MLX5_IPSEC_CAP_ESPINUDP; } if (mlx5_get_roce_state(mdev) && -- cgit From d65954934937f1509501ffdd7e0201b37638d2e1 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Wed, 19 Jul 2023 12:26:55 +0300 Subject: net/mlx5e: Support IPsec NAT-T functionality Extend mlx5 IPsec packet offload to support UDP encapsulation of IPsec ESP packets. Signed-off-by: Leon Romanovsky Signed-off-by: Paolo Abeni --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 27 +++++++++- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 11 +++- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 61 +++++++++++++++++----- 3 files changed, 81 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 891d39b4bfd4..658b7d8d50c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -354,6 +354,12 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, mlx5e_ipsec_init_limits(sa_entry, attrs); mlx5e_ipsec_init_macs(sa_entry, attrs); + + if (x->encap) { + attrs->encap = true; + attrs->sport = x->encap->encap_sport; + attrs->dport = x->encap->encap_dport; + } } static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, @@ -387,8 +393,25 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, return -EINVAL; } if (x->encap) { - NL_SET_ERR_MSG_MOD(extack, "Encapsulated xfrm state may not be offloaded"); - return -EINVAL; + if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ESPINUDP)) { + NL_SET_ERR_MSG_MOD(extack, "Encapsulation is not supported"); + return -EINVAL; + } + + if (x->encap->encap_type != UDP_ENCAP_ESPINUDP) { + NL_SET_ERR_MSG_MOD(extack, "Encapsulation other than UDP is not supported"); + return -EINVAL; + } + + if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) { + NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in packet offload mode only"); + return -EINVAL; + } + + if (x->props.mode != XFRM_MODE_TRANSPORT) { + NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in transport mode only"); + return -EINVAL; + } } if (!x->aead) { NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states without aead"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index b382b0cad7f6..7a7047263618 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -94,13 +94,20 @@ struct mlx5_accel_esp_xfrm_attrs { u8 dir : 2; u8 type : 2; u8 drop : 1; + u8 encap : 1; u8 family; struct mlx5_replay_esn replay_esn; u32 authsize; u32 reqid; struct mlx5_ipsec_lft lft; - u8 smac[ETH_ALEN]; - u8 dmac[ETH_ALEN]; + union { + u8 smac[ETH_ALEN]; + __be16 sport; + }; + union { + u8 dmac[ETH_ALEN]; + __be16 dport; + }; }; enum mlx5_ipsec_cap { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index dbe87bf89c0d..47baf983147f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -951,37 +951,70 @@ free_reformatbf: return -EINVAL; } +static int get_reformat_type(struct mlx5_accel_esp_xfrm_attrs *attrs) +{ + switch (attrs->dir) { + case XFRM_DEV_OFFLOAD_IN: + if (attrs->encap) + return MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT_OVER_UDP; + return MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT; + case XFRM_DEV_OFFLOAD_OUT: + if (attrs->family == AF_INET) { + if (attrs->encap) + return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_UDPV4; + return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4; + } + + if (attrs->encap) + return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_UDPV6; + return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6; + default: + WARN_ON(true); + } + + return -EINVAL; +} + static int setup_pkt_transport_reformat(struct mlx5_accel_esp_xfrm_attrs *attrs, struct mlx5_pkt_reformat_params *reformat_params) { - u8 *reformatbf; + struct udphdr *udphdr; + char *reformatbf; + size_t bfflen; __be32 spi; + void *hdr; + + reformat_params->type = get_reformat_type(attrs); + if (reformat_params->type < 0) + return reformat_params->type; switch (attrs->dir) { case XFRM_DEV_OFFLOAD_IN: - reformat_params->type = MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT; break; case XFRM_DEV_OFFLOAD_OUT: - if (attrs->family == AF_INET) - reformat_params->type = - MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4; - else - reformat_params->type = - MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6; - - reformatbf = kzalloc(MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE, - GFP_KERNEL); + bfflen = MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE; + if (attrs->encap) + bfflen += sizeof(*udphdr); + + reformatbf = kzalloc(bfflen, GFP_KERNEL); if (!reformatbf) return -ENOMEM; + hdr = reformatbf; + if (attrs->encap) { + udphdr = (struct udphdr *)reformatbf; + udphdr->source = attrs->sport; + udphdr->dest = attrs->dport; + hdr += sizeof(*udphdr); + } + /* convert to network format */ spi = htonl(attrs->spi); - memcpy(reformatbf, &spi, sizeof(spi)); + memcpy(hdr, &spi, sizeof(spi)); reformat_params->param_0 = attrs->authsize; - reformat_params->size = - MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE; + reformat_params->size = bfflen; reformat_params->data = reformatbf; break; default: -- cgit From 90f2ba4896e289ba7973a5349cbad4463c97e321 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 24 Jul 2023 13:11:07 +0300 Subject: wifi: ath9k: avoid using uninitialized array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 'ath_tx_count_frames()', 'ba' array may be used uninitialized, so add 'memset()' call similar to one used in 'ath_tx_complete_aggr()'. Signed-off-by: Dmitry Antipov Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230620080855.396851-1-dmantipov@yandex.ru --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f6f2ab7a63ff..8babaaacacf5 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -466,6 +466,8 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, *nframes = 0; isaggr = bf_isaggr(bf); + memset(ba, 0, WME_BA_BMP_SIZE >> 3); + if (isaggr) { seq_st = ts->ts_seqnum; memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); -- cgit From 810e41cebb6c6e394f2068f839e1a3fc745a5dcc Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 24 Jul 2023 13:11:07 +0300 Subject: wifi: ath9k: fix fortify warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y, I've noticed the following: In function ‘fortify_memcpy_chk’, inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:556:4, inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3: ./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 529 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In function ‘fortify_memcpy_chk’, inlined from ‘ath_tx_count_frames’ at drivers/net/wireless/ath/ath9k/xmit.c:473:3, inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:572:2, inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3: ./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 529 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In both cases, the compiler complains on: memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); which is the legal way to copy both 'ba_low' and following 'ba_high' members of 'struct ath_tx_status' at once (that is, issue one 8-byte 'memcpy()' for two 4-byte fields). Since the fortification logic seems interprets this trick as an attempt to overread 4-byte 'ba_low', silence relevant warnings by using the convenient 'struct_group()' quirk. Suggested-by: Johannes Berg Signed-off-by: Dmitry Antipov Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230620080855.396851-2-dmantipov@yandex.ru --- drivers/net/wireless/ath/ath9k/mac.h | 6 ++++-- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index af44b33814dd..f03d792732da 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -115,8 +115,10 @@ struct ath_tx_status { u8 qid; u16 desc_id; u8 tid; - u32 ba_low; - u32 ba_high; + struct_group(ba, + u32 ba_low; + u32 ba_high; + ); u32 evm0; u32 evm1; u32 evm2; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 8babaaacacf5..4e939dcac1c9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -470,7 +470,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, if (isaggr) { seq_st = ts->ts_seqnum; - memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); + memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3); } while (bf) { @@ -553,7 +553,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (isaggr && txok) { if (ts->ts_flags & ATH9K_TX_BA) { seq_st = ts->ts_seqnum; - memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); + memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3); } else { /* * AR5416 can become deaf/mute when BA -- cgit From f7eb8315b22a8f58365b8916446a11326e5a719b Mon Sep 17 00:00:00 2001 From: Minjie Du Date: Mon, 24 Jul 2023 13:11:07 +0300 Subject: wifi: ath5k: remove phydir check from ath5k_debug_init_device() 'phydir' returned from debugfs_create_dir() is checked against NULL. As the debugfs API returns an error pointer, the returned value can never be NULL. Therefore, as the documentation suggests that the check is unnecessary and other debugfs calls have no operation in error cases, it is advisable to completely eliminate the check. Signed-off-by: Minjie Du Reviewed-by: Jiri Slaby Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230714081619.2032-1-duminjie@vivo.com --- drivers/net/wireless/ath/ath5k/debug.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4b41160e5d38..ec130510aeb2 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -982,8 +982,6 @@ ath5k_debug_init_device(struct ath5k_hw *ah) ah->debug.level = ath5k_debug; phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir); - if (!phydir) - return; debugfs_create_file("debug", 0600, phydir, ah, &fops_debug); debugfs_create_file("registers", 0400, phydir, ah, ®isters_fops); -- cgit From 1301783c8def21fb5e1658676f36d75fff15c571 Mon Sep 17 00:00:00 2001 From: Wang Ming Date: Mon, 24 Jul 2023 13:11:08 +0300 Subject: wifi: ath6kl: Remove error checking for debugfs_create_dir() It is expected that most callers should _ignore_ the errors return by debugfs_create_dir() in ath6kl_debug_init_fs(). Signed-off-by: Wang Ming Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230714014358.514-1-machel@vivo.com --- drivers/net/wireless/ath/ath6kl/debug.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 433a047f3747..b837d31416df 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1793,8 +1793,6 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) { ar->debugfs_phy = debugfs_create_dir("ath6kl", ar->wiphy->debugfsdir); - if (!ar->debugfs_phy) - return -ENOMEM; debugfs_create_file("tgt_stats", 0400, ar->debugfs_phy, ar, &fops_tgt_stats); -- cgit From 061115fbfb2ce5870c9a004d68dc63138c07c782 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Sun, 23 Jul 2023 12:04:02 +0800 Subject: wifi: ath9k: fix printk specifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smatch reports: ath_pci_probe() warn: argument 4 to %lx specifier is cast from pointer ath_ahb_probe() warn: argument 4 to %lx specifier is cast from pointer Fix it by modifying %lx to %p in the printk format string. Note that with this change, the pointer address will be printed as a hashed value by default. This is appropriate because the kernel should not leak kernel pointers to user space in an informational message. If someone wants to see the real address for debugging purposes, this can be achieved with the no_hash_pointers kernel option. Signed-off-by: Dongliang Mu Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230723040403.296723-1-dzm91@hust.edu.cn --- drivers/net/wireless/ath/ath9k/ahb.c | 4 ++-- drivers/net/wireless/ath/ath9k/pci.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9cd12b20b18d..9bfaadfa6c00 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev) ah = sc->sc_ah; ath9k_hw_name(ah, hw_name, sizeof(hw_name)); - wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", - hw_name, (unsigned long)mem, irq); + wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n", + hw_name, mem, irq); return 0; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index a09f9d223f3d..0633589b85c2 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->sc_ah->msi_reg = 0; ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); - wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", - hw_name, (unsigned long)sc->mem, pdev->irq); + wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n", + hw_name, sc->mem, pdev->irq); return 0; -- cgit From 634fcbcaa4062db39aeb5ac6ed1bc1feb8dd5216 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 28 Jun 2023 10:23:15 +0300 Subject: wifi: rtw88: delete timer and free skb queue when unloading Fix possible crash and memory leak on driver unload by deleting TX purge timer and freeing C2H queue in 'rtw_core_deinit()', shrink critical section in the latter by freeing COEX queue out of TX report lock scope. Reviewed-by: Ping-Ke Shih Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230628072327.167196-1-dmantipov@yandex.ru --- drivers/net/wireless/realtek/rtw88/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index c853e2f2d448..c2ddb4d382af 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -2183,10 +2183,12 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) release_firmware(wow_fw->firmware); destroy_workqueue(rtwdev->tx_wq); + timer_delete_sync(&rtwdev->tx_report.purge_timer); spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); skb_queue_purge(&rtwdev->tx_report.queue); - skb_queue_purge(&rtwdev->coex.queue); spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); + skb_queue_purge(&rtwdev->coex.queue); + skb_queue_purge(&rtwdev->c2h_queue); list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, build_list) { -- cgit From 6ca25a31e0a804be1675c0c0115fd6dbdfd7889e Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 28 Jun 2023 10:23:16 +0300 Subject: wifi: rtw88: remove unused and set but unused leftovers Drop unused and set but unused 'last_push' of 'struct rtw_txq', 'wireless_set' of 'struct rtw_sta_info', 'usb_txagg_num' of 'struct rtw_usb' and 'n' of 'struct rx_usb_ctrl_block', unused definition of 'struct rtw_timer_list', adjust related code. Reviewed-by: Ping-Ke Shih Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230628072327.167196-2-dmantipov@yandex.ru --- drivers/net/wireless/realtek/rtw88/main.c | 1 - drivers/net/wireless/realtek/rtw88/main.h | 9 --------- drivers/net/wireless/realtek/rtw88/tx.c | 2 -- drivers/net/wireless/realtek/rtw88/usb.c | 1 - drivers/net/wireless/realtek/rtw88/usb.h | 2 -- 5 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index c2ddb4d382af..935022246fd4 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1303,7 +1303,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, si->stbc_en = stbc_en; si->ldpc_en = ldpc_en; si->rf_type = rf_type; - si->wireless_set = wireless_set; si->sgi_enable = is_support_sgi; si->vht_enable = is_vht_enable; si->ra_mask = ra_mask; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index f9dd2ab941c8..c42ef8294d59 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -511,12 +511,6 @@ struct rtw_txpwr_idx { struct rtw_5g_txpwr_idx pwr_idx_5g; }; -struct rtw_timer_list { - struct timer_list timer; - void (*function)(void *data); - void *args; -}; - struct rtw_channel_params { u8 center_chan; u8 primary_chan; @@ -734,9 +728,7 @@ struct rtw_ra_report { struct rtw_txq { struct list_head list; - unsigned long flags; - unsigned long last_push; }; #define RTW_BC_MC_MACID 1 @@ -754,7 +746,6 @@ struct rtw_sta_info { u8 rate_id; enum rtw_bandwidth bw_mode; enum rtw_rf_type rf_type; - enum rtw_wireless_set wireless_set; u8 stbc_en:2; u8 ldpc_en:2; bool sgi_enable; diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c index 2821119dc930..f63900b6621d 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.c +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -606,8 +606,6 @@ static int rtw_txq_push_skb(struct rtw_dev *rtwdev, rtw_err(rtwdev, "failed to write TX skb to HCI\n"); return ret; } - rtwtxq->last_push = jiffies; - return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 4a57efdba97b..0458ab02a89f 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -654,7 +654,6 @@ static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb) for (i = 0; i < RTW_USB_RXCB_NUM; i++) { struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; - rxcb->n = i; rxcb->rtwdev = rtwusb->rtwdev; rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rxcb->rx_urb) diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h index ad1d7955c6a5..fad998005ec8 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.h +++ b/drivers/net/wireless/realtek/rtw88/usb.h @@ -58,7 +58,6 @@ struct rx_usb_ctrl_block { struct rtw_dev *rtwdev; struct urb *rx_urb; struct sk_buff *rx_skb; - int n; }; struct rtw_usb_tx_data { @@ -79,7 +78,6 @@ struct rtw_usb { u8 pipe_in; u8 out_ep[RTW_USB_EP_MAX]; int qsel_to_ep[TX_DESC_QSEL_MAX]; - u8 usb_txagg_num; struct workqueue_struct *txwq, *rxwq; -- cgit From e88c9558951f4209a29fcaae64def133a30e9917 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 28 Jun 2023 10:23:17 +0300 Subject: wifi: rtw88: remove unused USB bulkout size set Drop no longer used 'bulkout_size' of 'struct rtw_usb' as well as related macros from usb.h and leftovers in 'rtw_usb_parse()'. This follows commit 462c8db6a011 ("wifi: rtw88: usb: drop now unnecessary URB size check"). Reviewed-by: Ping-Ke Shih Reviewed-by: Sascha Hauer Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230628072327.167196-3-dmantipov@yandex.ru --- drivers/net/wireless/realtek/rtw88/usb.c | 17 ----------------- drivers/net/wireless/realtek/rtw88/usb.h | 5 ----- 2 files changed, 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 0458ab02a89f..91ed6d10ba8a 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -142,7 +142,6 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev, struct usb_host_interface *host_interface = &interface->altsetting[0]; struct usb_interface_descriptor *interface_desc = &host_interface->desc; struct usb_endpoint_descriptor *endpoint; - struct usb_device *usbd = interface_to_usbdev(interface); int num_out_pipes = 0; int i; u8 num; @@ -184,22 +183,6 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev, } } - switch (usbd->speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - rtwusb->bulkout_size = RTW_USB_FULL_SPEED_BULK_SIZE; - break; - case USB_SPEED_HIGH: - rtwusb->bulkout_size = RTW_USB_HIGH_SPEED_BULK_SIZE; - break; - case USB_SPEED_SUPER: - rtwusb->bulkout_size = RTW_USB_SUPER_SPEED_BULK_SIZE; - break; - default: - rtw_err(rtwdev, "failed to detect usb speed\n"); - return -EINVAL; - } - rtwdev->hci.bulkout_num = num_out_pipes; if (num_out_pipes < 1 || num_out_pipes > 4) { diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h index fad998005ec8..86697a5c0103 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.h +++ b/drivers/net/wireless/realtek/rtw88/usb.h @@ -18,10 +18,6 @@ #define RTW_USB_VENQT_CMD_IDX 0x00 -#define RTW_USB_SUPER_SPEED_BULK_SIZE 1024 -#define RTW_USB_HIGH_SPEED_BULK_SIZE 512 -#define RTW_USB_FULL_SPEED_BULK_SIZE 64 - #define RTW_USB_TX_SEL_HQ BIT(0) #define RTW_USB_TX_SEL_LQ BIT(1) #define RTW_USB_TX_SEL_NQ BIT(2) @@ -73,7 +69,6 @@ struct rtw_usb { __le32 *usb_data; unsigned int usb_data_index; - u32 bulkout_size; u8 pipe_interrupt; u8 pipe_in; u8 out_ep[RTW_USB_EP_MAX]; -- cgit From 8986f0a9a3bb26bdaf17d5a1c8fadcc4c3edeae8 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 28 Jun 2023 10:23:18 +0300 Subject: wifi: rtw88: simplify vif iterators Since all iterators called by 'rtw_iterate_vifs()' never uses 'mac' argument, it may be omitted, and 'struct rtw_vifs_entry' may be simplified accordingly. Signed-off-by: Dmitry Antipov Reviewed-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230628072327.167196-4-dmantipov@yandex.ru --- drivers/net/wireless/realtek/rtw88/fw.c | 2 +- drivers/net/wireless/realtek/rtw88/main.c | 8 +++----- drivers/net/wireless/realtek/rtw88/ps.c | 6 ++---- drivers/net/wireless/realtek/rtw88/util.c | 7 ++----- drivers/net/wireless/realtek/rtw88/util.h | 3 +-- 5 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 567bbedd8ee0..a1b674e3caaa 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -140,7 +140,7 @@ struct rtw_beacon_filter_iter_data { u8 *payload; }; -static void rtw_fw_bcn_filter_notify_vif_iter(void *data, u8 *mac, +static void rtw_fw_bcn_filter_notify_vif_iter(void *data, struct ieee80211_vif *vif) { struct rtw_beacon_filter_iter_data *iter_data = data; diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 935022246fd4..4a33d2e47f33 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -185,8 +185,7 @@ static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) bf_info->cur_csi_rpt_rate = new_csi_rate_idx; } -static void rtw_vif_watch_dog_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) { struct rtw_watch_dog_iter_data *iter_data = data; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; @@ -2330,7 +2329,7 @@ struct rtw_iter_port_switch_data { struct rtw_vif *rtwvif_ap; }; -static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +static void rtw_port_switch_iter(void *data, struct ieee80211_vif *vif) { struct rtw_iter_port_switch_data *iter_data = data; struct rtw_dev *rtwdev = iter_data->rtwdev; @@ -2382,8 +2381,7 @@ void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) rtw_iterate_vifs(rtwdev, rtw_port_switch_iter, &iter_data); } -static void rtw_check_sta_active_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_check_sta_active_iter(void *data, struct ieee80211_vif *vif) { struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; bool *active = data; diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 43e80a3a8136..07e8cbd436cd 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -37,8 +37,7 @@ int rtw_enter_ips(struct rtw_dev *rtwdev) return 0; } -static void rtw_restore_port_cfg_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif) { struct rtw_dev *rtwdev = data; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; @@ -320,8 +319,7 @@ static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, data->found_vif = vif; } -static void rtw_vif_recalc_lps_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) { __rtw_vif_recalc_lps(data, vif); } diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c index ff3c269fb1a7..e222d3c01a77 100644 --- a/drivers/net/wireless/realtek/rtw88/util.c +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -159,7 +159,6 @@ void rtw_iterate_stas(struct rtw_dev *rtwdev, struct rtw_vifs_entry { struct list_head list; struct ieee80211_vif *vif; - u8 mac[ETH_ALEN]; }; struct rtw_iter_vifs_data { @@ -177,13 +176,11 @@ static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) return; vifs_entry->vif = vif; - ether_addr_copy(vifs_entry->mac, mac); list_add_tail(&vifs_entry->list, &iter_stas->list); } void rtw_iterate_vifs(struct rtw_dev *rtwdev, - void (*iterator)(void *data, u8 *mac, - struct ieee80211_vif *vif), + void (*iterator)(void *data, struct ieee80211_vif *vif), void *data) { struct rtw_iter_vifs_data iter_data; @@ -204,7 +201,7 @@ void rtw_iterate_vifs(struct rtw_dev *rtwdev, list_for_each_entry_safe(vif_entry, tmp, &iter_data.list, list) { list_del_init(&vif_entry->list); - iterator(data, vif_entry->mac, vif_entry->vif); + iterator(data, vif_entry->vif); kfree(vif_entry); } } diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h index dc8965525400..f8399128a9a3 100644 --- a/drivers/net/wireless/realtek/rtw88/util.h +++ b/drivers/net/wireless/realtek/rtw88/util.h @@ -18,8 +18,7 @@ struct rtw_dev; ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) void rtw_iterate_vifs(struct rtw_dev *rtwdev, - void (*iterator)(void *data, u8 *mac, - struct ieee80211_vif *vif), + void (*iterator)(void *data, struct ieee80211_vif *vif), void *data); void rtw_iterate_stas(struct rtw_dev *rtwdev, void (*iterator)(void *data, -- cgit From 59b4cc439f184c5eaa34161ec67af1e16ffabed4 Mon Sep 17 00:00:00 2001 From: Zhang Shurong Date: Sat, 15 Jul 2023 21:42:57 +0800 Subject: wifi: rtw89: debug: Fix error handling in rtw89_debug_priv_btc_manual_set() If there is a failure during kstrtobool_from_user() rtw89_debug_priv_btc_manual_set should return a negative error code instead of returning the count directly. Fix this bug by returning an error code instead of a count after a failed call of the function "kstrtobool_from_user". Moreover I omitted the label "out" with this source code correction. Fixes: e3ec7017f6a2 ("rtw89: add Realtek 802.11ax driver") Signed-off-by: Zhang Shurong Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/tencent_1C09B99BD7DA9CAD18B00C8F0F050F540607@qq.com --- drivers/net/wireless/realtek/rtw89/debug.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index a4bbac916e22..ce5a9ac08145 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3193,12 +3193,14 @@ static ssize_t rtw89_debug_priv_btc_manual_set(struct file *filp, struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; struct rtw89_btc *btc = &rtwdev->btc; bool btc_manual; + int ret; - if (kstrtobool_from_user(user_buf, count, &btc_manual)) - goto out; + ret = kstrtobool_from_user(user_buf, count, &btc_manual); + if (ret) + return ret; btc->ctrl.manual = btc_manual; -out: + return count; } -- cgit From 2d59478308685f95346e2289c2dc519d8d8ecc48 Mon Sep 17 00:00:00 2001 From: Yueh-Shun Li Date: Thu, 22 Jun 2023 01:26:27 +0000 Subject: wifi: zd1211rw: fix typo "tranmits" Spell "transmits" properly. Found by searching for keyword "tranm". Signed-off-by: Yueh-Shun Li Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230622012627.15050-4-shamrocklee@posteo.net --- drivers/net/wireless/zydas/zd1211rw/zd_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c index 850c26bc9524..8505d84eeed6 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c @@ -1006,7 +1006,7 @@ resubmit: * @usb: the zd1211rw-private USB structure * @skb: a &struct sk_buff pointer * - * This function tranmits a frame to the device. It doesn't wait for + * This function transmits a frame to the device. It doesn't wait for * completion. The frame must contain the control set and have all the * control set information available. * -- cgit From efbc7e791a51b416555c6013cdf4943288d49261 Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 11 Jul 2023 00:02:45 +0300 Subject: wifi: rtl8xxxu: Enable AP mode for RTL8192FU Theoretically this chip can handle 127 clients. Tested only very briefly but it should work as well as the RTL8188FU. Signed-off-by: Bitterblue Smith Reviewed-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/ffcabba5-7e9e-674c-ad03-73646b040b96@gmail.com --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c index 18dc5221a9c0..28e93835e05a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c @@ -2079,6 +2079,8 @@ struct rtl8xxxu_fileops rtl8192fu_fops = { .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, .max_aggr_num = 0x1f1f, + .supports_ap = 1, + .max_macid_num = 128, .trxff_boundary = 0x3f3f, .pbp_rx = PBP_PAGE_SIZE_256, .pbp_tx = PBP_PAGE_SIZE_256, -- cgit From dd71aca9a58bedb7bbba1c5c7cca2059a9cb2430 Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 11 Jul 2023 00:04:05 +0300 Subject: wifi: rtl8xxxu: Enable AP mode for RTL8710BU (RTL8188GU) Theoretically this chip can handle 15 clients. Tested only very briefly but it should work as well as the RTL8188FU. Signed-off-by: Bitterblue Smith Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/ce04a0a1-df72-ea30-f742-8834e01457f5@gmail.com --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c index f0d17b75c5f1..871b8cca8a18 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c @@ -1875,6 +1875,8 @@ struct rtl8xxxu_fileops rtl8710bu_fops = { */ .ustime_tsf_edca = 0x28, .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 16, .adda_1t_init = 0x03c00016, .adda_1t_path_on = 0x03c00016, .trxff_boundary = 0x3f7f, -- cgit From 8c34b62167b449d16d6737a132996acad312a398 Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 11 Jul 2023 00:04:39 +0300 Subject: wifi: rtl8xxxu: Enable AP mode for RTL8192EU Theoretically this chip can handle 127 clients. Tested only very briefly but it should work as well as the RTL8188FU. Signed-off-by: Bitterblue Smith Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/56c9b186-ba9a-8469-652d-ce1709813e9e@gmail.com --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index f673aa9ba15a..47bcaec6f2db 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -1767,6 +1767,8 @@ struct rtl8xxxu_fileops rtl8192eu_fops = { .has_s0s1 = 0, .gen2_thermal_meter = 1, .needs_full_init = 1, + .supports_ap = 1, + .max_macid_num = 128, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, -- cgit From 4831a80908f1562685ed29f7ec63ef5bec6b0fc3 Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 11 Jul 2023 00:05:14 +0300 Subject: wifi: rtl8xxxu: Enable AP mode for RTL8723BU Theoretically this chip can handle 127 clients. Only compile tested but it should work as well as the RTL8188FU. Signed-off-by: Bitterblue Smith Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/b2876c56-0ea7-c398-5c9b-635f9f894f2c@gmail.com --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 13ad5d5b73f4..954369ed6226 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -1742,6 +1742,8 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 128, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, -- cgit From caf9ead2c7d06fd7aa4cb48bd569ad61db9a0b4a Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 29 Jun 2023 11:51:00 +0300 Subject: wifi: mwifiex: prefer strscpy() over strlcpy() Prefer 'strscpy()' over 'strlcpy()' in 'mwifiex_init_hw_fw()'. Signed-off-by: Dmitry Antipov Reviewed-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230629085115.180499-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/main.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 1cd9d20cca16..d99127dc466e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -724,14 +724,9 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter, /* Override default firmware with manufacturing one if * manufacturing mode is enabled */ - if (mfg_mode) { - if (strlcpy(adapter->fw_name, MFG_FIRMWARE, - sizeof(adapter->fw_name)) >= - sizeof(adapter->fw_name)) { - pr_err("%s: fw_name too long!\n", __func__); - return -1; - } - } + if (mfg_mode) + strscpy(adapter->fw_name, MFG_FIRMWARE, + sizeof(adapter->fw_name)); if (req_fw_nowait) { ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name, -- cgit From dcce94b80a954a8968ff29fafcfb066d6197fa9a Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 29 Jun 2023 11:51:01 +0300 Subject: wifi: mwifiex: fix fortify warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y, I've noticed the following: In function ‘fortify_memcpy_chk’, inlined from ‘mwifiex_construct_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:765:3, inlined from ‘mwifiex_send_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:856:6: ./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 529 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The compiler actually complains on: memmove(pos + ETH_ALEN, &mgmt->u.action.category, sizeof(mgmt->u.action.u.tdls_discover_resp)); and it happens because the fortification logic interprets this as an attempt to overread 1-byte 'u.action.category' member of 'struct ieee80211_mgmt'. To silence this warning, it's enough to pass an address of 'u.action' itself instead of an address of its first member. This also fixes an improper usage of 'sizeof()'. Since 'skb' is extended with 'sizeof(mgmt->u.action.u.tdls_discover_resp) + 1' bytes (where 1 is actually 'sizeof(mgmt->u.action.category)'), I assume that the same number of bytes should be copied. Suggested-by: Brian Norris Signed-off-by: Dmitry Antipov Reviewed-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230629085115.180499-2-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/tdls.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 97bb87c3676b..6c60621b6ccc 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -735,6 +735,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, int ret; u16 capab; struct ieee80211_ht_cap *ht_cap; + unsigned int extra; u8 radio, *pos; capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; @@ -753,7 +754,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, switch (action_code) { case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1); + /* See the layout of 'struct ieee80211_mgmt'. */ + extra = sizeof(mgmt->u.action.u.tdls_discover_resp) + + sizeof(mgmt->u.action.category); + skb_put(skb, extra); mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; @@ -762,8 +766,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, mgmt->u.action.u.tdls_discover_resp.capability = cpu_to_le16(capab); /* move back for addr4 */ - memmove(pos + ETH_ALEN, &mgmt->u.action.category, - sizeof(mgmt->u.action.u.tdls_discover_resp)); + memmove(pos + ETH_ALEN, &mgmt->u.action, extra); /* init address 4 */ eth_broadcast_addr(pos); -- cgit From 7ee92f6b41606202de66f7629a7d3c597d92da02 Mon Sep 17 00:00:00 2001 From: Johannes Wiesboeck Date: Thu, 6 Jul 2023 11:34:36 +0200 Subject: wifi: mwifiex: Set WIPHY_FLAG_NETNS_OK flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow moving the wiphy device for mwififex to a non-inital network namespace. Many wireless drivers enable this flag implicitly by initializing through the generic ieee80211_alloc_hw_nm function. As mwifiex does not utilize this function WIPHY_FLAG_NETNS_OK must be set explicitly. Moving to network namespace and working connection tested using wpa_supplicant from a network namespace as well as from a container on GyroidOS. The hardware was the Toradex Apalis i.MX8QM Board using the Azurewave AW-CM276NF wireless module. Signed-off-by: Johannes Wiesboeck Reviewed-by: Michael Weiß Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230706093437.3380526-1-johannes.wiesboeck@aisec.fraunhofer.de --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 813d1cbebe19..ba4e29713a8c 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4395,6 +4395,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_NETNS_OK | WIPHY_FLAG_PS_ON_BY_DEFAULT; if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) -- cgit From b2090d93d4b6f1c72a9793d5a171806b8468b7cb Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 19 Jul 2023 11:31:55 +0300 Subject: wifi: brcmsmac: remove unused data type Remove unused 'struct gpioh_item'. It seems it was so since commit 5b435de0d786 ("net: wireless: add brcm80211 drivers"). Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230719083232.158177-1-dmantipov@yandex.ru --- drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h index 2d08c155c23b..90b6e3982d2c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h @@ -145,14 +145,6 @@ struct si_pub { struct pci_dev; -struct gpioh_item { - void *arg; - bool level; - void (*handler) (u32 stat, void *arg); - u32 event; - struct gpioh_item *next; -}; - /* misc si info needed by some of the routines */ struct si_info { struct si_pub pub; /* back plane public state (must be first) */ -- cgit From 98c4d0abf5c478db1ad126ff0c187dbb84c0803c Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Thu, 20 Apr 2023 15:24:51 -0400 Subject: mt76: mt7921: don't assume adequate headroom for SDIO headers mt7921_usb_sdio_tx_prepare_skb() calls mt7921_usb_sdio_write_txwi() and mt7921_skb_add_usb_sdio_hdr(), both of which blindly assume that adequate headroom will be available in the passed skb. This assumption typically is satisfied when the skb was allocated in the net core for transmission via the mt7921 netdev (although even that is only an optimization and is not strictly guaranteed), but the assumption is sometimes not satisfied when the skb originated in the receive path of another netdev and was passed through to the mt7921, such as by the bridge layer. Blindly prepending bytes to an skb is always wrong. This commit introduces a call to skb_cow_head() before the call to mt7921_usb_sdio_write_txwi() in mt7921_usb_sdio_tx_prepare_skb() to ensure that at least MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE bytes can be pushed onto the skb. Without this fix, I can trivially cause kernel panics by bridging an MT7921AU-based USB 802.11ax interface with an Ethernet interface on an Intel Atom-based x86 system using its onboard RTL8169 PCI Ethernet adapter and also on an ARM-based Raspberry Pi 1 using its onboard SMSC9512 USB Ethernet adapter. Note that the panics do not occur in every system configuration, as they occur only if the receiving netdev leaves less headroom in its received skbs than the mt7921 needs for its SDIO headers. Here is an example stack trace of this panic on Raspberry Pi OS Lite 2023-02-21 running kernel 6.1.24+ [1]: skb_panic from skb_push+0x44/0x48 skb_push from mt7921_usb_sdio_tx_prepare_skb+0xd4/0x190 [mt7921_common] mt7921_usb_sdio_tx_prepare_skb [mt7921_common] from mt76u_tx_queue_skb+0x94/0x1d0 [mt76_usb] mt76u_tx_queue_skb [mt76_usb] from __mt76_tx_queue_skb+0x4c/0xc8 [mt76] __mt76_tx_queue_skb [mt76] from mt76_txq_schedule.part.0+0x13c/0x398 [mt76] mt76_txq_schedule.part.0 [mt76] from mt76_txq_schedule_all+0x24/0x30 [mt76] mt76_txq_schedule_all [mt76] from mt7921_tx_worker+0x58/0xf4 [mt7921_common] mt7921_tx_worker [mt7921_common] from __mt76_worker_fn+0x9c/0xec [mt76] __mt76_worker_fn [mt76] from kthread+0xbc/0xe0 kthread from ret_from_fork+0x14/0x34 After this fix, bridging the mt7921 interface works fine on both of my previously problematic systems. [1] https://github.com/raspberrypi/firmware/tree/5c276f55a4b21345cd4d6200a504ee991851ff7a Link: https://github.com/openwrt/openwrt/issues/11796 Signed-off-by: Matt Whitlock Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 1675bf520481..a671c601c583 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1180,6 +1180,10 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (unlikely(tx_info->skb->len <= ETH_HLEN)) return -EINVAL; + err = skb_cow_head(skb, MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE); + if (err) + return err; + if (!wcid) wcid = &dev->mt76.global_wcid; -- cgit From c55b4e788f1dd6ca89cc97cf291d2a03b0b96de1 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 27 Apr 2023 07:05:15 +0800 Subject: wifi: mt76: mt7996: fix header translation logic When header translation failure is indicated, the hardware will insert an extra 2-byte field containing the data length after the protocol type field. This happens either when the LLC-SNAP pattern did not match, or if a VLAN header was detected. The previous commit accidentally breaks the logic, so reverts back. Fixes: 27db47ab1f47 (wifi: mt76: mt7996: enable mesh HW amsdu/de-amsdu support) Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 9b0f6053e0fa..25c5deb15d21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -836,14 +836,19 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) skb_pull(skb, hdr_gap); if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) { pad_start = ieee80211_get_hdrlen_from_skb(skb); - } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) && - get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) { + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { /* When header translation failure is indicated, * the hardware will insert an extra 2-byte field * containing the data length after the protocol - * type field. + * type field. This happens either when the LLC-SNAP + * pattern did not match, or if a VLAN header was + * detected. */ - pad_start = 16; + pad_start = 12; + if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) + pad_start += 4; + else + pad_start = 0; } if (pad_start) { -- cgit From 68f1c3ea337fbc9a58463647be7582eae5a8134b Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 2 May 2023 11:10:05 +0800 Subject: wifi: mt76: mt7996: enable BSS_CHANGED_MU_GROUPS support The Group ID Management frame is an Action frame of category VHT. It is transmitted by the AP to assign or change the user position of a STA for one or more group IDs. Also, sniffer can use a given group id to monitor STA that belongs to that group. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7996/main.c | 23 +++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 21 ++++++++++++++------- 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index f1b48cdda58f..3569fef20cd9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -183,6 +183,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); if (!mdev->dev->of_node || !of_property_read_bool(mdev->dev->of_node, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index f306e9c50ea3..7a97b7180403 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -530,6 +530,26 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return mvif->basic_rates_idx; } +static void +mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + u8 band = mvif->mt76.band_idx; + u32 *mu; + + mu = (u32 *)info->mu_group.membership; + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD0(band), mu[0]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD1(band), mu[1]); + + mu = (u32 *)info->mu_group.position; + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS0(band), mu[0]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS1(band), mu[1]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS2(band), mu[2]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]); +} + static void mt7996_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -602,6 +622,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, changed & BSS_CHANGED_FILS_DISCOVERY) mt7996_mcu_beacon_inband_discov(dev, vif, changed); + if (changed & BSS_CHANGED_MU_GROUPS) + mt7996_update_mu_group(hw, vif, info); + mutex_unlock(&dev->mt76.mutex); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index d1d3d154195d..97beab924517 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -557,22 +557,29 @@ enum base_rev { #define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188) +/* PHYRX CSD */ +#define MT_WF_PHYRX_CSD_BASE 0x83000000 +#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \ + ((_band) << 20) + \ + ((_wf) << 16) + (ofs)) +#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000) + /* PHYRX CTRL */ #define MT_WF_PHYRX_BAND_BASE 0x83080000 #define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \ ((_band) << 20) + (ofs)) +#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054) +#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058) +#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c) +#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060) +#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064) +#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068) + #define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004) #define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0) #define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9) -/* PHYRX CSD */ -#define MT_WF_PHYRX_CSD_BASE 0x83000000 -#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \ - ((_band) << 20) + \ - ((_wf) << 16) + (ofs)) -#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000) - /* PHYRX CSD BAND */ #define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230) #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18) -- cgit From 905a0a6ac7a7709d3ac98ca8c98ca27dd1567b9b Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 2 May 2023 11:10:06 +0800 Subject: wifi: mt76: mt7615: enable BSS_CHANGED_MU_GROUPS support The Group ID Management frame is an Action frame of category VHT. It is transmitted by the AP to assign or change the user position of a STA for one or more group IDs. Also, sniffer can use a given group id to monitor STA that belongs to that group. Notify underlying driver of changes via BSS_CHANGED_MU_GROUPS. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7615/main.c | 29 ++++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7615/regs.h | 9 ++++++++ 3 files changed, 40 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 621e69f07e3c..ab475c841818 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -397,6 +397,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + if (!is_mt7622(&phy->dev->mt76)) + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index dadb13f2ca09..4167aafa5b0e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -552,6 +552,32 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, mt7615_mutex_release(dev); } +static void +mt7615_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + u8 i, band = mvif->mt76.band_idx; + u32 *mu; + + mu = (u32 *)info->mu_group.membership; + for (i = 0; i < WLAN_MEMBERSHIP_LEN / sizeof(*mu); i++) { + if (is_mt7663(&dev->mt76)) + mt76_wr(dev, MT7663_WF_PHY_GID_TAB_VLD(band, i), mu[i]); + else + mt76_wr(dev, MT_WF_PHY_GID_TAB_VLD(band, i), mu[i]); + } + + mu = (u32 *)info->mu_group.position; + for (i = 0; i < WLAN_USER_POSITION_LEN / sizeof(*mu); i++) { + if (is_mt7663(&dev->mt76)) + mt76_wr(dev, MT7663_WF_PHY_GID_TAB_POS(band, i), mu[i]); + else + mt76_wr(dev, MT_WF_PHY_GID_TAB_POS(band, i), mu[i]); + } +} + static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -600,6 +626,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7615_mac_set_beacon_filter(phy, vif, vif->cfg.assoc); + if (changed & BSS_CHANGED_MU_GROUPS) + mt7615_update_mu_group(hw, vif, info); + mt7615_mutex_release(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 7cecb22c569e..806b3887c541 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -212,6 +212,15 @@ enum mt7615_reg_base { #define MT7663_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0224 + ((_phy) << 12)) +#define MT_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \ + ((_phy) << 9)) +#define MT7663_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \ + ((_phy) << 12)) +#define MT_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \ + ((_phy) << 9)) +#define MT7663_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \ + ((_phy) << 12)) + #define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c) #define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \ GENMASK(28, 20)) -- cgit From 62561a47af587a863583ce1d607b519c0c4bb384 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 6 May 2023 13:46:19 +0800 Subject: wifi: mt76: enable UNII-4 channel 177 support Enable support for the 5GHz channel 177 with center frequency 5885MHz and operating class 125 based on IEEE Std 802.11ax-2021 Table E-4. Signed-off-by: Himanshu Goyal Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 467afef98ba2..cd3aac4cc06f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -76,6 +76,7 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = { CHAN5G(165, 5825), CHAN5G(169, 5845), CHAN5G(173, 5865), + CHAN5G(177, 5885), }; static const struct ieee80211_channel mt76_channels_6ghz[] = { -- cgit From 9a3994077d170ec9ac75e800932b5671d9940cd2 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Tue, 9 May 2023 11:11:57 +0800 Subject: wifi: mt76: mt7915: fix background radar event being blocked The background radar uses MT_RX_SEL2 as its band indication, so fix it. Fixes: 7a53eecd5c87 (wifi: mt76: mt7915: check the correctness of event data) Signed-off-by: StanleyYP Wang Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 9fcb22fa1f97..088a065e37d5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -274,7 +274,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) r = (struct mt7915_mcu_rdd_report *)skb->data; - if (r->band_idx > MT_BAND1) + if (r->band_idx > MT_RX_SEL2) return; if ((r->band_idx && !dev->phy.mt76->band_idx) && -- cgit From 943e4fb96e6f47c70a0a9d29d62cffc2479330e6 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 10 May 2023 12:53:16 +0800 Subject: wifi: mt76: mt7915: report tx retries/failed counts for non-WED path Get missing tx retries/failed counts from txfree done events and report them via mt7915_sta_statistics(). Co-developed-by: Peter Chiu Signed-off-by: Peter Chiu Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 6 ++---- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 22 ++++++++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt7915/mac.h | 7 ++++++- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 3 +++ 6 files changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index d39a3cc5e381..368668448542 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -729,17 +729,15 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - bool noacked = !(info->flags & IEEE80211_TX_STAT_ACK); if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK)) info->flags |= IEEE80211_TX_STAT_ACK; info->status.ampdu_len = 1; - info->status.ampdu_ack_len = !noacked; + info->status.ampdu_ack_len = + !!(info->flags & IEEE80211_TX_STAT_ACK); info->status.rates[0].idx = -1; - wcid->stats.tx_failed += noacked; - mt76_connac2_mac_fill_txs(dev, wcid, txs_data); mt76_tx_status_skb_done(dev, skb, &list); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ac2049f49bb3..8d6e09605dc4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -581,6 +581,8 @@ void mt7915_mac_init(struct mt7915_dev *dev) if (!is_mt7915(&dev->mt76)) mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); + else + mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY); /* enable hardware de-agg */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 7df8d95fc3fb..9b2ccd99854e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -951,6 +951,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) struct mt76_dev *mdev = &dev->mt76; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + struct mt76_wcid *wcid = NULL; LIST_HEAD(free_list); void *end = data + len; bool v3, wake = false; @@ -977,7 +978,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) info = le32_to_cpu(*cur_info); if (info & MT_TX_FREE_PAIR) { struct mt7915_sta *msta; - struct mt76_wcid *wcid; u16 idx; idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); @@ -994,7 +994,25 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) continue; } - if (v3 && (info & MT_TX_FREE_MPDU_HEADER)) + if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) { + u32 tx_retries = 0, tx_failed = 0; + + if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) { + tx_retries = + FIELD_GET(MT_TX_FREE_COUNT_V3, info) - 1; + tx_failed = tx_retries + + !!FIELD_GET(MT_TX_FREE_STAT_V3, info); + } else if (!v3 && (info & MT_TX_FREE_MPDU_HEADER)) { + tx_retries = + FIELD_GET(MT_TX_FREE_COUNT, info) - 1; + tx_failed = tx_retries + + !!FIELD_GET(MT_TX_FREE_STAT, info); + } + wcid->stats.tx_retries += tx_retries; + wcid->stats.tx_failed += tx_failed; + } + + if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) continue; for (i = 0; i < 1 + v3; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index ce94f87e2042..448b1b380190 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -9,7 +9,12 @@ #define MT_TX_FREE_VER GENMASK(18, 16) #define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) /* 0: success, others: dropped */ -#define MT_TX_FREE_MPDU_HEADER BIT(30) +#define MT_TX_FREE_COUNT GENMASK(12, 0) +#define MT_TX_FREE_COUNT_V3 GENMASK(27, 24) +#define MT_TX_FREE_STAT GENMASK(14, 13) +#define MT_TX_FREE_STAT_V3 GENMASK(29, 28) +#define MT_TX_FREE_MPDU_HEADER BIT(15) +#define MT_TX_FREE_MPDU_HEADER_V3 BIT(30) #define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0) #define MT_TXS5_F0_FINAL_MPDU BIT(31) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 1b361199c061..706aca359ca3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1045,12 +1045,6 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, sinfo->tx_packets = msta->wcid.stats.tx_packets; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); - sinfo->tx_failed = msta->wcid.stats.tx_failed; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - - sinfo->tx_retries = msta->wcid.stats.tx_retries; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); - if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) { sinfo->rx_bytes = msta->wcid.stats.rx_bytes; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); @@ -1060,6 +1054,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, } } + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + sinfo->ack_signal = (s8)msta->ack_signal; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index c8e478a55081..71fa9576ad0e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -145,6 +145,9 @@ enum offs_rev { #define MT_PLE_BASE 0x820c0000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) +#define MT_PLE_HOST_RPT0 MT_PLE(0x030) +#define MT_PLE_HOST_RPT0_TX_LATENCY BIT(3) + #define MT_FL_Q_EMPTY MT_PLE(__OFFS(PLE_FL_Q_EMPTY)) #define MT_FL_Q0_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL)) #define MT_FL_Q2_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0x8) -- cgit From 161a7528e4074d104305fc109c16134b4990070e Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Wed, 10 May 2023 12:53:17 +0800 Subject: wifi: mt76: mt7915: rework tx packets counting when WED is active PPDU TxS can only report MPDU count whereas mac80211 requires MSDU scale (NL80211_STA_INFO_TX_PACKETS), so switch to get MSDU counts from WA statistic. Note that mt7915 WA firmware only counts tx_packet for WED path, so driver needs to take care of host path additionally. Fixes: 43eaa3689507 ("wifi: mt76: add PPDU based TxS support for WED device") Co-developed-by: Ryder Lee Signed-off-by: Ryder Lee Signed-off-by: Peter Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 9 +-- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + drivers/net/wireless/mediatek/mt76/mt7915/main.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 74 ++++++++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 + 6 files changed, 79 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6b07b8fafec2..0e9f4197213a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -277,7 +277,7 @@ struct mt76_sta_stats { u64 tx_mcs[16]; /* mcs idx */ u64 tx_bytes; /* WED TX */ - u32 tx_packets; + u32 tx_packets; /* unit: MSDU */ u32 tx_retries; u32 tx_failed; /* WED RX */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index 368668448542..f6346a458978 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -523,7 +523,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, /* counting non-offloading skbs */ wcid->stats.tx_bytes += skb->len; - wcid->stats.tx_packets++; + /* mt7915 WA only counts WED path */ + if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed)) + wcid->stats.tx_packets++; } val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | @@ -606,12 +608,11 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, txs = le32_to_cpu(txs_data[0]); /* PPDU based reporting */ - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { + if (mtk_wed_device_active(&dev->mmio.wed) && + FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { stats->tx_bytes += le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) - le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE); - stats->tx_packets += - le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT); stats->tx_failed += le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); stats->tx_retries += diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index ca1ce97a6d2f..7a52b68491b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -998,6 +998,7 @@ enum { MCU_EXT_EVENT_ASSERT_DUMP = 0x23, MCU_EXT_EVENT_RDD_REPORT = 0x3a, MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, + MCU_EXT_EVENT_WA_TX_STAT = 0x74, MCU_EXT_EVENT_BCC_NOTIFY = 0x75, MCU_EXT_EVENT_MURU_CTRL = 0x9f, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 706aca359ca3..6512fdf842b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1042,8 +1042,10 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, sinfo->tx_bytes = msta->wcid.stats.tx_bytes; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); - sinfo->tx_packets = msta->wcid.stats.tx_packets; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) { + sinfo->tx_packets = msta->wcid.stats.tx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + } if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) { sinfo->rx_bytes = msta->wcid.stats.rx_bytes; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 088a065e37d5..8da9c87e9804 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -164,7 +164,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, } rxd = (struct mt76_connac2_mcu_rxd *)skb->data; - if (seq != rxd->seq) + if (seq != rxd->seq && + !(rxd->eid == MCU_CMD_EXT_CID && + rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) return -EAGAIN; if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) { @@ -395,12 +397,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) struct mt76_connac2_mcu_rxd *rxd; rxd = (struct mt76_connac2_mcu_rxd *)skb->data; - if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || - rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST || - rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || - rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || - rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY || - !rxd->seq) + if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || + rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST || + rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || + rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || + rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY || + !rxd->seq) && + !(rxd->eid == MCU_CMD_EXT_CID && + rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) mt7915_mcu_rx_unsolicited_event(dev, skb); else mt76_mcu_rx_event(&dev->mt76, skb); @@ -3733,6 +3737,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev, &req, sizeof(req), true); } +int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx) +{ + struct { + __le32 cmd; + __le32 num; + __le32 __rsv; + __le16 wlan_idx; + } req = { + .cmd = cpu_to_le32(0x15), + .num = cpu_to_le32(1), + .wlan_idx = cpu_to_le16(wlan_idx), + }; + struct mt7915_mcu_wa_tx_stat { + __le16 wlan_idx; + u8 __rsv[2]; + + /* tx_bytes is deprecated since WA byte counter uses u32, + * which easily leads to overflow. + */ + __le32 tx_bytes; + __le32 tx_packets; + } *res; + struct mt76_wcid *wcid; + struct sk_buff *skb; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + if (!is_mt7915(&dev->mt76)) + skb_pull(skb, 4); + + res = (struct mt7915_mcu_wa_tx_stat *)skb->data; + + if (le16_to_cpu(res->wlan_idx) != wlan_idx) { + ret = -EINVAL; + goto out; + } + + rcu_read_lock(); + + wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); + if (wcid) + wcid->stats.tx_packets += le32_to_cpu(res->tx_packets); + else + ret = -EINVAL; + + rcu_read_unlock(); +out: + dev_kfree_skb(skb); + + return ret; +} + int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index b3ead3530740..3053f4abf7db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -539,6 +539,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef); +int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid); int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set); int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); -- cgit From f39d499345dddb8382986fd5a2a0e84a63b1a6d5 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Wed, 10 May 2023 12:53:18 +0800 Subject: wifi: mt76: mt7915: rework tx bytes counting when WED is active Concurrent binding/non-binding skbs could be handled anywhere which leads to mixed byte counting, so switch to use PPDU TxS reporting regardless Tx paths when WED is active. Fixes: 43eaa3689507 ("wifi: mt76: add PPDU based TxS support for WED device") Co-developed-by: Ryder Lee Signed-off-by: Ryder Lee Signed-off-by: Peter Chiu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 6 +++++ drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 30 ++-------------------- drivers/net/wireless/mediatek/mt76/tx.c | 9 ++++++- 4 files changed, 16 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index f6346a458978..3501f0503118 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -521,8 +521,6 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); - /* counting non-offloading skbs */ - wcid->stats.tx_bytes += skb->len; /* mt7915 WA only counts WED path */ if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed)) wcid->stats.tx_packets++; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 8d6e09605dc4..30c552a5f920 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -499,6 +499,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); + + /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than + * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. + */ + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 45f3558bf31c..2fa059af23de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -545,8 +545,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - struct mt7915_phy *phy; - int ret; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); @@ -554,43 +552,19 @@ static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed) dev->mt76.token_size = wed->wlan.token_start; spin_unlock_bh(&dev->mt76.token_lock); - ret = wait_event_timeout(dev->mt76.tx_wait, - !dev->mt76.wed_token_count, HZ); - if (!ret) - return -EAGAIN; - - phy = &dev->phy; - mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H); - - phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; - if (phy) - mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), - MT_AGG_ACR_PPDU_TXS2H); - - return 0; + return !wait_event_timeout(dev->mt76.tx_wait, + !dev->mt76.wed_token_count, HZ); } static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - struct mt7915_phy *phy; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); spin_lock_bh(&dev->mt76.token_lock); dev->mt76.token_size = MT7915_TOKEN_SIZE; spin_unlock_bh(&dev->mt76.token_lock); - - /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than - * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. - */ - phy = &dev->phy; - mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H); - - phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; - if (phy) - mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), - MT_AGG_ACR_PPDU_TXS2H); } static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 72b3ec715e47..e9b9728458a9 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -121,6 +121,7 @@ int mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, struct sk_buff *skb) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); int pid; @@ -134,8 +135,14 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, return MT_PACKET_ID_NO_ACK; if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_CTL_RATE_CTRL_PROBE))) + IEEE80211_TX_CTL_RATE_CTRL_PROBE))) { + if (mtk_wed_device_active(&dev->mmio.wed) && + ((info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) || + ieee80211_is_data(hdr->frame_control))) + return MT_PACKET_ID_WED; + return MT_PACKET_ID_NO_SKB; + } spin_lock_bh(&dev->status_lock); -- cgit From e890c3cf7897b1d07b19124ad2e42c687b3b99e5 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Wed, 10 May 2023 12:53:19 +0800 Subject: wifi: mt76: report non-binding skb tx rate when WED is active AQL relies on accurate tx rate reporting, so add this patch for non-binding skb rate when WED is enabled. Co-developed-by: Ryder Lee Signed-off-by: Ryder Lee Signed-off-by: Peter Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/tx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index e9b9728458a9..6cc26cc6c517 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -270,8 +270,15 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff * #endif if (cb->pktid < MT_PACKET_ID_FIRST) { + struct ieee80211_rate_status rs = {}; + hw = mt76_tx_status_get_hw(dev, skb); status.sta = wcid_to_sta(wcid); + if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) { + rs.rate_idx = wcid->rate; + status.rates = &rs; + status.n_rates = 1; + } spin_lock_bh(&dev->rx_lock); ieee80211_tx_status_ext(hw, &status); spin_unlock_bh(&dev->rx_lock); -- cgit From 41bc54404687faa05404df0910890b062c705f54 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 10 May 2023 12:53:20 +0800 Subject: wifi: mt76: mt7915: drop return in mt7915_sta_statistics Avoid blocking other statistics sinfo->filled when txrate is unavailable. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 6512fdf842b0..85d4ea3d8064 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1019,21 +1019,20 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); } - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + if (txrate->legacy || txrate->flags) { + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } - sinfo->txrate.flags = txrate->flags; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); /* offloading flows bypass networking stack, so driver counts and * reports sta statistics via NL80211_STA_INFO when WED is active. -- cgit From b34f346b917eafed6e61d737917f8543884fe2bf Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 10 May 2023 12:53:21 +0800 Subject: wifi: mt76: mt7996: drop return in mt7996_sta_statistics Avoid blocking other statistics sinfo->filled when txrate is unavailable. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 7a97b7180403..0dbfb0db35a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -975,18 +975,19 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct rate_info *txrate = &msta->wcid.rate; - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + if (txrate->legacy || txrate->flags) { + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); -- cgit From d616d3680264beb9a9d2c4fc681064b06f447eeb Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Wed, 10 May 2023 14:51:13 +0800 Subject: wifi: mt76: mt7921: do not support one stream on secondary antenna only mt7921 support following antenna combiantions only. * primary + secondary (2x2) * primary only (1x1) Since we cannot work on secondary antenna only, return error if the antenna bitmap is 0x2 in .set_antenna(). For example: iw phy0 set antenna 3 3 /* valid */ iw phy0 set antenna 1 1 /* valid */ iw phy0 set antenna 2 2 /* invalid */ Cc: stable@vger.kernel.org Fixes: e0f9fdda81bd ("mt76: mt7921: add ieee80211_ops") Suggested-by: Knox Chiou Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 3b6adb29cbef..0e3ada1e008c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1363,7 +1363,7 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) return -EINVAL; if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) - tx_ant = BIT(ffs(tx_ant) - 1) - 1; + return -EINVAL; mt7921_mutex_acquire(dev); -- cgit From 692031b9045ca0739232052d0cdb26a5d4e5b4b5 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 12 May 2023 15:11:58 +0200 Subject: wifi: mt76: mt7921: remove macro duplication in regs.h Get rid of MT_MIB_RTS_COUNT_MASK marco duplication in mt7921/regs.h Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index e52977ff3349..b180142562a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -158,7 +158,6 @@ #define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) #define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) #define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) #define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) -- cgit From 7f03a56314be00f0ecfa3ef27559d6cfa6ba0429 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 13 May 2023 00:29:53 +0200 Subject: wifi: mt76: mt7915: move mib_stats structure in mt76.h mib_stats structure is shared by mostly all chipsets. Move it to shared code. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 63 ++++++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/debugfs.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 63 +--------------------- 5 files changed, 69 insertions(+), 67 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0e9f4197213a..6d22482183d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -857,6 +857,69 @@ struct mt76_dev { }; }; +/* per-phy stats. */ +struct mt76_mib_stats { + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; + u32 tx_bf_cnt; + u32 tx_mu_bf_cnt; + u32 tx_mu_mpdu_cnt; + u32 tx_mu_acked_mpdu_cnt; + u32 tx_su_acked_mpdu_cnt; + u32 tx_bf_ibf_ppdu_cnt; + u32 tx_bf_ebf_ppdu_cnt; + + u32 tx_bf_rx_fb_all_cnt; + u32 tx_bf_rx_fb_eht_cnt; + u32 tx_bf_rx_fb_he_cnt; + u32 tx_bf_rx_fb_vht_cnt; + u32 tx_bf_rx_fb_ht_cnt; + + u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ + u32 tx_bf_rx_fb_nc_cnt; + u32 tx_bf_rx_fb_nr_cnt; + u32 tx_bf_fb_cpl_cnt; + u32 tx_bf_fb_trig_cnt; + + u32 tx_ampdu_cnt; + u32 tx_stop_q_empty_cnt; + u32 tx_mpdu_attempts_cnt; + u32 tx_mpdu_success_cnt; + u32 tx_pkt_ebf_cnt; + u32 tx_pkt_ibf_cnt; + + u32 tx_rwp_fail_cnt; + u32 tx_rwp_need_cnt; + + /* rx stats */ + u32 rx_fifo_full_cnt; + u32 channel_idle_cnt; + u32 primary_cca_busy_time; + u32 secondary_cca_busy_time; + u32 primary_energy_detect_time; + u32 cck_mdrdy_time; + u32 ofdm_mdrdy_time; + u32 green_mdrdy_time; + u32 rx_vector_mismatch_cnt; + u32 rx_delimiter_fail_cnt; + u32 rx_mrdy_cnt; + u32 rx_len_mismatch_cnt; + u32 rx_mpdu_cnt; + u32 rx_ampdu_cnt; + u32 rx_ampdu_bytes_cnt; + u32 rx_ampdu_valid_subframe_cnt; + u32 rx_ampdu_valid_subframe_bytes_cnt; + u32 rx_pfdrop_cnt; + u32 rx_vec_queue_overflow_drop_cnt; + u32 rx_ba_cnt; + + u32 tx_amsdu[8]; + u32 tx_amsdu_cnt; +}; + struct mt76_power_limits { s8 cck[4]; s8 ofdm[8]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 879884ead660..dd5c494efa5f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -719,10 +719,10 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, static void mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) { + struct mt76_mib_stats *mib = &phy->mib; static const char * const bw[] = { "BW20", "BW40", "BW80", "BW160" }; - struct mib_stats *mib = &phy->mib; /* Tx Beamformer monitor */ seq_puts(s, "\nTx Beamformer applied PPDU counts: "); @@ -768,7 +768,7 @@ mt7915_tx_stats_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; struct mt7915_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; int i; mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 9b2ccd99854e..9e5eb0bfeb26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1765,8 +1765,8 @@ void mt7915_reset(struct mt7915_dev *dev) void mt7915_mac_update_stats(struct mt7915_phy *phy) { + struct mt76_mib_stats *mib = &phy->mib; struct mt7915_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; int i, aggr0 = 0, aggr1, cnt; u8 band = phy->mt76->band_idx; u32 val; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 85d4ea3d8064..e384c633e811 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -842,7 +842,7 @@ mt7915_get_stats(struct ieee80211_hw *hw, { struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = mt7915_hw_dev(hw); - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; mutex_lock(&dev->mt76.mutex); @@ -1327,11 +1327,11 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, .idx = mvif->mt76.idx, }; - struct mib_stats *mib = &phy->mib; /* See mt7915_ampdu_stat_read_phy, etc */ int i, ei = 0, stats_size; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 3053f4abf7db..41e0aafae9f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -157,67 +157,6 @@ struct mt7915_vif { struct cfg80211_bitrate_mask bitrate_mask; }; -/* per-phy stats. */ -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - u32 tx_bf_cnt; - u32 tx_mu_mpdu_cnt; - u32 tx_mu_acked_mpdu_cnt; - u32 tx_su_acked_mpdu_cnt; - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ - u32 tx_bf_rx_fb_nc_cnt; - u32 tx_bf_rx_fb_nr_cnt; - u32 tx_bf_fb_cpl_cnt; - u32 tx_bf_fb_trig_cnt; - - u32 tx_ampdu_cnt; - u32 tx_stop_q_empty_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - u32 tx_pkt_ebf_cnt; - u32 tx_pkt_ibf_cnt; - - u32 tx_rwp_fail_cnt; - u32 tx_rwp_need_cnt; - - /* rx stats */ - u32 rx_fifo_full_cnt; - u32 channel_idle_cnt; - u32 primary_cca_busy_time; - u32 secondary_cca_busy_time; - u32 primary_energy_detect_time; - u32 cck_mdrdy_time; - u32 ofdm_mdrdy_time; - u32 green_mdrdy_time; - u32 rx_vector_mismatch_cnt; - u32 rx_delimiter_fail_cnt; - u32 rx_mrdy_cnt; - u32 rx_len_mismatch_cnt; - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ampdu_valid_subframe_cnt; - u32 rx_ampdu_valid_subframe_bytes_cnt; - u32 rx_pfdrop_cnt; - u32 rx_vec_queue_overflow_drop_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; -}; - /* crash-dump */ struct mt7915_crash_data { guid_t guid; @@ -263,7 +202,7 @@ struct mt7915_phy { u32 rx_ampdu_ts; u32 ampdu_ref; - struct mib_stats mib; + struct mt76_mib_stats mib; struct mt76_channel_state state_ts; #ifdef CONFIG_NL80211_TESTMODE -- cgit From 98214484f2339c01fbb0fa3bfda3790f96fb0b9f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 13 May 2023 00:29:54 +0200 Subject: wifi: mt76: mt7996: rely on mib_stats shared definition Get rid of private copy of mib_stats structure. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7996/debugfs.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 56 +--------------------- 4 files changed, 6 insertions(+), 60 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 513ab4ba41c9..4d40ec7ff57f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -474,10 +474,10 @@ mt7996_ampdu_stat_read_phy(struct mt7996_phy *phy, struct seq_file *file) static void mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s) { + struct mt76_mib_stats *mib = &phy->mib; static const char * const bw[] = { "BW20", "BW40", "BW80", "BW160" }; - struct mib_stats *mib = &phy->mib; /* Tx Beamformer monitor */ seq_puts(s, "\nTx Beamformer applied PPDU counts: "); @@ -523,7 +523,7 @@ mt7996_tx_stats_show(struct seq_file *file, void *data) { struct mt7996_phy *phy = file->private; struct mt7996_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; int i; u32 attempts, success, per; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 25c5deb15d21..d05d7e79781f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -2196,8 +2196,8 @@ void mt7996_reset(struct mt7996_dev *dev) void mt7996_mac_update_stats(struct mt7996_phy *phy) { + struct mt76_mib_stats *mib = &phy->mib; struct mt7996_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; u8 band_idx = phy->mt76->band_idx; u32 cnt; int i; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 0dbfb0db35a5..9362f8487a0e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -815,7 +815,7 @@ mt7996_get_stats(struct ieee80211_hw *hw, { struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; mutex_lock(&dev->mt76.mutex); @@ -1221,11 +1221,11 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw, struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, .idx = mvif->mt76.idx, }; - struct mib_stats *mib = &phy->mib; /* See mt7996_ampdu_stat_read_phy, etc */ int i, ei = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 4d7dcb95a620..348d3ad3f9e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -130,60 +130,6 @@ struct mt7996_vif { u8 beacon_rates_idx; }; -/* per-phy stats. */ -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - u32 tx_mu_bf_cnt; - u32 tx_mu_mpdu_cnt; - u32 tx_mu_acked_mpdu_cnt; - u32 tx_su_acked_mpdu_cnt; - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_eht_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ - u32 tx_bf_rx_fb_nc_cnt; - u32 tx_bf_rx_fb_nr_cnt; - u32 tx_bf_fb_cpl_cnt; - u32 tx_bf_fb_trig_cnt; - - u32 tx_ampdu_cnt; - u32 tx_stop_q_empty_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - /* BF counter is PPDU-based, so remove MPDU-based BF counter */ - - u32 tx_rwp_fail_cnt; - u32 tx_rwp_need_cnt; - - /* rx stats */ - u32 rx_fifo_full_cnt; - u32 channel_idle_cnt; - u32 rx_vector_mismatch_cnt; - u32 rx_delimiter_fail_cnt; - u32 rx_len_mismatch_cnt; - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ampdu_valid_subframe_cnt; - u32 rx_ampdu_valid_subframe_bytes_cnt; - u32 rx_pfdrop_cnt; - u32 rx_vec_queue_overflow_drop_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; -}; - /* crash-dump */ struct mt7996_crash_data { guid_t guid; @@ -222,7 +168,7 @@ struct mt7996_phy { u32 rx_ampdu_ts; u32 ampdu_ref; - struct mib_stats mib; + struct mt76_mib_stats mib; struct mt76_channel_state state_ts; }; -- cgit From 52a1f158b3ff76d6501c061e3c6952801a2dc9a7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 13 May 2023 00:29:55 +0200 Subject: wifi: mt76: mt7921: rely on mib_stats shared definition Get rid of private copy of mib_stats structure. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 +-- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 31 +--------------------- 4 files changed, 5 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index d6b6edba2fec..d6c66e775536 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -95,7 +95,7 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) { struct mt7921_dev *dev = file->private; struct mt7921_phy *phy = &dev->phy; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; int i; mt7921_mutex_acquire(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index a671c601c583..a2e9d7b654c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -952,8 +952,8 @@ EXPORT_SYMBOL_GPL(mt7921_reset); void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) { + struct mt76_mib_stats *mib = &phy->mib; struct mt7921_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; int i, aggr0 = 0, aggr1; u32 val; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 0e3ada1e008c..d183982c0b40 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -995,7 +995,7 @@ mt7921_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; mt7921_mutex_acquire(phy->dev); @@ -1133,7 +1133,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, .idx = mvif->mt76.idx, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 149acb1662d5..76dc2538b915 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -179,35 +179,6 @@ struct mt7921_vif { struct ieee80211_chanctx_conf *ctx; }; -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_ampdu_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - u32 tx_pkt_ebf_cnt; - u32 tx_pkt_ibf_cnt; - - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; -}; - enum { MT7921_CLC_POWER, MT7921_CLC_CHAN, @@ -247,7 +218,7 @@ struct mt7921_phy { u32 rx_ampdu_ts; u32 ampdu_ref; - struct mib_stats mib; + struct mt76_mib_stats mib; u8 sta_work_count; -- cgit From 6bad146d162e92174b09522b357b64f8fda95246 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 15 May 2023 15:27:12 +0200 Subject: wifi: mt76: mt7915: add support for MT7981 Add support for the MediaTek MT7981 SoC which is similar to the MT7986 but with a newer IP cores and only 2x ARM Cortex-A53 instead of 4x. Unlike MT7986 the MT7981 can only connect a single wireless frontend, usually MT7976 is used for DBDC. Signed-off-by: Alexander Couzens Signed-off-by: Daniel Golle Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 10 ++ drivers/net/wireless/mediatek/mt76/mt7915/Kconfig | 6 +- drivers/net/wireless/mediatek/mt76/mt7915/Makefile | 2 +- .../net/wireless/mediatek/mt76/mt7915/coredump.c | 7 +- drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 7 +- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 3 + drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 17 ++- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 14 +- drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 13 +- drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 162 +++++++++++++++------ 13 files changed, 179 insertions(+), 76 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 15653b274f83..77ca8f057d61 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -197,11 +197,21 @@ static inline bool is_mt7916(struct mt76_dev *dev) return mt76_chip(dev) == 0x7906; } +static inline bool is_mt7981(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7981; +} + static inline bool is_mt7986(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7986; } +static inline bool is_mt798x(struct mt76_dev *dev) +{ + return is_mt7981(dev) || is_mt7986(dev); +} + static inline bool is_mt7996(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7990; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig index d710726d47bf..896ec38c23d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig @@ -14,12 +14,12 @@ config MT7915E To compile this driver as a module, choose M here. -config MT7986_WMAC - bool "MT7986 (SoC) WMAC support" +config MT798X_WMAC + bool "MT798x (SoC) WMAC support" depends on MT7915E depends on ARCH_MEDIATEK || COMPILE_TEST select REGMAP help - This adds support for the built-in WMAC on MT7986 SoC device + This adds support for the built-in WMAC on MT7981 and MT7986 SoC device which has the same feature set as a MT7915, but enables 6E support. diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index 797ae49805c3..e0ca638c91a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -6,5 +6,5 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ debugfs.o mmio.o mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o -mt7915e-$(CONFIG_MT7986_WMAC) += soc.o +mt7915e-$(CONFIG_MT798X_WMAC) += soc.o mt7915e-$(CONFIG_DEV_COREDUMP) += coredump.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c b/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c index d097a56dd33d..5daf2258dfe6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c @@ -52,7 +52,7 @@ static const struct mt7915_mem_region mt7916_mem_regions[] = { }, }; -static const struct mt7915_mem_region mt7986_mem_regions[] = { +static const struct mt7915_mem_region mt798x_mem_regions[] = { { .start = 0x00800000, .len = 0x0005ffff, @@ -92,9 +92,10 @@ mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) case 0x7915: *num = ARRAY_SIZE(mt7915_mem_regions); return &mt7915_mem_regions[0]; + case 0x7981: case 0x7986: - *num = ARRAY_SIZE(mt7986_mem_regions); - return &mt7986_mem_regions[0]; + *num = ARRAY_SIZE(mt798x_mem_regions); + return &mt798x_mem_regions[0]; case 0x7916: *num = ARRAY_SIZE(mt7916_mem_regions); return &mt7916_mem_regions[0]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 43a5456d4b97..86a93dedb1bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -11,7 +11,7 @@ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base struct mt7915_dev *dev = phy->dev; if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) ring_base += MT_TXQ_ID(0) * MT_RING_SIZE; else ring_base = MT_WED_TX_RING_BASE; @@ -370,7 +370,7 @@ static int mt7915_dma_enable(struct mt7915_dev *dev) int ret; wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); else mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); @@ -404,7 +404,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) mt7915_dma_disable(dev, true); if (mtk_wed_device_active(&mdev->mmio.wed)) { - if (!is_mt7986(mdev)) { + if (!is_mt798x(mdev)) { u8 wed_control_rx1 = is_mt7915(mdev) ? 1 : 2; mt76_set(dev, MT_WFDMA_HOST_CONFIG, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index a79628933948..76be7308460b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -39,6 +39,8 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev) return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76)); case 0x7916: return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76)); + case 0x7981: + return CHECK_EEPROM_ERR(is_mt7981(&dev->mt76)); case 0x7986: return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76)); default: @@ -52,6 +54,9 @@ static char *mt7915_eeprom_name(struct mt7915_dev *dev) case 0x7915: return dev->dbdc_support ? MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT; + case 0x7981: + /* mt7981 only supports mt7976 and only in DBDC mode */ + return MT7981_EEPROM_MT7976_DEFAULT_DBDC; case 0x7986: switch (mt7915_check_adie(dev, true)) { case MT7976_ONE_ADIE_DBDC: @@ -215,7 +220,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, eeprom[MT_EE_WIFI_CONF + 2 + band]); } - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) nss_max = 2; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 30c552a5f920..07cdf14c515f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -740,7 +740,7 @@ void mt7915_wfsys_reset(struct mt7915_dev *dev) mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); msleep(100); - } else if (is_mt7986(&dev->mt76)) { + } else if (is_mt798x(&dev->mt76)) { mt7986_wmac_disable(dev); msleep(20); @@ -761,7 +761,7 @@ static bool mt7915_band_config(struct mt7915_dev *dev) dev->phy.mt76->band_idx = 0; - if (is_mt7986(&dev->mt76)) { + if (is_mt798x(&dev->mt76)) { u32 sku = mt7915_check_adie(dev, true); /* @@ -1170,7 +1170,7 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev) mt7915_dma_cleanup(dev); tasklet_disable(&dev->mt76.irq_tasklet); - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) mt7986_wmac_disable(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 9e5eb0bfeb26..14ea42732ded 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1594,7 +1594,7 @@ void mt7915_mac_reset_work(struct work_struct *work) if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { mtk_wed_device_stop(&dev->mt76.mmio.wed); - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) mt76_wr(dev, MT_INT_WED_MASK_CSR, 0); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 8da9c87e9804..c9716422c803 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -13,6 +13,9 @@ case 0x7915: \ _fw = MT7915_##name; \ break; \ + case 0x7981: \ + _fw = MT7981_##name; \ + break; \ case 0x7986: \ _fw = MT7986_##name##__VA_ARGS__; \ break; \ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 2fa059af23de..fc7ace638ce8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -417,7 +417,7 @@ static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); u32 l1_remap; - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) return MT_CONN_INFRA_OFFSET(addr); l1_remap = is_mt7915(&dev->mt76) ? @@ -447,7 +447,7 @@ static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) /* use read to push write */ dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2); } else { - u32 ofs = is_mt7986(&dev->mt76) ? 0x400000 : 0; + u32 ofs = is_mt798x(&dev->mt76) ? 0x400000 : 0; offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_MT7916, addr); base = FIELD_GET(MT_HIF_REMAP_L2_BASE_MT7916, addr); @@ -759,7 +759,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.nbuf = MT7915_HW_TOKEN_SIZE; wed->wlan.tx_tbit[0] = is_mt7915(&dev->mt76) ? 4 : 30; wed->wlan.tx_tbit[1] = is_mt7915(&dev->mt76) ? 5 : 31; - wed->wlan.txfree_tbit = is_mt7986(&dev->mt76) ? 2 : 1; + wed->wlan.txfree_tbit = is_mt798x(&dev->mt76) ? 2 : 1; wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; wed->wlan.wcid_512 = !is_mt7915(&dev->mt76); @@ -769,7 +769,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, if (is_mt7915(&dev->mt76)) { wed->wlan.rx_tbit[0] = 16; wed->wlan.rx_tbit[1] = 17; - } else if (is_mt7986(&dev->mt76)) { + } else if (is_mt798x(&dev->mt76)) { wed->wlan.rx_tbit[0] = 22; wed->wlan.rx_tbit[1] = 23; } else { @@ -827,6 +827,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev, dev->reg.map = mt7916_reg_map; dev->reg.map_size = ARRAY_SIZE(mt7916_reg_map); break; + case 0x7981: case 0x7986: dev->reg.reg_rev = mt7986_reg; dev->reg.offs_rev = mt7916_offs; @@ -1036,8 +1037,8 @@ static int __init mt7915_init(void) if (ret) goto error_pci; - if (IS_ENABLED(CONFIG_MT7986_WMAC)) { - ret = platform_driver_register(&mt7986_wmac_driver); + if (IS_ENABLED(CONFIG_MT798X_WMAC)) { + ret = platform_driver_register(&mt798x_wmac_driver); if (ret) goto error_wmac; } @@ -1054,8 +1055,8 @@ error_pci: static void __exit mt7915_exit(void) { - if (IS_ENABLED(CONFIG_MT7986_WMAC)) - platform_driver_unregister(&mt7986_wmac_driver); + if (IS_ENABLED(CONFIG_MT798X_WMAC)) + platform_driver_unregister(&mt798x_wmac_driver); pci_unregister_driver(&mt7915_pci_driver); pci_unregister_driver(&mt7915_hif_driver); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 41e0aafae9f8..736f5fbfafc5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -34,6 +34,10 @@ #define MT7916_FIRMWARE_WM "mediatek/mt7916_wm.bin" #define MT7916_ROM_PATCH "mediatek/mt7916_rom_patch.bin" +#define MT7981_FIRMWARE_WA "mediatek/mt7981_wa.bin" +#define MT7981_FIRMWARE_WM "mediatek/mt7981_wm.bin" +#define MT7981_ROM_PATCH "mediatek/mt7981_rom_patch.bin" + #define MT7986_FIRMWARE_WA "mediatek/mt7986_wa.bin" #define MT7986_FIRMWARE_WM "mediatek/mt7986_wm.bin" #define MT7986_FIRMWARE_WM_MT7975 "mediatek/mt7986_wm_mt7975.bin" @@ -43,6 +47,9 @@ #define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin" #define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin" #define MT7916_EEPROM_DEFAULT "mediatek/mt7916_eeprom.bin" + +#define MT7981_EEPROM_MT7976_DEFAULT_DBDC "mediatek/mt7981_eeprom_mt7976_dbdc.bin" + #define MT7986_EEPROM_MT7975_DEFAULT "mediatek/mt7986_eeprom_mt7975.bin" #define MT7986_EEPROM_MT7975_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7975_dual.bin" #define MT7986_EEPROM_MT7976_DEFAULT "mediatek/mt7986_eeprom_mt7976.bin" @@ -359,8 +366,7 @@ mt7915_ext_phy(struct mt7915_dev *dev) static inline u32 mt7915_check_adie(struct mt7915_dev *dev, bool sku) { u32 mask = sku ? MT_CONNINFRA_SKU_MASK : MT_ADIE_TYPE_MASK; - - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) return 0; return mt76_rr(dev, MT_CONNINFRA_SKU_DEC_ADDR) & mask; @@ -370,9 +376,9 @@ extern const struct ieee80211_ops mt7915_ops; extern const struct mt76_testmode_ops mt7915_testmode_ops; extern struct pci_driver mt7915_pci_driver; extern struct pci_driver mt7915_hif_driver; -extern struct platform_driver mt7986_wmac_driver; +extern struct platform_driver mt798x_wmac_driver; -#ifdef CONFIG_MT7986_WMAC +#ifdef CONFIG_MT798X_WMAC int mt7986_wmac_enable(struct mt7915_dev *dev); void mt7986_wmac_disable(struct mt7915_dev *dev); #else diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 71fa9576ad0e..588cd87e24e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -874,7 +874,12 @@ enum offs_rev { #define MT_AFE_RG_WBG_EN_WPLL_UP_MASK BIT(20) #define MT_AFE_RG_WBG_EN_PLL_UP_MASK (MT_AFE_RG_WBG_EN_BPLL_UP_MASK | \ MT_AFE_RG_WBG_EN_WPLL_UP_MASK) -#define MT_AFE_RG_WBG_EN_TXCAL_MASK GENMASK(21, 17) +#define MT_AFE_RG_WBG_EN_TXCAL_WF4 BIT(29) +#define MT_AFE_RG_WBG_EN_TXCAL_BT BIT(21) +#define MT_AFE_RG_WBG_EN_TXCAL_WF3 BIT(20) +#define MT_AFE_RG_WBG_EN_TXCAL_WF2 BIT(19) +#define MT_AFE_RG_WBG_EN_TXCAL_WF1 BIT(18) +#define MT_AFE_RG_WBG_EN_TXCAL_WF0 BIT(17) #define MT_ADIE_SLP_CTRL_BASE(_band) (0x18005000 + ((_band) << 19)) #define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs)) @@ -1099,6 +1104,12 @@ enum offs_rev { #define MT_TOP_MCU_EMI_BASE MT_TOP(0x1c4) #define MT_TOP_MCU_EMI_BASE_MASK GENMASK(19, 0) +#define MT_TOP_WF_AP_PERI_BASE MT_TOP(0x1c8) +#define MT_TOP_WF_AP_PERI_BASE_MASK GENMASK(19, 0) + +#define MT_TOP_EFUSE_BASE MT_TOP(0x1cc) +#define MT_TOP_EFUSE_BASE_MASK GENMASK(19, 0) + #define MT_TOP_CONN_INFRA_WAKEUP MT_TOP(0x1a0) #define MT_TOP_CONN_INFRA_WAKEUP_MASK BIT(0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 32c137066e7f..1f23e60f9714 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -16,6 +16,9 @@ #include "mt7915.h" +#define MT7981_CON_INFRA_VERSION 0x02090000 +#define MT7986_CON_INFRA_VERSION 0x02070000 + /* INFRACFG */ #define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0 #define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4 @@ -167,10 +170,14 @@ static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) return val; } -static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev) +static u8 mt798x_wmac_check_adie_type(struct mt7915_dev *dev) { u32 val; + /* Only DBDC A-die is used with MT7981 */ + if (is_mt7981(&dev->mt76)) + return ADIE_DBDC; + val = readl(dev->sku + MT_TOP_POS_SKU); return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val); @@ -195,7 +202,7 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev) int ret; u8 type; - type = mt7986_wmac_check_adie_type(dev); + type = mt798x_wmac_check_adie_type(dev); pinctrl = devm_pinctrl_get(dev->mt76.dev); if (IS_ERR(pinctrl)) return PTR_ERR(pinctrl); @@ -257,16 +264,26 @@ static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable) return 0; } -static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev) +static int mt798x_wmac_coninfra_check(struct mt7915_dev *dev) { u32 cur; + u32 con_infra_version; + + if (is_mt7981(&dev->mt76)) { + con_infra_version = MT7981_CON_INFRA_VERSION; + } else if (is_mt7986(&dev->mt76)) { + con_infra_version = MT7986_CON_INFRA_VERSION; + } else { + WARN_ON(1); + return -EINVAL; + } - return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000), + return read_poll_timeout(mt76_rr, cur, (cur == con_infra_version), USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, dev, MT_CONN_INFRA_BASE); } -static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) +static int mt798x_wmac_coninfra_setup(struct mt7915_dev *dev) { struct device *pdev = dev->mt76.dev; struct reserved_mem *rmem; @@ -284,15 +301,25 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK; - /* Set conninfra subsys PLL check */ - mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, - MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); - mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, - MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + if (is_mt7986(&dev->mt76)) { + /* Set conninfra subsys PLL check */ + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + } mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE, MT_TOP_MCU_EMI_BASE_MASK, val); + if (is_mt7981(&dev->mt76)) { + mt76_rmw_field(dev, MT_TOP_WF_AP_PERI_BASE, + MT_TOP_WF_AP_PERI_BASE_MASK, 0x300d0000 >> 16); + + mt76_rmw_field(dev, MT_TOP_EFUSE_BASE, + MT_TOP_EFUSE_BASE_MASK, 0x11f20000 >> 16); + } + mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base); mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size); @@ -305,15 +332,18 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) return 0; } -static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) +static int mt798x_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) { int ret; - u32 adie_main, adie_ext; + u32 adie_main = 0, adie_ext = 0; mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1); - mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, - MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); + + if (is_mt7986(&dev->mt76)) { + mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, + MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); + } mt76_wmac_spi_lock(dev); @@ -321,9 +351,11 @@ static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) if (ret) goto out; - ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); - if (ret) - goto out; + if (is_mt7986(&dev->mt76)) { + ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); + if (ret) + goto out; + } *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) | (MT_ADIE_CHIP_ID_MASK & adie_ext); @@ -470,7 +502,7 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie) return ret; } -static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) +static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) { u32 id, version, rg_xo_01, rg_xo_03; int ret; @@ -489,7 +521,14 @@ static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) rg_xo_01 = 0x1d59080f; rg_xo_03 = 0x34c00fe0; } else { - rg_xo_01 = 0x1959f80f; + if (is_mt7981(&dev->mt76)) { + rg_xo_01 = 0x1959c80f; + } else if (is_mt7986(&dev->mt76)) { + rg_xo_01 = 0x1959f80f; + } else { + WARN_ON(1); + return -EINVAL; + } rg_xo_03 = 0x34d00fe0; } @@ -611,7 +650,15 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) return ret; /* turn on SX0 LTBUF */ - ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); + if (is_mt7981(&dev->mt76)) { + ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000007); + } else if (is_mt7986(&dev->mt76)) { + ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); + } else { + WARN_ON(1); + return -EINVAL; + } + if (ret) return ret; @@ -658,7 +705,10 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) return ret; /* set CKB driving and filter */ - return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); + if (is_mt7986(&dev->mt76)) + return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); + + return ret; } static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) @@ -686,7 +736,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) ret = mt7986_wmac_adie_patch_7975(dev, adie); } else if (is_7976(dev, adie, adie_type)) { - if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) { + if (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC) { ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_WRI_CK_SEL, 0x1c); if (ret) @@ -701,7 +751,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) if (ret) goto out; - ret = mt7986_wmac_adie_patch_7976(dev, adie); + ret = mt798x_wmac_adie_patch_7976(dev, adie); } out: mt76_wmac_spi_unlock(dev); @@ -714,6 +764,7 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) { int ret; u8 idx; + u32 txcal; mt76_wmac_spi_lock(dev); if (is_7975(dev, adie, adie_type)) @@ -744,12 +795,18 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1); usleep_range(60, 100); - mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), - MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f); + txcal = (MT_AFE_RG_WBG_EN_TXCAL_BT | + MT_AFE_RG_WBG_EN_TXCAL_WF0 | + MT_AFE_RG_WBG_EN_TXCAL_WF1 | + MT_AFE_RG_WBG_EN_TXCAL_WF2 | + MT_AFE_RG_WBG_EN_TXCAL_WF3); + if (is_mt7981(&dev->mt76)) + txcal |= MT_AFE_RG_WBG_EN_TXCAL_WF4; + + mt76_set(dev, MT_AFE_DIG_EN_01(idx), txcal); usleep_range(800, 1000); - mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), - MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0); + mt76_clear(dev, MT_AFE_DIG_EN_01(idx), txcal); mt76_rmw(dev, MT_AFE_DIG_EN_03(idx), MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0); @@ -806,7 +863,7 @@ static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev) mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); - return mt7986_wmac_coninfra_check(dev); + return mt798x_wmac_coninfra_check(dev); } static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type) @@ -876,14 +933,15 @@ static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable) if (!enable) return 0; - return mt7986_wmac_coninfra_check(dev); + return mt798x_wmac_coninfra_check(dev); } static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable) { u32 cur; - mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0); + if (is_mt7986(&dev->mt76)) + mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0); mt76_rmw_field(dev, MT7986_TOP_WM_RESET, MT7986_TOP_WM_RESET_MASK, enable); @@ -1006,7 +1064,7 @@ mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type) if (ret) return ret; - if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC)) + if (!adie && (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC)) ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type); return ret; @@ -1061,15 +1119,15 @@ int mt7986_wmac_enable(struct mt7915_dev *dev) if (ret) return ret; - ret = mt7986_wmac_coninfra_check(dev); + ret = mt798x_wmac_coninfra_check(dev); if (ret) return ret; - ret = mt7986_wmac_coninfra_setup(dev); + ret = mt798x_wmac_coninfra_setup(dev); if (ret) return ret; - ret = mt7986_wmac_sku_setup(dev, &adie_type); + ret = mt798x_wmac_sku_setup(dev, &adie_type); if (ret) return ret; @@ -1077,9 +1135,12 @@ int mt7986_wmac_enable(struct mt7915_dev *dev) if (ret) return ret; - ret = mt7986_wmac_adie_setup(dev, 1, adie_type); - if (ret) - return ret; + /* mt7981 doesn't support a second a-die */ + if (is_mt7986(&dev->mt76)) { + ret = mt7986_wmac_adie_setup(dev, 1, adie_type); + if (ret) + return ret; + } ret = mt7986_wmac_subsys_powerup(dev, adie_type); if (ret) @@ -1132,7 +1193,7 @@ void mt7986_wmac_disable(struct mt7915_dev *dev) mt7986_wmac_consys_reset(dev, false); } -static int mt7986_wmac_init(struct mt7915_dev *dev) +static int mt798x_wmac_init(struct mt7915_dev *dev) { struct device *pdev = dev->mt76.dev; struct platform_device *pfdev = to_platform_device(pdev); @@ -1165,7 +1226,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev) return 0; } -static int mt7986_wmac_probe(struct platform_device *pdev) +static int mt798x_wmac_probe(struct platform_device *pdev) { void __iomem *mem_base; struct mt7915_dev *dev; @@ -1203,7 +1264,7 @@ static int mt7986_wmac_probe(struct platform_device *pdev) if (ret) goto free_device; - ret = mt7986_wmac_init(dev); + ret = mt798x_wmac_init(dev); if (ret) goto free_irq; @@ -1225,7 +1286,7 @@ free_device: return ret; } -static int mt7986_wmac_remove(struct platform_device *pdev) +static int mt798x_wmac_remove(struct platform_device *pdev) { struct mt7915_dev *dev = platform_get_drvdata(pdev); @@ -1234,20 +1295,21 @@ static int mt7986_wmac_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id mt7986_wmac_of_match[] = { +static const struct of_device_id mt798x_wmac_of_match[] = { + { .compatible = "mediatek,mt7981-wmac", .data = (u32 *)0x7981 }, { .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 }, {}, }; -MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match); +MODULE_DEVICE_TABLE(of, mt798x_wmac_of_match); -struct platform_driver mt7986_wmac_driver = { +struct platform_driver mt798x_wmac_driver = { .driver = { - .name = "mt7986-wmac", - .of_match_table = mt7986_wmac_of_match, + .name = "mt798x-wmac", + .of_match_table = mt798x_wmac_of_match, }, - .probe = mt7986_wmac_probe, - .remove = mt7986_wmac_remove, + .probe = mt798x_wmac_probe, + .remove = mt798x_wmac_remove, }; MODULE_FIRMWARE(MT7986_FIRMWARE_WA); @@ -1255,3 +1317,7 @@ MODULE_FIRMWARE(MT7986_FIRMWARE_WM); MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975); MODULE_FIRMWARE(MT7986_ROM_PATCH); MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975); + +MODULE_FIRMWARE(MT7981_FIRMWARE_WA); +MODULE_FIRMWARE(MT7981_FIRMWARE_WM); +MODULE_FIRMWARE(MT7981_ROM_PATCH); -- cgit From 9aecfa754c7fc12c3f7feb669aec2f744e83954a Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Mon, 15 May 2023 23:18:50 +0800 Subject: wifi: mt76: mt7921e: report tx retries/failed counts in tx free event Get missing tx retries/failed counts from txfree done events and report them via mt7921_sta_statistics(). Signed-off-by: Deren Wu Reviewed-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 8 +++++++- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h index fabf637bdf7f..bd2a92467a97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h @@ -34,7 +34,7 @@ enum { #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) -#define MT_TX_FREE_LATENCY GENMASK(12, 0) +#define MT_TX_FREE_COUNT GENMASK(12, 0) /* 0: success, others: dropped */ #define MT_TX_FREE_STATUS GENMASK(14, 13) #define MT_TX_FREE_MSDU_ID GENMASK(30, 16) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index a2e9d7b654c5..2d3f394039f6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -614,6 +614,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) struct mt76_dev *mdev = &dev->mt76; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + struct mt76_wcid *wcid = NULL; struct sk_buff *skb, *tmp; void *end = data + len; LIST_HEAD(free_list); @@ -637,7 +638,6 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) */ if (info & MT_TX_FREE_PAIR) { struct mt7921_sta *msta; - struct mt76_wcid *wcid; u16 idx; count++; @@ -658,6 +658,12 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); stat = FIELD_GET(MT_TX_FREE_STATUS, info); + if (wcid) { + wcid->stats.tx_retries += + FIELD_GET(MT_TX_FREE_COUNT, info) - 1; + wcid->stats.tx_failed += !!stat; + } + txwi = mt76_token_release(mdev, msdu, &wake); if (!txwi) continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index d183982c0b40..199da4b701a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1399,6 +1399,12 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw, sinfo->txrate.he_dcm = txrate->he_dcm; sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; } + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); -- cgit From b642f4c5f3de0a8f47808d32b1ebd9c427a42a66 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Wed, 17 May 2023 17:18:24 +0800 Subject: wifi: mt76: mt7921: fix skb leak by txs missing in AMSDU txs may be dropped if the frame is aggregated in AMSDU. When the problem shows up, some SKBs would be hold in driver to cause network stopped temporarily. Even if the problem can be recovered by txs timeout handling, mt7921 still need to disable txs in AMSDU to avoid this issue. Cc: stable@vger.kernel.org Fixes: 163f4d22c118 ("mt76: mt7921: add MAC support") Reviewed-by: Shayne Chen Signed-off-by: Deren Wu Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index 3501f0503118..f481ca3a0db8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -495,6 +495,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, BSS_CHANGED_BEACON_ENABLED)); bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); + bool amsdu_en = wcid->amsdu; if (vif) { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; @@ -554,12 +555,14 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, txwi[4] = 0; val = FIELD_PREP(MT_TXD5_PID, pid); - if (pid >= MT_PACKET_ID_FIRST) + if (pid >= MT_PACKET_ID_FIRST) { val |= MT_TXD5_TX_STATUS_HOST; + amsdu_en = amsdu_en && !is_mt7921(dev); + } txwi[5] = cpu_to_le32(val); txwi[6] = 0; - txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; + txwi[7] = amsdu_en ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; if (is_8023) mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid); -- cgit From 749c2c2b29dfb3a41cfdf9942581c2524664e969 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 18 May 2023 01:34:42 +0800 Subject: wifi: mt76: add tx_nss histogram to ethtool stats mt76_connac2_mac_fill_txs() counts tx_nss but ethtool doesn't show stats. Add missing histogram accordingly. Signed-off-by: Ben Greear Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt7915/main.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 ++++ 4 files changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index cd3aac4cc06f..24ebf0504a3b 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1744,6 +1744,9 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, for (i = 0; i < (eht ? 14 : 12); i++) data[ei++] += stats->tx_mcs[i]; + for (i = 0; i < 4; i++) + data[ei++] += stats->tx_nss[i]; + wi->worker_stat_count = ei - wi->initial_stat_idx; } EXPORT_SYMBOL_GPL(mt76_ethtool_worker); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index e384c633e811..ecb27da27c6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1280,6 +1280,10 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_9", "v_tx_mcs_10", "v_tx_mcs_11", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", }; #define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 199da4b701a5..d520e68a8c82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1077,6 +1077,10 @@ static const char mt7921_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_9", "v_tx_mcs_10", "v_tx_mcs_11", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", }; static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 9362f8487a0e..073a9f91d9a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -1177,6 +1177,10 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_11", "v_tx_mcs_12", "v_tx_mcs_13", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", }; #define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats) -- cgit From 1258c156f2537786468c7fe04f547f64c97c1e12 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 18 May 2023 01:34:43 +0800 Subject: wifi: mt76: mt7915: accumulate mu-mimo ofdma muru stats The stats are clear-on-read, which makes it very difficult for tools to adequately deal with wrapped stats and with keeping good totals. So, accumulate these values when they are read from the firmware/radio and present totals to user-space. Signed-off-by: Ben Greear Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 32 ++++++ .../net/wireless/mediatek/mt76/mt7915/debugfs.c | 124 ++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 3 + drivers/net/wireless/mediatek/mt76/mt7915/main.c | 63 +++++++++++ drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 43 ++++++- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2 +- 6 files changed, 196 insertions(+), 71 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6d22482183d8..c11a417c5e37 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -918,6 +918,38 @@ struct mt76_mib_stats { u32 tx_amsdu[8]; u32 tx_amsdu_cnt; + + /* mcu_muru_stats */ + u32 dl_cck_cnt; + u32 dl_ofdm_cnt; + u32 dl_htmix_cnt; + u32 dl_htgf_cnt; + u32 dl_vht_su_cnt; + u32 dl_vht_2mu_cnt; + u32 dl_vht_3mu_cnt; + u32 dl_vht_4mu_cnt; + u32 dl_he_su_cnt; + u32 dl_he_ext_su_cnt; + u32 dl_he_2ru_cnt; + u32 dl_he_2mu_cnt; + u32 dl_he_3ru_cnt; + u32 dl_he_3mu_cnt; + u32 dl_he_4ru_cnt; + u32 dl_he_4mu_cnt; + u32 dl_he_5to8ru_cnt; + u32 dl_he_9to16ru_cnt; + u32 dl_he_gtr16ru_cnt; + + u32 ul_hetrig_su_cnt; + u32 ul_hetrig_2ru_cnt; + u32 ul_hetrig_3ru_cnt; + u32 ul_hetrig_4ru_cnt; + u32 ul_hetrig_5to8ru_cnt; + u32 ul_hetrig_9to16ru_cnt; + u32 ul_hetrig_gtr16ru_cnt; + u32 ul_hetrig_2mu_cnt; + u32 ul_hetrig_3mu_cnt; + u32 ul_hetrig_4mu_cnt; }; struct mt76_power_limits { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index dd5c494efa5f..6c3696c8c700 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -251,7 +251,6 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; struct mt7915_dev *dev = phy->dev; - struct mt7915_mcu_muru_stats mu_stats = {}; static const char * const dl_non_he_type[] = { "CCK", "OFDM", "HT MIX", "HT GF", "VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU" @@ -275,7 +274,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) mutex_lock(&dev->mt76.mutex); - ret = mt7915_mcu_muru_debug_get(phy, &mu_stats); + ret = mt7915_mcu_muru_debug_get(phy); if (ret) goto exit; @@ -285,14 +284,13 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) for (i = 0; i < 5; i++) seq_printf(file, "%8s | ", dl_non_he_type[i]); -#define __dl_u32(s) le32_to_cpu(mu_stats.dl.s) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ", - __dl_u32(cck_cnt), - __dl_u32(ofdm_cnt), - __dl_u32(htmix_cnt), - __dl_u32(htgf_cnt), - __dl_u32(vht_su_cnt)); + phy->mib.dl_cck_cnt, + phy->mib.dl_ofdm_cnt, + phy->mib.dl_htmix_cnt, + phy->mib.dl_htgf_cnt, + phy->mib.dl_vht_su_cnt); seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); @@ -301,23 +299,23 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __dl_u32(vht_2mu_cnt), - __dl_u32(vht_3mu_cnt), - __dl_u32(vht_4mu_cnt)); + phy->mib.dl_vht_2mu_cnt, + phy->mib.dl_vht_3mu_cnt, + phy->mib.dl_vht_4mu_cnt); - sub_total_cnt = __dl_u32(vht_2mu_cnt) + - __dl_u32(vht_3mu_cnt) + - __dl_u32(vht_4mu_cnt); + sub_total_cnt = phy->mib.dl_vht_2mu_cnt + + phy->mib.dl_vht_3mu_cnt + + phy->mib.dl_vht_4mu_cnt; seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); total_ppdu_cnt = sub_total_cnt + - __dl_u32(cck_cnt) + - __dl_u32(ofdm_cnt) + - __dl_u32(htmix_cnt) + - __dl_u32(htgf_cnt) + - __dl_u32(vht_su_cnt); + phy->mib.dl_cck_cnt + + phy->mib.dl_ofdm_cnt + + phy->mib.dl_htmix_cnt + + phy->mib.dl_htgf_cnt + + phy->mib.dl_vht_su_cnt; seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt); @@ -329,8 +327,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | ", - __dl_u32(he_su_cnt), - __dl_u32(he_ext_su_cnt)); + phy->mib.dl_he_su_cnt, phy->mib.dl_he_ext_su_cnt); seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); @@ -339,9 +336,8 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __dl_u32(he_2mu_cnt), - __dl_u32(he_3mu_cnt), - __dl_u32(he_4mu_cnt)); + phy->mib.dl_he_2mu_cnt, phy->mib.dl_he_3mu_cnt, + phy->mib.dl_he_4mu_cnt); seq_puts(file, "\nDownlink OFDMA\nData Type: "); @@ -350,37 +346,35 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ", - __dl_u32(he_2ru_cnt), - __dl_u32(he_3ru_cnt), - __dl_u32(he_4ru_cnt), - __dl_u32(he_5to8ru_cnt), - __dl_u32(he_9to16ru_cnt), - __dl_u32(he_gtr16ru_cnt)); - - sub_total_cnt = __dl_u32(he_2mu_cnt) + - __dl_u32(he_3mu_cnt) + - __dl_u32(he_4mu_cnt); + phy->mib.dl_he_2ru_cnt, + phy->mib.dl_he_3ru_cnt, + phy->mib.dl_he_4ru_cnt, + phy->mib.dl_he_5to8ru_cnt, + phy->mib.dl_he_9to16ru_cnt, + phy->mib.dl_he_gtr16ru_cnt); + + sub_total_cnt = phy->mib.dl_he_2mu_cnt + + phy->mib.dl_he_3mu_cnt + + phy->mib.dl_he_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); - sub_total_cnt = __dl_u32(he_2ru_cnt) + - __dl_u32(he_3ru_cnt) + - __dl_u32(he_4ru_cnt) + - __dl_u32(he_5to8ru_cnt) + - __dl_u32(he_9to16ru_cnt) + - __dl_u32(he_gtr16ru_cnt); + sub_total_cnt = phy->mib.dl_he_2ru_cnt + + phy->mib.dl_he_3ru_cnt + + phy->mib.dl_he_4ru_cnt + + phy->mib.dl_he_5to8ru_cnt + + phy->mib.dl_he_9to16ru_cnt + + phy->mib.dl_he_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", sub_total_cnt); - total_ppdu_cnt += __dl_u32(he_su_cnt) + - __dl_u32(he_ext_su_cnt); + total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt; seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); -#undef __dl_u32 /* HE Uplink */ seq_puts(file, "\n\nUplink"); @@ -389,12 +383,11 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) for (i = 0; i < 3; i++) seq_printf(file, "%8s | ", ul_he_type[i]); -#define __ul_u32(s) le32_to_cpu(mu_stats.ul.s) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __ul_u32(hetrig_2mu_cnt), - __ul_u32(hetrig_3mu_cnt), - __ul_u32(hetrig_4mu_cnt)); + phy->mib.ul_hetrig_2mu_cnt, + phy->mib.ul_hetrig_3mu_cnt, + phy->mib.ul_hetrig_4mu_cnt); seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type: "); @@ -403,37 +396,36 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u | %7u | ", - __ul_u32(hetrig_su_cnt), - __ul_u32(hetrig_2ru_cnt), - __ul_u32(hetrig_3ru_cnt), - __ul_u32(hetrig_4ru_cnt), - __ul_u32(hetrig_5to8ru_cnt), - __ul_u32(hetrig_9to16ru_cnt), - __ul_u32(hetrig_gtr16ru_cnt)); - - sub_total_cnt = __ul_u32(hetrig_2mu_cnt) + - __ul_u32(hetrig_3mu_cnt) + - __ul_u32(hetrig_4mu_cnt); + phy->mib.ul_hetrig_su_cnt, + phy->mib.ul_hetrig_2ru_cnt, + phy->mib.ul_hetrig_3ru_cnt, + phy->mib.ul_hetrig_4ru_cnt, + phy->mib.ul_hetrig_5to8ru_cnt, + phy->mib.ul_hetrig_9to16ru_cnt, + phy->mib.ul_hetrig_gtr16ru_cnt); + + sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt + + phy->mib.ul_hetrig_3mu_cnt + + phy->mib.ul_hetrig_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", sub_total_cnt); - sub_total_cnt = __ul_u32(hetrig_2ru_cnt) + - __ul_u32(hetrig_3ru_cnt) + - __ul_u32(hetrig_4ru_cnt) + - __ul_u32(hetrig_5to8ru_cnt) + - __ul_u32(hetrig_9to16ru_cnt) + - __ul_u32(hetrig_gtr16ru_cnt); + sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt + + phy->mib.ul_hetrig_3ru_cnt + + phy->mib.ul_hetrig_4ru_cnt + + phy->mib.ul_hetrig_5to8ru_cnt + + phy->mib.ul_hetrig_9to16ru_cnt + + phy->mib.ul_hetrig_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", sub_total_cnt); - total_ppdu_cnt += __ul_u32(hetrig_su_cnt); + total_ppdu_cnt += phy->mib.ul_hetrig_su_cnt; seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt); -#undef __ul_u32 exit: mutex_unlock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 14ea42732ded..4226fd496143 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -2072,6 +2072,9 @@ void mt7915_mac_work(struct work_struct *work) mt7915_mac_update_stats(phy); mt7915_mac_severe_check(phy); + + if (phy->dev->muru_debug) + mt7915_mcu_muru_debug_get(phy); } mutex_unlock(&mphy->dev->mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index ecb27da27c6d..64c02734a3f2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1254,6 +1254,38 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_vec_queue_overflow_drop_cnt", "rx_ba_cnt", + /* muru mu-mimo and ofdma related stats */ + "dl_cck_cnt", + "dl_ofdm_cnt", + "dl_htmix_cnt", + "dl_htgf_cnt", + "dl_vht_su_cnt", + "dl_vht_2mu_cnt", + "dl_vht_3mu_cnt", + "dl_vht_4mu_cnt", + "dl_he_su_cnt", + "dl_he_ext_su_cnt", + "dl_he_2ru_cnt", + "dl_he_2mu_cnt", + "dl_he_3ru_cnt", + "dl_he_3mu_cnt", + "dl_he_4ru_cnt", + "dl_he_4mu_cnt", + "dl_he_5to8ru_cnt", + "dl_he_9to16ru_cnt", + "dl_he_gtr16ru_cnt", + + "ul_hetrig_su_cnt", + "ul_hetrig_2ru_cnt", + "ul_hetrig_3ru_cnt", + "ul_hetrig_4ru_cnt", + "ul_hetrig_5to8ru_cnt", + "ul_hetrig_9to16ru_cnt", + "ul_hetrig_gtr16ru_cnt", + "ul_hetrig_2mu_cnt", + "ul_hetrig_3mu_cnt", + "ul_hetrig_4mu_cnt", + /* per vif counters */ "v_tx_mode_cck", "v_tx_mode_ofdm", @@ -1408,6 +1440,37 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, data[ei++] = mib->rx_vec_queue_overflow_drop_cnt; data[ei++] = mib->rx_ba_cnt; + data[ei++] = mib->dl_cck_cnt; + data[ei++] = mib->dl_ofdm_cnt; + data[ei++] = mib->dl_htmix_cnt; + data[ei++] = mib->dl_htgf_cnt; + data[ei++] = mib->dl_vht_su_cnt; + data[ei++] = mib->dl_vht_2mu_cnt; + data[ei++] = mib->dl_vht_3mu_cnt; + data[ei++] = mib->dl_vht_4mu_cnt; + data[ei++] = mib->dl_he_su_cnt; + data[ei++] = mib->dl_he_ext_su_cnt; + data[ei++] = mib->dl_he_2ru_cnt; + data[ei++] = mib->dl_he_2mu_cnt; + data[ei++] = mib->dl_he_3ru_cnt; + data[ei++] = mib->dl_he_3mu_cnt; + data[ei++] = mib->dl_he_4ru_cnt; + data[ei++] = mib->dl_he_4mu_cnt; + data[ei++] = mib->dl_he_5to8ru_cnt; + data[ei++] = mib->dl_he_9to16ru_cnt; + data[ei++] = mib->dl_he_gtr16ru_cnt; + + data[ei++] = mib->ul_hetrig_su_cnt; + data[ei++] = mib->ul_hetrig_2ru_cnt; + data[ei++] = mib->ul_hetrig_3ru_cnt; + data[ei++] = mib->ul_hetrig_4ru_cnt; + data[ei++] = mib->ul_hetrig_5to8ru_cnt; + data[ei++] = mib->ul_hetrig_9to16ru_cnt; + data[ei++] = mib->ul_hetrig_gtr16ru_cnt; + data[ei++] = mib->ul_hetrig_2mu_cnt; + data[ei++] = mib->ul_hetrig_3mu_cnt; + data[ei++] = mib->ul_hetrig_4mu_cnt; + /* Add values for all stations owned by this vif */ wi.initial_stat_idx = ei; ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index c9716422c803..bb8ec0d1d01c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2119,12 +2119,11 @@ int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled) sizeof(data), false); } -int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; struct sk_buff *skb; - struct mt7915_mcu_muru_stats *mu_stats = - (struct mt7915_mcu_muru_stats *)ms; + struct mt7915_mcu_muru_stats *mu_stats; int ret; struct { @@ -2140,7 +2139,43 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) if (ret) return ret; - memcpy(mu_stats, skb->data, sizeof(struct mt7915_mcu_muru_stats)); + mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data); + + /* accumulate stats, these are clear-on-read */ +#define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s) +#define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s) + __dl_u32(cck_cnt); + __dl_u32(ofdm_cnt); + __dl_u32(htmix_cnt); + __dl_u32(htgf_cnt); + __dl_u32(vht_su_cnt); + __dl_u32(vht_2mu_cnt); + __dl_u32(vht_3mu_cnt); + __dl_u32(vht_4mu_cnt); + __dl_u32(he_su_cnt); + __dl_u32(he_2ru_cnt); + __dl_u32(he_2mu_cnt); + __dl_u32(he_3ru_cnt); + __dl_u32(he_3mu_cnt); + __dl_u32(he_4ru_cnt); + __dl_u32(he_4mu_cnt); + __dl_u32(he_5to8ru_cnt); + __dl_u32(he_9to16ru_cnt); + __dl_u32(he_gtr16ru_cnt); + + __ul_u32(hetrig_su_cnt); + __ul_u32(hetrig_2ru_cnt); + __ul_u32(hetrig_3ru_cnt); + __ul_u32(hetrig_4ru_cnt); + __ul_u32(hetrig_5to8ru_cnt); + __ul_u32(hetrig_9to16ru_cnt); + __ul_u32(hetrig_gtr16ru_cnt); + __ul_u32(hetrig_2mu_cnt); + __ul_u32(hetrig_3mu_cnt); + __ul_u32(hetrig_4mu_cnt); +#undef __dl_u32 +#undef __ul_u32 + dev_kfree_skb(skb); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 736f5fbfafc5..0b8380bc0588 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -569,7 +569,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy); void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy); void mt7915_update_channel(struct mt76_phy *mphy); int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enable); -int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms); +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy); int mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev *dev); int mt7915_init_debugfs(struct mt7915_phy *phy); void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len); -- cgit From 0e5911bb7cc92c00dda9b4d635c1266b7ca915c6 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Thu, 18 May 2023 22:08:14 +0800 Subject: wifi: mt76: mt7921: fix non-PSC channel scan fail Due to the scan command may only request legacy bands and PSC channel in 6GHz band, we are unable to scan the APs on non-PSC channel in this case. Enable WIPHY_FLAG_SPLIT_SCAN_6GHZ to support non-PSC channel (obtained during scan on legacy bands) in 6GHz scan request. Fixes: 50ac15a511e3 ("mt76: mt7921: add 6GHz support") Signed-off-by: Ming Yen Hsieh Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index bf1da9fddfab..f41975e37d06 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -113,7 +113,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; wiphy->max_sched_scan_reqs = 1; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_SPLIT_SCAN_6GHZ; wiphy->reg_notifier = mt7921_regd_notifier; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | -- cgit From 6ae39b7c7ed4d594cacb6b1d61fb6a8602df0c3c Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 2 Jun 2023 14:14:24 -0700 Subject: wifi: mt76: mt7921: Support temp sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow sensors tool to read radio's temperature, example: mt7921_phy17-pci-1800 Adapter: PCI adapter temp1: +72.0°C Signed-off-by: Ben Greear Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 60 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 17 ++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 3 files changed, 78 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index f41975e37d06..73a31efc08da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -2,6 +2,9 @@ /* Copyright (C) 2020 MediaTek Inc. */ #include +#include +#include +#include #include #include "mt7921.h" #include "../mt76_connac2_mac.h" @@ -51,6 +54,57 @@ static const struct ieee80211_iface_combination if_comb_chanctx[] = { } }; +static ssize_t mt7921_thermal_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + switch (to_sensor_dev_attr(attr)->index) { + case 0: { + struct mt7921_phy *phy = dev_get_drvdata(dev); + struct mt7921_dev *mdev = phy->dev; + int temperature; + + mt7921_mutex_acquire(mdev); + temperature = mt7921_mcu_get_temperature(phy); + mt7921_mutex_release(mdev); + + if (temperature < 0) + return temperature; + /* display in millidegree Celsius */ + return sprintf(buf, "%u\n", temperature * 1000); + } + default: + return -EINVAL; + } +} +static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7921_thermal_temp, 0); + +static struct attribute *mt7921_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(mt7921_hwmon); + +static int mt7921_thermal_init(struct mt7921_phy *phy) +{ + struct wiphy *wiphy = phy->mt76->hw->wiphy; + struct device *hwmon; + const char *name; + + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7921_%s", + wiphy_name(wiphy)); + + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, + mt7921_hwmon_groups); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); + + return 0; +} + static void mt7921_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) @@ -363,6 +417,12 @@ static void mt7921_init_work(struct work_struct *work) return; } + ret = mt7921_thermal_init(&dev->phy); + if (ret) { + dev_err(dev->mt76.dev, "thermal init failed\n"); + return; + } + /* we support chip reset now */ dev->hw_init_done = true; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index f55caa00ac69..a0ad18c70b1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1305,6 +1305,23 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, return 0; } +int mt7921_mcu_get_temperature(struct mt7921_phy *phy) +{ + struct mt7921_dev *dev = phy->dev; + struct { + u8 ctrl_id; + u8 action; + u8 band_idx; + u8 rsv[5]; + } req = { + .ctrl_id = THERMAL_SENSOR_TEMP_QUERY, + .band_idx = phy->mt76->band_idx, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req, + sizeof(req), true); +} + int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, u8 bit_op, u32 bit_map) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 76dc2538b915..3776055201d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -511,6 +511,7 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, struct ieee80211_chanctx_conf *ctx); +int mt7921_mcu_get_temperature(struct mt7921_phy *phy); int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, -- cgit From 1e64fdd41c9d2c6f6c9ef0ce7d6854c70d812d0f Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Tue, 23 May 2023 02:49:53 +0800 Subject: wifi: mt76: mt7915: disable WFDMA Tx/Rx during SER recovery Stop WFDMA transaction to avoid potential unexpected issue while doing system recovery. Signed-off-by: Bo Jiao Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 6 + drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 148 ++++++++++++--------- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 25 +++- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 + 4 files changed, 107 insertions(+), 73 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 465190ebaf1c..05d9ab3ce819 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -466,6 +466,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf buf = {}; dma_addr_t addr; + if (test_bit(MT76_MCU_RESET, &dev->phy.state)) + goto error; + if (q->queued + 1 >= q->ndesc - 1) goto error; @@ -507,6 +510,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, dma_addr_t addr; u8 *txwi; + if (test_bit(MT76_RESET, &dev->phy.state)) + goto free_skb; + t = mt76_get_txwi(dev); if (!t) goto free_skb; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 86a93dedb1bf..59a44d79aaed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -250,12 +250,90 @@ static void mt7915_dma_disable(struct mt7915_dev *dev, bool rst) } } -static int mt7915_dma_enable(struct mt7915_dev *dev) +int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset) { struct mt76_dev *mdev = &dev->mt76; u32 hif1_ofs = 0; u32 irq_mask; + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + + /* enable wpdma tx/rx */ + if (!reset) { + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + + if (dev->hif2) { + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_PDMA_BAND); + } + } + + /* enable interrupts for TX/RX rings */ + irq_mask = MT_INT_RX_DONE_MCU | + MT_INT_TX_DONE_MCU | + MT_INT_MCU_CMD; + + if (!dev->phy.mt76->band_idx) + irq_mask |= MT_INT_BAND0_RX_DONE; + + if (dev->dbdc_support || dev->phy.mt76->band_idx) + irq_mask |= MT_INT_BAND1_RX_DONE; + + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) { + u32 wed_irq_mask = irq_mask; + int ret; + + wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; + if (!is_mt798x(&dev->mt76)) + mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); + else + mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); + + ret = mt7915_mcu_wed_enable_rx_stats(dev); + if (ret) + return ret; + + mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + } + + irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; + + mt7915_irq_enable(dev, irq_mask); + mt7915_irq_disable(dev, 0); + + return 0; +} + +static int mt7915_dma_enable(struct mt7915_dev *dev, bool reset) +{ + struct mt76_dev *mdev = &dev->mt76; + u32 hif1_ofs = 0; + if (dev->hif2) hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); @@ -322,69 +400,7 @@ static int mt7915_dma_enable(struct mt7915_dev *dev) mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); - /* set WFDMA Tx/Rx */ - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (is_mt7915(mdev)) - mt76_set(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN | - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - - if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (is_mt7915(mdev)) - mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN | - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - - mt76_set(dev, MT_WFDMA_HOST_CONFIG, - MT_WFDMA_HOST_CONFIG_PDMA_BAND); - } - - /* enable interrupts for TX/RX rings */ - irq_mask = MT_INT_RX_DONE_MCU | - MT_INT_TX_DONE_MCU | - MT_INT_MCU_CMD; - - if (!dev->phy.mt76->band_idx) - irq_mask |= MT_INT_BAND0_RX_DONE; - - if (dev->dbdc_support || dev->phy.mt76->band_idx) - irq_mask |= MT_INT_BAND1_RX_DONE; - - if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { - u32 wed_irq_mask = irq_mask; - int ret; - - wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; - if (!is_mt798x(&dev->mt76)) - mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); - else - mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); - - ret = mt7915_mcu_wed_enable_rx_stats(dev); - if (ret) - return ret; - - mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); - } - - mt7915_irq_enable(dev, irq_mask); - - return 0; + return mt7915_dma_start(dev, reset, true); } int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) @@ -560,7 +576,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) mt7915_poll_tx); napi_enable(&dev->mt76.tx_napi); - mt7915_dma_enable(dev); + mt7915_dma_enable(dev, false); return 0; } @@ -642,7 +658,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mt76_rmw(dev, MT_WFDMA0_EXT0_CFG, MT_WFDMA0_EXT0_RXWB_KEEP, MT_WFDMA0_EXT0_RXWB_KEEP); - mt7915_dma_enable(dev); + mt7915_dma_enable(dev, !force); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 4226fd496143..2bc2fefa1cd0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1407,8 +1407,12 @@ mt7915_mac_restart(struct mt7915_dev *dev) if (dev_is_pci(mdev->dev)) { mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); - if (dev->hif2) - mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); + if (dev->hif2) { + if (is_mt7915(mdev)) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); + else + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0x0); + } } set_bit(MT76_RESET, &dev->mphy.state); @@ -1458,8 +1462,12 @@ mt7915_mac_restart(struct mt7915_dev *dev) } if (dev_is_pci(mdev->dev)) { mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - if (dev->hif2) - mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + if (dev->hif2) { + if (is_mt7915(mdev)) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + else + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); + } } /* load firmware */ @@ -1629,6 +1637,12 @@ void mt7915_mac_reset_work(struct work_struct *work) mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); } + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + /* enable DMA Tx/Rx and interrupt */ + mt7915_dma_start(dev, false, false); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); if (phy2) @@ -1643,9 +1657,6 @@ void mt7915_mac_reset_work(struct work_struct *work) tasklet_schedule(&dev->mt76.irq_tasklet); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - mt76_worker_enable(&dev->mt76.tx_worker); local_bh_disable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 0b8380bc0588..93b536e01eb5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -411,6 +411,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); int mt7915_dma_reset(struct mt7915_dev *dev, bool force); +int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset); int mt7915_txbf_init(struct mt7915_dev *dev); void mt7915_init_txpower(struct mt7915_dev *dev, struct ieee80211_supported_band *sband); -- cgit From 8e8c09c7d09020ddd1fb7c09423383aa5f88d391 Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Tue, 23 May 2023 02:49:54 +0800 Subject: wifi: mt76: mt7996: disable WFDMA Tx/Rx during SER recovery Stop WFDMA transaction to avoid potential unexpected issue while doing system recovery. Signed-off-by: Bo Jiao Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/dma.c | 81 +++++++++++++--------- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 9 ++- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 + 3 files changed, 55 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 534143465d9b..99b00a135711 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -128,11 +128,55 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset) } } -static int mt7996_dma_enable(struct mt7996_dev *dev) +void mt7996_dma_start(struct mt7996_dev *dev, bool reset) { u32 hif1_ofs = 0; u32 irq_mask; + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + + /* enable WFDMA Tx/Rx */ + if (!reset) { + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (dev->hif2) + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + } + + /* enable interrupts for TX/RX rings */ + irq_mask = MT_INT_MCU_CMD; + if (reset) + goto done; + + irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU; + + if (!dev->mphy.band_idx) + irq_mask |= MT_INT_BAND0_RX_DONE; + + if (dev->dbdc_support) + irq_mask |= MT_INT_BAND1_RX_DONE; + + if (dev->tbtc_support) + irq_mask |= MT_INT_BAND2_RX_DONE; + +done: + mt7996_irq_enable(dev, irq_mask); + mt7996_irq_disable(dev, 0); +} + +static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) +{ + u32 hif1_ofs = 0; + if (dev->hif2) hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); @@ -170,13 +214,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); - /* set WFDMA Tx/Rx */ - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - /* GLO_CFG_EXT0 */ mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0, WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD | @@ -187,12 +224,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE); if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - /* GLO_CFG_EXT0 */ mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs, WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD | @@ -216,23 +247,7 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */ } - /* enable interrupts for TX/RX rings */ - irq_mask = MT_INT_RX_DONE_MCU | - MT_INT_TX_DONE_MCU | - MT_INT_MCU_CMD; - - if (!dev->mphy.band_idx) - irq_mask |= MT_INT_BAND0_RX_DONE; - - if (dev->dbdc_support) - irq_mask |= MT_INT_BAND1_RX_DONE; - - if (dev->tbtc_support) - irq_mask |= MT_INT_BAND2_RX_DONE; - - mt7996_irq_enable(dev, irq_mask); - - return 0; + mt7996_dma_start(dev, reset); } int mt7996_dma_init(struct mt7996_dev *dev) @@ -347,7 +362,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) mt7996_poll_tx); napi_enable(&dev->mt76.tx_napi); - mt7996_dma_enable(dev); + mt7996_dma_enable(dev, false); return 0; } @@ -413,7 +428,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force) mt76_for_each_q_rx(&dev->mt76, i) mt76_queue_rx_reset(dev, i); - mt7996_dma_enable(dev); + mt7996_dma_enable(dev, !force); } void mt7996_dma_cleanup(struct mt7996_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index d05d7e79781f..de1590903318 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -2051,6 +2051,12 @@ void mt7996_mac_reset_work(struct work_struct *work) mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); } + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + /* enable DMA Tx/Tx and interrupt */ + mt7996_dma_start(dev, false); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); if (phy2) @@ -2067,9 +2073,6 @@ void mt7996_mac_reset_work(struct work_struct *work) tasklet_schedule(&dev->mt76.irq_tasklet); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - mt76_worker_enable(&dev->mt76.tx_worker); local_bh_disable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 348d3ad3f9e7..7b74477abbe3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -351,6 +351,7 @@ int mt7996_dma_init(struct mt7996_dev *dev); void mt7996_dma_reset(struct mt7996_dev *dev, bool force); void mt7996_dma_prefetch(struct mt7996_dev *dev); void mt7996_dma_cleanup(struct mt7996_dev *dev); +void mt7996_dma_start(struct mt7996_dev *dev, bool reset); void mt7996_init_txpower(struct mt7996_dev *dev, struct ieee80211_supported_band *sband); int mt7996_txbf_init(struct mt7996_dev *dev); -- cgit From 0dde9c11cf58c1720556c778737d28d1945c8e07 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 27 May 2023 13:23:46 +0200 Subject: wifi: mt76: mt7921: make mt7921_mac_sta_poll static Make mt7921_mac_sta_poll static since it is run just in mac.c Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 2d3f394039f6..49f44b1e8d51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -52,7 +52,7 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) 0, 5000); } -void mt7921_mac_sta_poll(struct mt7921_dev *dev) +static void mt7921_mac_sta_poll(struct mt7921_dev *dev) { static const u8 ac_to_tid[] = { [IEEE80211_AC_BE] = 0, @@ -183,7 +183,6 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); } } -EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll); static void mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 3776055201d0..523b177e23cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -484,7 +484,6 @@ int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, struct ieee80211_sta *sta, bool clear_status, struct list_head *free_list); -void mt7921_mac_sta_poll(struct mt7921_dev *dev); int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); -- cgit From c4f0755823045b66484fb53d686f85d3151400f4 Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Sun, 28 May 2023 21:04:28 +0300 Subject: wifi: mt76: mt7915: fix command timeout in AP stop period Due to AP stop improperly, mt7915 driver would face random command timeout by chip fw problem. Migrate AP start/stop process to .start_ap/.stop_ap and congiure BSS network settings in both hooks. The new flow is shown below. * AP start .start_ap() configure BSS network resource set BSS to connected state .bss_info_changed() enable fw beacon offload * AP stop .bss_info_changed() disable fw beacon offload (skip this command) .stop_ap() set BSS to disconnected state (beacon offload disabled automatically) destroy BSS network resource Based on "mt76: mt7921: fix command timeout in AP stop period" Signed-off-by: Rany Hany Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 63 +++++++++++++++++++----- 1 file changed, 50 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 64c02734a3f2..679397dddf0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -599,6 +599,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, { struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = mt7915_hw_dev(hw); + int set_bss_info = -1, set_sta = -1; mutex_lock(&dev->mt76.mutex); @@ -607,15 +608,18 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, * and then peer references bss_info_rfch to set bandwidth cap. */ if (changed & BSS_CHANGED_BSSID && - vif->type == NL80211_IFTYPE_STATION) { - bool join = !is_zero_ether_addr(info->bssid); - - mt7915_mcu_add_bss_info(phy, vif, join); - mt7915_mcu_add_sta(dev, vif, NULL, join); - } - + vif->type == NL80211_IFTYPE_STATION) + set_bss_info = set_sta = !is_zero_ether_addr(info->bssid); if (changed & BSS_CHANGED_ASSOC) - mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc); + set_bss_info = vif->cfg.assoc; + if (changed & BSS_CHANGED_BEACON_ENABLED && + vif->type != NL80211_IFTYPE_AP) + set_bss_info = set_sta = info->enable_beacon; + + if (set_bss_info == 1) + mt7915_mcu_add_bss_info(phy, vif, true); + if (set_sta == 1) + mt7915_mcu_add_sta(dev, vif, NULL, true); if (changed & BSS_CHANGED_ERP_CTS_PROT) mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot); @@ -629,11 +633,6 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { - mt7915_mcu_add_bss_info(phy, vif, true); - mt7915_mcu_add_sta(dev, vif, NULL, true); - } - /* ensure that enable txcmd_mode after bss_info */ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_set_tx(dev, vif); @@ -650,6 +649,42 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_FILS_DISCOVERY)) mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); + if (set_bss_info == 0) + mt7915_mcu_add_bss_info(phy, vif, false); + if (set_sta == 0) + mt7915_mcu_add_sta(dev, vif, NULL, false); + + mutex_unlock(&dev->mt76.mutex); +} + +static int +mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + int err; + + mutex_lock(&dev->mt76.mutex); + + err = mt7915_mcu_add_bss_info(phy, vif, true); + if (err) + goto out; + err = mt7915_mcu_add_sta(dev, vif, NULL, true); +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} + +static void +mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mt7915_mcu_add_sta(dev, vif, NULL, false); mutex_unlock(&dev->mt76.mutex); } @@ -1594,6 +1629,8 @@ const struct ieee80211_ops mt7915_ops = { .conf_tx = mt7915_conf_tx, .configure_filter = mt7915_configure_filter, .bss_info_changed = mt7915_bss_info_changed, + .start_ap = mt7915_start_ap, + .stop_ap = mt7915_stop_ap, .sta_add = mt7915_sta_add, .sta_remove = mt7915_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, -- cgit From d82e7c67b318e6f0399b72a9821a51e693a40381 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 29 May 2023 16:54:32 +0200 Subject: mt76: mt7996: rely on mt76_sta_stats in mt76_wcid mt76 now accounts station stats in mt76_sta_stats available in mt76_wcid struct. Get rid of mt7996 private copy. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 7 ++++--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 -- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index de1590903318..bc8b9a6fc5a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1329,9 +1329,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) } static bool -mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, - __le32 *txs_data, struct mt76_sta_stats *stats) +mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data) { + struct mt76_sta_stats *stats = &wcid->stats; struct ieee80211_supported_band *sband; struct mt76_dev *mdev = &dev->mt76; struct mt76_phy *mphy; @@ -1493,7 +1494,7 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) msta = container_of(wcid, struct mt7996_sta, wcid); - mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats); + mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data); if (!wcid->sta) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 073a9f91d9a5..7d674114653c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -1214,7 +1214,7 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) if (msta->vif->mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->stats, true); + mt76_ethtool_worker(wi, &msta->wcid.stats, true); } static diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 7b74477abbe3..fdc443b02380 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -106,8 +106,6 @@ struct mt7996_sta { unsigned long jiffies; unsigned long ampdu_state; - struct mt76_sta_stats stats; - struct mt76_connac_sta_key_conf bip; struct { -- cgit From f124ed65ab185ef6148b4cdc4207a5b0a0faa206 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 5 Jun 2023 08:51:43 +0200 Subject: wifi: mt76: mt7921: get rid of MT7921_RESET_TIMEOUT marco MT7921_RESET_TIMEOUT is never used, so get rid of it. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 523b177e23cd..7cad215cb748 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -19,7 +19,6 @@ #define MT7921_PM_TIMEOUT (HZ / 12) #define MT7921_HW_SCAN_TIMEOUT (HZ / 10) #define MT7921_WATCHDOG_TIME (HZ / 4) -#define MT7921_RESET_TIMEOUT (30 * HZ) #define MT7921_TX_RING_SIZE 2048 #define MT7921_TX_MCU_RING_SIZE 256 -- cgit From d73dab22e7a8a8f31283ef90315bff085809b5cf Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Mon, 5 Jun 2023 23:21:32 +0800 Subject: wifi: mt76: mt7996: move radio ctrl commands to proper functions Move radio enable/disable commands into functions for configuring per-phy radio. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 7d674114653c..9e5057df5f44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -43,6 +43,10 @@ int mt7996_run(struct ieee80211_hw *hw) if (ret) goto out; + ret = mt7996_mcu_set_radio_en(phy, true); + if (ret) + goto out; + ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); if (ret) goto out; @@ -82,6 +86,8 @@ static void mt7996_stop(struct ieee80211_hw *hw) mutex_lock(&dev->mt76.mutex); + mt7996_mcu_set_radio_en(phy, false); + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); mutex_unlock(&dev->mt76.mutex); @@ -190,10 +196,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - ret = mt7996_mcu_set_radio_en(phy, true); - if (ret) - goto out; - dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); @@ -253,7 +255,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, phy->monitor_vif = NULL; mt7996_mcu_add_dev_info(phy, vif, false); - mt7996_mcu_set_radio_en(phy, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); -- cgit From a32f063dfbe38a70cd670cdc2266b9fafdc998a8 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 5 Jun 2023 23:21:33 +0800 Subject: wifi: mt76: connac: add support for dsp firmware download Add FW_START_WORKING_PDA_DSP for the indication of starting DSP firmware download, which is for phy-related control. The firmware is transparent to the driver, but it's necessary for the firmware download process. Reviewed-by: Shayne Chen Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 67 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 7 +++ drivers/net/wireless/mediatek/mt76/mt7996/pci.c | 1 + 4 files changed, 42 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 7a52b68491b6..ede011e88008 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -22,6 +22,7 @@ #define FW_START_OVERRIDE BIT(0) #define FW_START_WORKING_PDA_CR4 BIT(2) +#define FW_START_WORKING_PDA_DSP BIT(3) #define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0) #define PATCH_SEC_TYPE_MASK GENMASK(15, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 88e2f9d0e513..545cc98749ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -2155,7 +2155,7 @@ out: static int mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, const struct mt7996_fw_trailer *hdr, - const u8 *data, bool is_wa) + const u8 *data, enum mt7996_ram_type type) { int i, offset = 0; u32 override = 0, option = 0; @@ -2167,8 +2167,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, region = (const struct mt7996_fw_region *)((const u8 *)hdr - (hdr->n_region - i) * sizeof(*region)); + /* DSP and WA use same mode */ mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, - region->feature_set, is_wa); + region->feature_set, + type != MT7996_RAM_TYPE_WM); len = le32_to_cpu(region->len); addr = le32_to_cpu(region->addr); @@ -2195,19 +2197,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, if (override) option |= FW_START_OVERRIDE; - if (is_wa) + if (type == MT7996_RAM_TYPE_WA) option |= FW_START_WORKING_PDA_CR4; + else if (type == MT7996_RAM_TYPE_DSP) + option |= FW_START_WORKING_PDA_DSP; return mt76_connac_mcu_start_firmware(&dev->mt76, override, option); } -static int mt7996_load_ram(struct mt7996_dev *dev) +static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type, + const char *fw_file, enum mt7996_ram_type ram_type) { const struct mt7996_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev); + ret = request_firmware(&fw, fw_file, dev->mt76.dev); if (ret) return ret; @@ -2217,37 +2222,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev) goto out; } - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n", + fw_type, hdr->fw_ver, hdr->build_date); - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false); + ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type); if (ret) { - dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); - goto out; - } - - release_firmware(fw); - - ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WA firmware\n"); + dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type); goto out; } @@ -2261,6 +2242,24 @@ out: return ret; } +static int mt7996_load_ram(struct mt7996_dev *dev) +{ + int ret; + + ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM, + MT7996_RAM_TYPE_WM); + if (ret) + return ret; + + ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP, + MT7996_RAM_TYPE_DSP); + if (ret) + return ret; + + return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA, + MT7996_RAM_TYPE_WA); +} + static int mt7996_firmware_state(struct mt7996_dev *dev, bool wa) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index fdc443b02380..ae47412172eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -29,6 +29,7 @@ #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin" #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin" +#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin" #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin" #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin" @@ -52,6 +53,12 @@ struct mt7996_sta; struct mt7996_dfs_pulse; struct mt7996_dfs_pattern; +enum mt7996_ram_type { + MT7996_RAM_TYPE_WM, + MT7996_RAM_TYPE_WA, + MT7996_RAM_TYPE_DSP, +}; + enum mt7996_txq_id { MT7996_TXQ_FWDL = 16, MT7996_TXQ_MCU_WM, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c index 64aee3fb5445..c5301050ff8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table); MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table); MODULE_FIRMWARE(MT7996_FIRMWARE_WA); MODULE_FIRMWARE(MT7996_FIRMWARE_WM); +MODULE_FIRMWARE(MT7996_FIRMWARE_DSP); MODULE_FIRMWARE(MT7996_ROM_PATCH); -- cgit From cc945b546227423488fe4be0ab92fd126b703246 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 5 Jun 2023 23:21:34 +0800 Subject: wifi: mt76: mt7996: fix bss wlan_idx when sending bss_info command The bmc_tx_wlan_idx should be the wlan_idx of the current bss rather than peer AP's wlan_idx, otherwise there will appear some frame decryption problems on station mode. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Reviewed-by: Shayne Chen Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 545cc98749ac..6706d38cf4cf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -712,6 +712,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct cfg80211_chan_def *chandef = &phy->chandef; struct mt76_connac_bss_basic_tlv *bss; u32 type = CONNECTION_INFRA_AP; + u16 sta_wlan_idx = wlan_idx; struct tlv *tlv; int idx; @@ -731,7 +732,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct mt76_wcid *wcid; wcid = (struct mt76_wcid *)sta->drv_priv; - wlan_idx = wcid->idx; + sta_wlan_idx = wcid->idx; } rcu_read_unlock(); } @@ -751,7 +752,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); bss->dtim_period = vif->bss_conf.dtim_period; bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); - bss->sta_idx = cpu_to_le16(wlan_idx); + bss->sta_idx = cpu_to_le16(sta_wlan_idx); bss->conn_type = cpu_to_le32(type); bss->omac_idx = mvif->omac_idx; bss->band_idx = mvif->band_idx; -- cgit From 2b8ca09062b1bee0253b121c48345505df0c84aa Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 5 Jun 2023 23:21:36 +0800 Subject: wifi: mt76: mt7996: enable VHT extended NSS BW feature Set SUPPORTS_VHT_EXT_NSS_BW to let the max BW capability correctly be parsed by different devices. Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 3569fef20cd9..38ff33a7fc12 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -218,6 +218,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; phy->mt76->sband_5g.sband.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_1; + + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); } mt76_set_stream_caps(phy->mt76, true); -- cgit From 83a10ae2d4c5b00fd597a7a7a5e7ceefef9bd116 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 5 Jun 2023 23:21:37 +0800 Subject: wifi: mt76: connac: add support to set ifs time by mcu command There's a race between driver and fw on some tx/rx control registers when setting ifs, which will cause accidental hw queue pause problems. Avoid this by setting ifs time with bss_info mcu command. Reviewed-by: Shayne Chen Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 27 +------------ drivers/net/wireless/mediatek/mt76/mt7996/main.c | 5 +-- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 46 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 17 ++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 +- 6 files changed, 70 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index ede011e88008..dcbb608360bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1289,6 +1289,7 @@ enum { UNI_BSS_INFO_UAPSD = 19, UNI_BSS_INFO_PS = 21, UNI_BSS_INFO_BCNFT = 22, + UNI_BSS_INFO_IFS_TIME = 23, UNI_BSS_INFO_OFFLOAD = 25, UNI_BSS_INFO_MLD = 26, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index bc8b9a6fc5a1..a39bb39af540 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1615,20 +1615,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy) mt7996_mcu_get_chan_mib_info(phy, true); } -void mt7996_mac_set_timing(struct mt7996_phy *phy) +void mt7996_mac_set_coverage_class(struct mt7996_phy *phy) { s16 coverage_class = phy->coverage_class; struct mt7996_dev *dev = phy->dev; struct mt7996_phy *phy2 = mt7996_phy2(dev); struct mt7996_phy *phy3 = mt7996_phy3(dev); - u32 val, reg_offset; + u32 reg_offset; u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); u8 band_idx = phy->mt76->band_idx; int offset; - bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; @@ -1641,34 +1640,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy) coverage_class = max_t(s16, coverage_class, phy3->coverage_class); - mt76_set(dev, MT_ARB_SCR(band_idx), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); - udelay(1); - offset = 3 * coverage_class; reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); - mt76_wr(dev, MT_TMAC_ICR0(band_idx), - FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | - FIELD_PREP(MT_IFS_RIFS, 2) | - FIELD_PREP(MT_IFS_SIFS, 10) | - FIELD_PREP(MT_IFS_SLOT, phy->slottime)); - - if (!a_band) - mt76_wr(dev, MT_TMAC_ICR1(band_idx), - FIELD_PREP(MT_IFS_EIFS_CCK, 314)); - - if (phy->slottime < 20 || a_band) - val = MT7996_CFEND_RATE_DEFAULT; - else - val = MT7996_CFEND_RATE_11B; - - mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val); - mt76_clear(dev, MT_ARB_SCR(band_idx), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); } void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 9e5057df5f44..f173d197fcf6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -287,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy) if (ret) goto out; - mt7996_mac_set_timing(phy); ret = mt7996_dfs_init_radar_detector(phy); mt7996_mac_cca_stats_reset(phy); @@ -584,7 +583,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, if (slottime != phy->slottime) { phy->slottime = slottime; - mt7996_mac_set_timing(phy); + mt7996_mcu_set_timing(phy, vif); } } @@ -927,7 +926,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) mutex_lock(&dev->mt76.mutex); phy->coverage_class = max_t(s16, coverage_class, 0); - mt7996_mac_set_timing(phy); + mt7996_mac_set_coverage_class(phy); mutex_unlock(&dev->mt76.mutex); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 6706d38cf4cf..0ede9769a8e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -701,6 +701,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, sizeof(req), true); } +static void +mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mvif->phy; + struct bss_ifs_time_tlv *ifs_time; + struct tlv *tlv; + bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time)); + + ifs_time = (struct bss_ifs_time_tlv *)tlv; + ifs_time->slot_valid = true; + ifs_time->sifs_valid = true; + ifs_time->rifs_valid = true; + ifs_time->eifs_valid = true; + + ifs_time->slot_time = cpu_to_le16(phy->slottime); + ifs_time->sifs_time = cpu_to_le16(10); + ifs_time->rifs_time = cpu_to_le16(2); + ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84); + + if (is_2ghz) { + ifs_time->eifs_cck_valid = true; + ifs_time->eifs_cck_time = cpu_to_le16(314); + } +} + static int mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, @@ -826,6 +854,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, mt7996_mcu_bss_bmc_tlv(skb, vif, phy); mt7996_mcu_bss_ra_tlv(skb, vif, phy); mt7996_mcu_bss_txcmd_tlv(skb, true); + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); if (vif->bss_conf.he_support) mt7996_mcu_bss_he_tlv(skb, vif, phy); @@ -838,6 +867,23 @@ out: MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_dev *dev = phy->dev; + struct sk_buff *skb; + + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + MT7996_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); +} + static int mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index d7075a4d0667..078f82858621 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -317,6 +317,22 @@ struct bss_sec_tlv { u8 __rsv2[1]; } __packed; +struct bss_ifs_time_tlv { + __le16 tag; + __le16 len; + u8 slot_valid; + u8 sifs_valid; + u8 rifs_valid; + u8 eifs_valid; + __le16 slot_time; + __le16 sifs_time; + __le16 rifs_time; + __le16 eifs_time; + u8 eifs_cck_valid; + u8 rsv; + __le16 eifs_cck_time; +} __packed; + struct bss_power_save { __le16 tag; __le16 len; @@ -552,6 +568,7 @@ enum { sizeof(struct bss_txcmd_tlv) + \ sizeof(struct bss_power_save) + \ sizeof(struct bss_sec_tlv) + \ + sizeof(struct bss_ifs_time_tlv) + \ sizeof(struct bss_mld_tlv)) #define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index ae47412172eb..7862e66efc85 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -408,6 +408,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, const struct mt7996_dfs_pattern *pattern); int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable); int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val); +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif); int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch); int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, u8 rx_sel, u8 val); @@ -471,7 +472,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed); -void mt7996_mac_set_timing(struct mt7996_phy *phy); +void mt7996_mac_set_coverage_class(struct mt7996_phy *phy); int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, -- cgit From 9ffe0d5690ed916e09baad2cc9ee7ec65b110038 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Mon, 5 Jun 2023 23:21:38 +0800 Subject: wifi: mt76: mt7996: use correct phy for background radar event If driver directly uses the band_idx reported from the radar event to access mt76_phy array, it will get the wrong phy for background radar. Fix this by adjusting the statement. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: StanleyYP Wang Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 0ede9769a8e8..20519bffce21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) return; - mphy = dev->mt76.phys[r->band_idx]; + if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2) + mphy = dev->rdd2_phy->mt76; + else + mphy = dev->mt76.phys[r->band_idx]; + if (!mphy) return; -- cgit From 1634de418b3048c5f435b6ffd37f75943c554c04 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Mon, 5 Jun 2023 23:21:39 +0800 Subject: wifi: mt76: mt7996: fix WA event ring size Fix rx ring size of WA event to get rid of event loss and queue overflow problems. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: StanleyYP Wang Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 99b00a135711..586e247a1e06 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -308,7 +308,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) /* event from WA */ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], MT_RXQ_ID(MT_RXQ_MCU_WA), - MT7996_RX_MCU_RING_SIZE, + MT7996_RX_MCU_RING_SIZE_WA, MT_RX_BUF_SIZE, MT_RXQ_RING_BASE(MT_RXQ_MCU_WA)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 7862e66efc85..d93762c3c587 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -26,6 +26,7 @@ #define MT7996_RX_RING_SIZE 1536 #define MT7996_RX_MCU_RING_SIZE 512 +#define MT7996_RX_MCU_RING_SIZE_WA 1024 #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin" #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin" -- cgit From 94f096a14af2647d875ae6a9a09d32eb43393184 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Mon, 5 Jun 2023 23:21:40 +0800 Subject: wifi: mt76: mt7996: add muru support Add sta_rec_muru() fw command to support MU-MIMO and OFDMA features. Signed-off-by: MeiChia Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 3 +- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 56 +++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index dcbb608360bf..4543e5bf0482 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -519,7 +519,8 @@ struct sta_rec_muru { u8 uo_ra; u8 he_2x996_tone; u8 rx_t_frame_11ac; - u8 rsv[3]; + u8 rx_ctrl_frame_to_mbss; + u8 rsv[2]; } ofdma_ul; struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 20519bffce21..611f6450520b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1101,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, } } +static void +mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct sta_rec_muru *muru; + struct tlv *tlv; + + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); + + muru = (struct sta_rec_muru *)tlv; + muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer || + vif->bss_conf.he_mu_beamformer || + vif->bss_conf.vht_mu_beamformer || + vif->bss_conf.vht_mu_beamformee; + muru->cfg.ofdma_dl_en = true; + + if (sta->deflink.vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + + if (!sta->deflink.he_cap.has_he) + return; + + muru->mimo_dl.partial_bw_dl_mimo = + HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]); + + muru->mimo_ul.full_ul_mimo = + HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]); + muru->mimo_ul.partial_ul_mimo = + HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]); + + muru->ofdma_dl.punc_pream_rx = + HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); + muru->ofdma_dl.he_20m_in_40m_2g = + HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]); + muru->ofdma_dl.he_20m_in_160m = + HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + muru->ofdma_dl.he_80m_in_160m = + HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + + muru->ofdma_ul.t_frame_dur = + HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]); + muru->ofdma_ul.mu_cascading = + HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]); + muru->ofdma_ul.uo_ra = + HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]); +} + static inline bool mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) @@ -1778,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, mt7996_mcu_sta_he_6g_tlv(skb, sta); /* starec eht */ mt7996_mcu_sta_eht_tlv(skb, sta); - /* TODO: starec muru */ + /* starec muru */ + mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta); /* starec bfee */ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta); /* starec hdr trans */ -- cgit From 037ae6d6d6d547c753334460c9d8d61a7db261df Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Mon, 5 Jun 2023 23:21:41 +0800 Subject: wifi: mt76: mt7996: increase tx token size Align tx token size to proprietary driver, which can improve peak throughput under MU performance tests. Signed-off-by: Howard Hsu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index d93762c3c587..23de7508c954 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -36,7 +36,7 @@ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin" #define MT7996_EEPROM_SIZE 7680 #define MT7996_EEPROM_BLOCK_SIZE 16 -#define MT7996_TOKEN_SIZE 8192 +#define MT7996_TOKEN_SIZE 16384 #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ -- cgit From fbba711c3de73c57b476767ba0d5ae1e8b2faa8f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:18 +0200 Subject: wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev sta_poll_list and sta_poll_lock are used by most of the drivers, so move them in mt76_dev structure. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 2 + drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 - drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 47 ++++++++++++---------- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 12 +++--- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2 - 6 files changed, 36 insertions(+), 32 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 24ebf0504a3b..c0ff36a98bed 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -661,6 +661,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size, idr_init(&dev->rx_token); INIT_LIST_HEAD(&dev->wcid_list); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); INIT_LIST_HEAD(&dev->txwi_cache); INIT_LIST_HEAD(&dev->rxwi_cache); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index c11a417c5e37..6becfcebb926 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -823,6 +823,9 @@ struct mt76_dev { struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; struct list_head wcid_list; + struct list_head sta_poll_list; + spinlock_t sta_poll_lock; + u32 rev; struct tasklet_struct pre_tbtt_tasklet; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 07cdf14c515f..fffab468efeb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -1185,9 +1185,7 @@ int mt7915_register_device(struct mt7915_dev *dev) INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work); INIT_LIST_HEAD(&dev->sta_rc_list); - INIT_LIST_HEAD(&dev->sta_poll_list); INIT_LIST_HEAD(&dev->twt_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 2bc2fefa1cd0..8ed217ee592e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -105,9 +105,9 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) LIST_HEAD(sta_poll_list); int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); rcu_read_lock(); @@ -118,15 +118,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) s8 rssi[4]; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, struct mt7915_sta, poll_list); list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -326,10 +326,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, if (status->wcid) { msta = container_of(status->wcid, struct mt7915_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } status->freq = mphy->chandef.chan->center_freq; @@ -892,10 +893,11 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, msta = container_of(wcid, struct mt7915_sta, wcid); sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); } } @@ -987,10 +989,11 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7915_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } @@ -1099,10 +1102,10 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); @@ -2039,7 +2042,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) u32 changed; LIST_HEAD(list); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); list_splice_init(&dev->sta_rc_list, &list); while (!list_empty(&list)) { @@ -2047,7 +2050,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) list_del_init(&msta->rc_list); changed = msta->changed; msta->changed = 0; - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); @@ -2060,10 +2063,10 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) if (changed & IEEE80211_RC_SMPS_CHANGED) mt7915_mcu_add_smps(dev, vif, sta); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); } - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } void mt7915_mac_work(struct work_struct *work) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 679397dddf0f..bccb00775299 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -308,10 +308,10 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); } @@ -749,12 +749,12 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) mt7915_mac_twt_teardown_flow(dev, msta, i); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); } static void mt7915_tx(struct ieee80211_hw *hw, @@ -1109,11 +1109,11 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) struct mt7915_dev *dev = msta->vif->phy->dev; u32 *changed = data; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); msta->changed |= *changed; if (list_empty(&msta->rc_list)) list_add_tail(&msta->rc_list, &dev->sta_rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } static void mt7915_sta_rc_update(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 93b536e01eb5..fe5f90822b34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -274,9 +274,7 @@ struct mt7915_dev { #endif struct list_head sta_rc_list; - struct list_head sta_poll_list; struct list_head twt_list; - spinlock_t sta_poll_lock; u32 hw_pattern; -- cgit From c55e898bd9ca980e3e68152e7630aacf517c1648 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:19 +0200 Subject: wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure and get rid of private copies. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 18 +++++++++--------- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 3 --- 4 files changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 9a2e632d577a..0762de3ce5ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -500,8 +500,6 @@ int mt7603_register_device(struct mt7603_dev *dev) bus_ops->rmw = mt7603_rmw; dev->mt76.bus = bus_ops; - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); spin_lock_init(&dev->ps_lock); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 12e0af52082a..ac8a67e10a4d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -412,16 +412,16 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) while (1) { bool clear = false; - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&dev->sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&dev->mt76.sta_poll_list)) { + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } - msta = list_first_entry(&dev->sta_poll_list, struct mt7603_sta, - poll_list); + msta = list_first_entry(&dev->mt76.sta_poll_list, + struct mt7603_sta, poll_list); list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7603_wtbl4_addr(msta->wcid.idx); for (i = 0; i < 4; i++) { @@ -1268,9 +1268,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) sta = wcid_to_sta(wcid); if (list_empty(&msta->poll_list)) { - spin_lock_bh(&dev->sta_poll_lock); - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 1b1358c6bb46..6d2295cf5753 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -100,10 +100,10 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mutex_lock(&dev->mt76.mutex); dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); @@ -388,10 +388,10 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7603_filter_tx(dev, wcid->idx, true); spin_unlock_bh(&dev->ps_lock); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); mt7603_wtbl_clear(dev, wcid->idx); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 7c3be596da09..689922d133e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -110,9 +110,6 @@ struct mt7603_dev { u32 rxfilter; - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - struct mt7603_sta global_sta; u32 agc0, agc3; -- cgit From 57a3fac664ce192359271d7f6ddf1d55dff80cbc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:20 +0200 Subject: wifi: mt76: mt7615: rely on shared sta_poll_list and sta_poll_lock Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure and get rid of private copies. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 23 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 3 --- 4 files changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index ab475c841818..18a50ccff106 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -628,8 +628,6 @@ void mt7615_init_device(struct mt7615_dev *dev) INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work); skb_queue_head_init(&dev->phy.scan_event_list); skb_queue_head_init(&dev->coredump.msg_list); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); init_waitqueue_head(&dev->phy.roc_wait); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 64002484ccad..f275c0fb0bf6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -387,10 +387,11 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) struct mt7615_sta *msta; msta = container_of(status->wcid, struct mt7615_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && @@ -905,9 +906,9 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) int i; INIT_LIST_HEAD(&sta_poll_list); - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); while (!list_empty(&sta_poll_list)) { bool clear = false; @@ -915,9 +916,9 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) msta = list_first_entry(&sta_poll_list, struct mt7615_sta, poll_list); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; @@ -1514,10 +1515,10 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) msta = container_of(wcid, struct mt7615_sta, wcid); sta = wcid_to_sta(wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data)) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 4167aafa5b0e..e14f1f30ac31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -274,10 +274,10 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_mutex_release(dev); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); } @@ -705,10 +705,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mt7615_mcu_add_bss_info(phy, vif, sta, false); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); mt76_connac_power_save_sched(phy->mt76, &dev->pm); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 582d1b5b7cb3..765ba986f07c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -262,9 +262,6 @@ struct mt7615_dev { wait_queue_head_t reset_wait; u32 reset_state; - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - struct { u8 n_pulses; u32 period; -- cgit From ea0f3867c017987bf4d6060e7665ecfffadb8cd9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:21 +0200 Subject: wifi: mt76: mt7996: rely on shared sta_poll_list and sta_poll_lock Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure and get rid of private copies. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 40 ++++++++++++---------- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++---- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 -- 4 files changed, 27 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 38ff33a7fc12..e297e7cb3a7a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -856,9 +856,7 @@ int mt7996_register_device(struct mt7996_dev *dev) INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work); INIT_LIST_HEAD(&dev->sta_rc_list); - INIT_LIST_HEAD(&dev->sta_poll_list); INIT_LIST_HEAD(&dev->twt_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7996_mac_reset_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index a39bb39af540..46b1dbcb4b45 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -111,9 +111,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) LIST_HEAD(sta_poll_list); int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); rcu_read_lock(); @@ -124,15 +124,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) s8 rssi[4]; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, struct mt7996_sta, poll_list); list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -681,10 +681,11 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) struct mt7996_sta *msta; msta = container_of(status->wcid, struct mt7996_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } status->freq = mphy->chandef.chan->center_freq; @@ -1291,10 +1292,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7996_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } @@ -1499,10 +1501,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); @@ -2325,7 +2327,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) u32 changed; LIST_HEAD(list); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); list_splice_init(&dev->sta_rc_list, &list); while (!list_empty(&list)) { @@ -2333,7 +2335,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) list_del_init(&msta->rc_list); changed = msta->changed; msta->changed = 0; - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); @@ -2345,10 +2347,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) /* TODO: smps change */ - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); } - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } void mt7996_mac_work(struct work_struct *work) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index f173d197fcf6..975aac210a7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -263,10 +263,10 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); } @@ -689,12 +689,12 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) mt7996_mac_twt_teardown_flow(dev, msta, i); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); } static void mt7996_tx(struct ieee80211_hw *hw, @@ -1005,11 +1005,11 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta) struct mt7996_dev *dev = msta->vif->phy->dev; u32 *changed = data; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); msta->changed |= *changed; if (list_empty(&msta->rc_list)) list_add_tail(&msta->rc_list, &dev->sta_rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } static void mt7996_sta_rc_update(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 23de7508c954..b45a9eecd71e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -224,9 +224,7 @@ struct mt7996_dev { #endif struct list_head sta_rc_list; - struct list_head sta_poll_list; struct list_head twt_list; - spinlock_t sta_poll_lock; u32 hw_pattern; -- cgit From 419acc515dd32039da1ac48b13077912e9b1c2c4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:22 +0200 Subject: wifi: mt76: mt7921: rely on shared sta_poll_list and sta_poll_lock Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure and get rid of private copies. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 -- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 32 ++++++++++++---------- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 8 +++--- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 -- 4 files changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 73a31efc08da..94b7cdfd018b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -456,8 +456,6 @@ int mt7921_register_device(struct mt7921_dev *dev) #endif skb_queue_head_init(&dev->phy.scan_event_list); skb_queue_head_init(&dev->coredump.msg_list); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); INIT_WORK(&dev->init_work, mt7921_init_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 49f44b1e8d51..773db10a36f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -68,9 +68,9 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) s8 rssi[4]; int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); while (true) { bool clear = false; @@ -78,15 +78,15 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) u16 idx; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, struct mt7921_sta, poll_list); list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_AC0_CTT_OFFSET); @@ -280,10 +280,11 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) if (status->wcid) { msta = container_of(status->wcid, struct mt7921_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } mt7921_get_status_freq_info(dev, mphy, status, chfreq); @@ -566,10 +567,10 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); @@ -647,10 +648,11 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7921_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + list_add_tail(&msta->poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index d520e68a8c82..a5e666690747 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -357,10 +357,10 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt7921_mutex_release(dev); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); } @@ -842,10 +842,10 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mvif->ctx); } - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->poll_list)) list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 7cad215cb748..20803968c779 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -274,9 +274,6 @@ struct mt7921_dev { bool hw_init_done:1; bool fw_assert:1; - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - struct work_struct init_work; u8 fw_debug; -- cgit From b73e1d9245eba06012792cd3c9ca96dad23904ee Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:23 +0200 Subject: wifi: mt76: mt7915: move poll_list in mt76_wcid poll_list field is used by most of the drivers, so move it in mt76_wcid structure. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 20 ++++++++++---------- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 - 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6becfcebb926..97e72cf3bc8e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -336,6 +336,8 @@ struct mt76_wcid { struct idr pktid; struct mt76_sta_stats stats; + + struct list_head poll_list; }; struct mt76_txq { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 8ed217ee592e..99383e4e113a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -124,8 +124,8 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) break; } msta = list_first_entry(&sta_poll_list, - struct mt7915_sta, poll_list); - list_del_init(&msta->poll_list); + struct mt7915_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -327,8 +327,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, if (status->wcid) { msta = container_of(status->wcid, struct mt7915_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); } @@ -894,8 +894,8 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &mdev->sta_poll_list); spin_unlock_bh(&mdev->sta_poll_lock); } @@ -990,8 +990,8 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) msta = container_of(wcid, struct mt7915_sta, wcid); spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &mdev->sta_poll_list); spin_unlock_bh(&mdev->sta_poll_lock); continue; @@ -1103,8 +1103,8 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) goto out; spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); out: diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index bccb00775299..f2f82eb61713 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -248,7 +248,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = ext_phy; mvif->sta.wcid.hw_key_idx = -1; @@ -309,8 +309,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); @@ -714,7 +714,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, return -ENOSPC; INIT_LIST_HEAD(&msta->rc_list); - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -750,8 +750,8 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7915_mac_twt_teardown_flow(dev, msta, i); spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); spin_unlock_bh(&mdev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index fe5f90822b34..a76dcceb0ec1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -136,7 +136,6 @@ struct mt7915_sta { struct mt7915_vif *vif; - struct list_head poll_list; struct list_head rc_list; u32 airtime_ac[8]; -- cgit From 2d29058e396a273ebb681559b135ff8bcb005e7c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:24 +0200 Subject: wifi: mt76: mt7603: rely on shared poll_list field Rely on poll_list field in mt76_wcid structure and get rid of private copy. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 1 - 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index ac8a67e10a4d..de11557eb04c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -419,8 +419,8 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) } msta = list_first_entry(&dev->mt76.sta_poll_list, - struct mt7603_sta, poll_list); - list_del_init(&msta->poll_list); + struct mt7603_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7603_wtbl4_addr(msta->wcid.idx); @@ -1267,9 +1267,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) msta = container_of(wcid, struct mt7603_sta, wcid); sta = wcid_to_sta(wcid); - if (list_empty(&msta->poll_list)) { + if (list_empty(&msta->wcid.poll_list)) { spin_lock_bh(&dev->mt76.sta_poll_lock); - list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 6d2295cf5753..1d4893410ca5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -66,7 +66,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; dev->mt76.vif_mask |= BIT_ULL(mvif->idx); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; mt76_packet_id_init(&mvif->sta.wcid); @@ -101,8 +101,8 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) rcu_assign_pointer(dev->mt76.wcid[idx], NULL); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mutex_lock(&dev->mt76.mutex); @@ -351,7 +351,7 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); __skb_queue_head_init(&msta->psq); msta->ps = ~0; msta->smps = ~0; @@ -389,8 +389,8 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, spin_unlock_bh(&dev->ps_lock); spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&mdev->sta_poll_lock); mt7603_wtbl_clear(dev, wcid->idx); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 689922d133e7..354b189862f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -64,7 +64,6 @@ struct mt7603_sta { struct mt7603_vif *vif; - struct list_head poll_list; u32 tx_airtime_ac[4]; struct sk_buff_head psq; -- cgit From 9d599f2d654639198478fb6e0a8bd381b283730e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:25 +0200 Subject: wifi: mt76: mt7615: rely on shared poll_list field Rely on poll_list field in mt76_wcid structure and get rid of private copy. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7615/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 - 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index f275c0fb0bf6..7ba789834e8d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -388,8 +388,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) msta = container_of(status->wcid, struct mt7615_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); } @@ -914,10 +914,10 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) bool clear = false; msta = list_first_entry(&sta_poll_list, struct mt7615_sta, - poll_list); + wcid.poll_list); spin_lock_bh(&dev->mt76.sta_poll_lock); - list_del_init(&msta->poll_list); + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; @@ -1516,8 +1516,8 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) sta = wcid_to_sta(wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index e14f1f30ac31..200b1752ca77 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -222,7 +222,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, idx = MT7615_WTBL_RESERVED - mvif->mt76.idx; - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -275,8 +275,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_mutex_release(dev); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); @@ -657,7 +657,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -706,8 +706,8 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7615_mcu_add_bss_info(phy, vif, sta, false); spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&mdev->sta_poll_lock); mt76_connac_power_save_sched(phy->mt76, &dev->pm); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 765ba986f07c..a20322aae967 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -125,7 +125,6 @@ struct mt7615_sta { struct mt7615_vif *vif; - struct list_head poll_list; u32 airtime_ac[8]; struct ieee80211_tx_rate rates[4]; -- cgit From e3b0311fcc3a882724937cbe276b1969c9975711 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:26 +0200 Subject: wifi: mt76: mt7996: rely on shared poll_list field Rely on poll_list field in mt76_wcid structure and get rid of private copy. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 16 ++++++++-------- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 - 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 46b1dbcb4b45..2adc2599d64d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -130,8 +130,8 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) break; } msta = list_first_entry(&sta_poll_list, - struct mt7996_sta, poll_list); - list_del_init(&msta->poll_list); + struct mt7996_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -682,8 +682,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) msta = container_of(status->wcid, struct mt7996_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); } @@ -1293,8 +1293,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) msta = container_of(wcid, struct mt7996_sta, wcid); spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &mdev->sta_poll_list); spin_unlock_bh(&mdev->sta_poll_lock); continue; @@ -1502,8 +1502,8 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) goto out; spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); out: diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 975aac210a7d..69b47136b8d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -202,7 +202,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, idx = MT7996_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -264,8 +264,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); @@ -654,7 +654,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, return -ENOSPC; INIT_LIST_HEAD(&msta->rc_list); - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -690,8 +690,8 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7996_mac_twt_teardown_flow(dev, msta, i); spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); spin_unlock_bh(&mdev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index b45a9eecd71e..e67d57a84426 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -103,7 +103,6 @@ struct mt7996_sta { struct mt7996_vif *vif; - struct list_head poll_list; struct list_head rc_list; u32 airtime_ac[8]; -- cgit From d17a2fe830d7c458166a06ca222ed7f4d94c671f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:27 +0200 Subject: wifi: mt76: mt7921: rely on shared poll_list field Rely on poll_list field in mt76_wcid structure and get rid of private copy. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 16 ++++++++-------- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 773db10a36f3..c00342e87405 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -84,8 +84,8 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) break; } msta = list_first_entry(&sta_poll_list, - struct mt7921_sta, poll_list); - list_del_init(&msta->poll_list); + struct mt7921_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -281,8 +281,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) if (status->wcid) { msta = container_of(status->wcid, struct mt7921_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); } @@ -568,8 +568,8 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) goto out; spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); out: @@ -649,8 +649,8 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) msta = container_of(wcid, struct mt7921_sta, wcid); spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &mdev->sta_poll_list); spin_unlock_bh(&mdev->sta_poll_lock); continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index a5e666690747..49053d05c164 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -313,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, idx = MT7921_WTBL_RESERVED - mvif->mt76.idx; - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -358,8 +358,8 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, mt7921_mutex_release(dev); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); @@ -764,7 +764,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -843,8 +843,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, } spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_connac_power_save_sched(&dev->mphy, &dev->pm); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 20803968c779..fe4de77a0c07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -150,7 +150,6 @@ struct mt7921_sta { struct mt7921_vif *vif; - struct list_head poll_list; u32 airtime_ac[8]; int ack_signal; -- cgit From ef591d74d4ba1273100d790f79059384f4547857 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:28 +0200 Subject: wifi: mt76: move ampdu_state in mt76_wcid ampdu_state field is used by most of the drivers, so move it in mt76_wcid structure. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 - drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 - 10 files changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 97e72cf3bc8e..8ec77682d8e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -316,6 +316,7 @@ struct mt76_wcid { int inactive_count; struct rate_info rate; + unsigned long ampdu_state; u16 idx; u8 hw_key_idx; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 99383e4e113a..b58e8275feef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -863,7 +863,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) return; msta = (struct mt7915_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) + if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index f2f82eb61713..decb60aac9dd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -836,16 +836,16 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7915_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7915_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index a76dcceb0ec1..066934249a09 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -144,7 +144,6 @@ struct mt7915_sta { unsigned long changed; unsigned long jiffies; - unsigned long ampdu_state; struct mt76_connac_sta_key_conf bip; struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index c00342e87405..3e589748e1a3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -531,7 +531,7 @@ static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) return; msta = (struct mt7921_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) + if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 49053d05c164..87067ac367eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -954,16 +954,16 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index fe4de77a0c07..2694ecb1fdcb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -156,7 +156,6 @@ struct mt7921_sta { struct ewma_avg_signal avg_ack_signal; unsigned long last_txs; - unsigned long ampdu_state; struct mt76_connac_sta_key_conf bip; }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 2adc2599d64d..dfe70e0ff329 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1204,7 +1204,7 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) return; msta = (struct mt7996_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) + if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 69b47136b8d7..54858cfc9342 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -774,16 +774,16 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7996_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7996_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index e67d57a84426..79cb71c16264 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -111,7 +111,6 @@ struct mt7996_sta { unsigned long changed; unsigned long jiffies; - unsigned long ampdu_state; struct mt76_connac_sta_key_conf bip; -- cgit From c8e370feb361896376acc871e68408613034437b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:29 +0200 Subject: mt76: connac: move more mt7921/mt7915 mac shared code in connac lib Move the following routines in mt76-connac lib since they are shared between mt7915 and mt7921: - mt76_connac2_tx_check_aggr - mt76_connac2_txwi_free - mt76_connac2_tx_token_put Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 5 ++ .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 82 +++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 91 +--------------------- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 - drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 59 +------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 4 - drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 16 +--- 9 files changed, 96 insertions(+), 166 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 77ca8f057d61..d3bb9114160f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -419,5 +419,10 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, struct mt76_rx_status *status, struct ieee80211_supported_band *sband, __le32 *rxv, u8 *mode); +void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi); +void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, + struct list_head *free_list); +void mt76_connac2_tx_token_put(struct mt76_dev *dev); #endif /* __MT76_CONNAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index f481ca3a0db8..ee5177fd6dde 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -1112,3 +1112,85 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, return 0; } EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate); + +void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +{ + struct mt76_wcid *wcid; + u16 fc, tid; + u32 val; + + if (!sta || + !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) + return; + + tid = le32_get_bits(txwi[1], MT_TXD1_TID); + if (tid >= 6) /* skip VO queue */ + return; + + val = le32_to_cpu(txwi[2]); + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; + if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) + return; + + wcid = (struct mt76_wcid *)sta->drv_priv; + if (!test_and_set_bit(tid, &wcid->ampdu_state)) + ieee80211_start_tx_ba_session(sta, tid, 0); +} +EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr); + +void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, + struct list_head *free_list) +{ + struct mt76_wcid *wcid; + __le32 *txwi; + u16 wcid_idx; + + mt76_connac_txp_skb_unmap(dev, t); + if (!t->skb) + goto out; + + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t); + if (sta) { + wcid = (struct mt76_wcid *)sta->drv_priv; + wcid_idx = wcid->idx; + } else { + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(dev->wcid[wcid_idx]); + + if (wcid && wcid->sta) { + sta = container_of((void *)wcid, struct ieee80211_sta, + drv_priv); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&wcid->poll_list)) + list_add_tail(&wcid->poll_list, + &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + } + } + + if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt76_connac2_tx_check_aggr(sta, txwi); + + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list); +out: + t->skb = NULL; + mt76_put_txwi(dev, t); +} +EXPORT_SYMBOL_GPL(mt76_connac2_txwi_free); + +void mt76_connac2_tx_token_put(struct mt76_dev *dev) +{ + struct mt76_txwi_cache *txwi; + int id; + + spin_lock_bh(&dev->token_lock); + idr_for_each_entry(&dev->token, txwi, id) { + mt76_connac2_txwi_free(dev, txwi, NULL, NULL); + dev->token_count--; + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); +} +EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index fffab468efeb..ee976657bfc3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -1166,7 +1166,7 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) static void mt7915_stop_hardware(struct mt7915_dev *dev) { mt7915_mcu_exit(dev); - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); mt7915_dma_cleanup(dev); tasklet_disable(&dev->mt76.irq_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index b58e8275feef..b8b0c0fda752 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -842,75 +842,6 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) return MT_TXD_SIZE + sizeof(*txp); } -static void -mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) -{ - struct mt7915_sta *msta; - u16 fc, tid; - u32 val; - - if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) - return; - - tid = le32_get_bits(txwi[1], MT_TXD1_TID); - if (tid >= 6) /* skip VO queue */ - return; - - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; - if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) - return; - - msta = (struct mt7915_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) - ieee80211_start_tx_ba_session(sta, tid, 0); -} - -static void -mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, struct list_head *free_list) -{ - struct mt76_dev *mdev = &dev->mt76; - struct mt7915_sta *msta; - struct mt76_wcid *wcid; - __le32 *txwi; - u16 wcid_idx; - - mt76_connac_txp_skb_unmap(mdev, t); - if (!t->skb) - goto out; - - txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); - if (sta) { - wcid = (struct mt76_wcid *)sta->drv_priv; - wcid_idx = wcid->idx; - } else { - wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]); - - if (wcid && wcid->sta) { - msta = container_of(wcid, struct mt7915_sta, wcid); - sta = container_of((void *)msta, struct ieee80211_sta, - drv_priv); - spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &mdev->sta_poll_list); - spin_unlock_bh(&mdev->sta_poll_lock); - } - } - - if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7915_tx_check_aggr(sta, txwi); - - __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); - -out: - t->skb = NULL; - mt76_put_txwi(mdev, t); -} - static void mt7915_mac_tx_free_prepare(struct mt7915_dev *dev) { @@ -1031,7 +962,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) if (!txwi) continue; - mt7915_txwi_free(dev, txwi, sta, &free_list); + mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); } } @@ -1063,7 +994,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) if (!txwi) continue; - mt7915_txwi_free(dev, txwi, NULL, &free_list); + mt76_connac2_txwi_free(mdev, txwi, NULL, &free_list); } mt7915_mac_tx_free_done(dev, &free_list, wake); @@ -1378,20 +1309,6 @@ mt7915_update_beacons(struct mt7915_dev *dev) mt7915_update_vif_beacon, mphy_ext->hw); } -void mt7915_tx_token_put(struct mt7915_dev *dev) -{ - struct mt76_txwi_cache *txwi; - int id; - - spin_lock_bh(&dev->mt76.token_lock); - idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7915_txwi_free(dev, txwi, NULL, NULL); - dev->mt76.token_count--; - } - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); -} - static int mt7915_mac_restart(struct mt7915_dev *dev) { @@ -1440,7 +1357,7 @@ mt7915_mac_restart(struct mt7915_dev *dev) napi_disable(&dev->mt76.tx_napi); /* token reinit */ - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); mt7915_dma_reset(dev, true); @@ -1633,7 +1550,7 @@ void mt7915_mac_reset_work(struct work_struct *work) if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { mt7915_dma_reset(dev, false); - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 066934249a09..0c7226b8c805 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -555,7 +555,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7915_tx_token_put(struct mt7915_dev *dev); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 3e589748e1a3..368f92719abf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -511,30 +511,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) return 0; } -static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) -{ - struct mt7921_sta *msta; - u16 fc, tid; - u32 val; - - if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) - return; - - tid = le32_get_bits(txwi[1], MT_TXD1_TID); - if (tid >= 6) /* skip VO queue */ - return; - - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; - if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) - return; - - msta = (struct mt7921_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) - ieee80211_start_tx_ba_session(sta, tid, 0); -} - void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) { struct mt7921_sta *msta = NULL; @@ -576,37 +552,6 @@ out: rcu_read_unlock(); } -void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, - struct list_head *free_list) -{ - struct mt76_dev *mdev = &dev->mt76; - __le32 *txwi; - u16 wcid_idx; - - mt76_connac_txp_skb_unmap(mdev, t); - if (!t->skb) - goto out; - - txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); - if (sta) { - struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; - - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); - - wcid_idx = wcid->idx; - } else { - wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - } - - __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); -out: - t->skb = NULL; - mt76_put_txwi(mdev, t); -} -EXPORT_SYMBOL_GPL(mt7921_txwi_free); - static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) { struct mt76_connac_tx_free *free = data; @@ -669,7 +614,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) if (!txwi) continue; - mt7921_txwi_free(dev, txwi, sta, stat, &free_list); + mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); } if (wake) @@ -1235,7 +1180,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, sta = wcid_to_sta(wcid); if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); + mt76_connac2_tx_check_aggr(sta, txwi); skb_pull(e->skb, headroom); mt76_tx_complete_skb(mdev, e->wcid, e->skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 2694ecb1fdcb..ec9879650174 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -442,7 +442,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info); void mt7921_tx_worker(struct mt76_worker *w); -void mt7921_tx_token_put(struct mt7921_dev *dev); bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); @@ -475,9 +474,6 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, struct netlink_callback *cb, void *data, int len); -void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, - struct list_head *free_list); int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 95610a117d2f..1b7f19939a69 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -115,7 +115,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) cancel_work_sync(&pm->wake_work); cancel_work_sync(&dev->reset_work); - mt7921_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); __mt7921_mcu_drv_pmctrl(dev); mt7921_dma_cleanup(dev); mt7921_wfsys_reset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 6053a2556c20..978c90a034cf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -53,20 +53,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } -void mt7921_tx_token_put(struct mt7921_dev *dev) -{ - struct mt76_txwi_cache *txwi; - int id; - - spin_lock_bh(&dev->mt76.token_lock); - idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7921_txwi_free(dev, txwi, NULL, false, NULL); - dev->mt76.token_count--; - } - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); -} - int mt7921e_mac_reset(struct mt7921_dev *dev) { int i, err; @@ -91,7 +77,7 @@ int mt7921e_mac_reset(struct mt7921_dev *dev) napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); napi_disable(&dev->mt76.tx_napi); - mt7921_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); mt7921_wpdma_reset(dev, true); -- cgit From 0cb065b9ade9cab8be3a75e8b1b734133c355b82 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:30 +0200 Subject: wifi: mt76: move rate info in mt76_vif This is a preliminary patch to introduce mt76_connac3 mac library used by WiFi7 chipsets (e.g. mt7996). Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 3 +++ drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 10 +++++----- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 10 +++++----- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 4 ---- 5 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8ec77682d8e9..878087257ea7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -705,6 +705,9 @@ struct mt76_vif { u8 wmm_idx; u8 scan_seq_num; u8 cipher; + u8 basic_rates_idx; + u8 mcast_rates_idx; + u8 beacon_rates_idx; }; struct mt76_phy { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index dfe70e0ff329..6fc9260a2e92 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1013,7 +1013,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - struct mt7996_vif *mvif; + struct mt76_vif *mvif; u16 tx_count = 15; u32 val; bool beacon = !!(changed & (BSS_CHANGED_BEACON | @@ -1021,11 +1021,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); - mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; if (mvif) { - omac_idx = mvif->mt76.omac_idx; - wmm_idx = mvif->mt76.wmm_idx; - band_idx = mvif->mt76.band_idx; + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + band_idx = mvif->band_idx; } if (inband_disc) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 54858cfc9342..c3a479dc3f53 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -223,9 +223,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) - mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; + mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; else - mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL; + mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL; mt7996_init_bitrate_mask(vif); @@ -505,7 +505,7 @@ static u8 mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool beacon, bool mcast) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct mt76_phy *mphy = hw->priv; u16 rate; u8 i, idx, ht; @@ -517,7 +517,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7996_dev *dev = mt7996_hw_dev(hw); /* must odd index */ - idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20); + idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20); mt7996_mac_set_fixed_rate_table(dev, idx, rate); return idx; } @@ -555,7 +555,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u64 changed) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 611f6450520b..4a30db49ef33 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -604,7 +604,7 @@ static void mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7996_phy *phy) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct bss_rate_tlv *bmc; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 79cb71c16264..726c222e8e1e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -128,10 +128,6 @@ struct mt7996_vif { struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; struct cfg80211_bitrate_mask bitrate_mask; - - u8 basic_rates_idx; - u8 mcast_rates_idx; - u8 beacon_rates_idx; }; /* crash-dump */ -- cgit From 4e9011fcdfc4f325df1661e600a0dcd9064c2bd9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:31 +0200 Subject: wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h Connac3 mac definitions are shared between WiFi7 chipsets so move them in mt76_connac3_mac.h Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac3_mac.h | 325 +++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 315 +------------------- 2 files changed, 326 insertions(+), 314 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h new file mode 100644 index 000000000000..6663a0b46541 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h @@ -0,0 +1,325 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT76_CONNAC3_MAC_H +#define __MT76_CONNAC3_MAC_H + +#define MT_CT_PARSE_LEN 72 +#define MT_CT_DMA_BUF_NUM 2 + +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_FLAG GENMASK(19, 16) +#define MT_RXD0_PKT_TYPE GENMASK(31, 27) + +#define MT_RXD0_MESH BIT(18) +#define MT_RXD0_MHCP BIT(19) +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) + +#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) +#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F +#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801 + +/* RXD DW1 */ +#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0) +#define MT_RXD1_NORMAL_GROUP_1 BIT(16) +#define MT_RXD1_NORMAL_GROUP_2 BIT(17) +#define MT_RXD1_NORMAL_GROUP_3 BIT(18) +#define MT_RXD1_NORMAL_GROUP_4 BIT(19) +#define MT_RXD1_NORMAL_GROUP_5 BIT(20) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) +#define MT_RXD1_NORMAL_CM BIT(23) +#define MT_RXD1_NORMAL_CLM BIT(24) +#define MT_RXD1_NORMAL_ICV_ERR BIT(25) +#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) +#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27) +#define MT_RXD1_NORMAL_SPP_EN BIT(29) +#define MT_RXD1_NORMAL_ADD_OM BIT(30) +#define MT_RXD1_NORMAL_SEC_DONE BIT(31) + +/* RXD DW2 */ +#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) +#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) +#define MT_RXD2_NORMAL_HDR_TRANS BIT(7) +#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13) +#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16) +#define MT_RXD2_NORMAL_MU_BAR BIT(21) +#define MT_RXD2_NORMAL_SW_BIT BIT(22) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) +#define MT_RXD2_NORMAL_INT_FRAME BIT(26) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) +#define MT_RXD2_NORMAL_BF_REPORT BIT(31) + +/* RXD DW3 */ +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) +#define MT_RXD3_NORMAL_U2M BIT(0) +#define MT_RXD3_NORMAL_HTC_VLD BIT(18) +#define MT_RXD3_NORMAL_BEACON_MC BIT(20) +#define MT_RXD3_NORMAL_BEACON_UC BIT(21) +#define MT_RXD3_NORMAL_CO_ANT BIT(22) +#define MT_RXD3_NORMAL_FCS_ERR BIT(24) +#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) + +/* RXD DW4 */ +#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) +#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) +#define MT_RXD4_MID_AMSDU_FRAME BIT(1) +#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) + +#define MT_RXV_HDR_BAND_IDX BIT(24) + +/* RXD GROUP4 */ +#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0) + +#define MT_RXD10_SEQ_CTRL GENMASK(15, 0) +#define MT_RXD10_QOS_CTL GENMASK(31, 16) + +#define MT_RXD11_HT_CONTROL GENMASK(31, 0) + +/* P-RXV */ +#define MT_PRXV_TX_RATE GENMASK(6, 0) +#define MT_PRXV_TX_DCM BIT(4) +#define MT_PRXV_TX_ER_SU_106T BIT(5) +#define MT_PRXV_NSTS GENMASK(10, 7) +#define MT_PRXV_TXBF BIT(11) +#define MT_PRXV_HT_AD_CODE BIT(12) +#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22) +#define MT_PRXV_RCPI3 GENMASK(31, 24) +#define MT_PRXV_RCPI2 GENMASK(23, 16) +#define MT_PRXV_RCPI1 GENMASK(15, 8) +#define MT_PRXV_RCPI0 GENMASK(7, 0) +#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3) +#define MT_PRXV_HT_STBC GENMASK(10, 9) +#define MT_PRXV_TX_MODE GENMASK(14, 11) +#define MT_PRXV_FRAME_MODE GENMASK(2, 0) +#define MT_PRXV_DCM BIT(5) + +/* C-RXV */ +#define MT_CRXV_HE_NUM_USER GENMASK(26, 20) +#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27) +#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30) + +#define MT_CRXV_HE_PE_DISAMBIG BIT(1) +#define MT_CRXV_HE_UPLINK BIT(2) + +#define MT_CRXV_HE_MU_AID GENMASK(27, 17) +#define MT_CRXV_HE_BEAM_CHNG BIT(29) + +#define MT_CRXV_HE_DOPPLER BIT(0) +#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10) +#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17) + +#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) +#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) +#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) +#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) + +#define MT_CRXV_HE_RU0 GENMASK(8, 0) +#define MT_CRXV_HE_RU1 GENMASK(17, 9) +#define MT_CRXV_HE_RU2 GENMASK(26, 18) +#define MT_CRXV_HE_RU3_L GENMASK(31, 27) +#define MT_CRXV_HE_RU3_H GENMASK(3, 0) + +enum tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +enum tx_pkt_type { + MT_TX_TYPE_CT, + MT_TX_TYPE_SF, + MT_TX_TYPE_CMD, + MT_TX_TYPE_FW, +}; + +enum tx_port_idx { + MT_TX_PORT_IDX_LMAC, + MT_TX_PORT_IDX_MCU +}; + +enum tx_mcu_port_q_idx { + MT_TX_MCU_PORT_RX_Q0 = 0x20, + MT_TX_MCU_PORT_RX_Q1, + MT_TX_MCU_PORT_RX_Q2, + MT_TX_MCU_PORT_RX_Q3, + MT_TX_MCU_PORT_RX_FWDL = 0x3e +}; + +enum tx_mgnt_type { + MT_TX_NORMAL, + MT_TX_TIMING, + MT_TX_ADDBA, +}; + +#define MT_CT_INFO_APPLY_TXD BIT(0) +#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) +#define MT_CT_INFO_MGMT_FRAME BIT(2) +#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define MT_CT_INFO_HSR2_TX BIT(4) +#define MT_CT_INFO_FROM_HOST BIT(7) + +#define MT_TXD_SIZE (8 * 4) + +#define MT_TXD0_Q_IDX GENMASK(31, 25) +#define MT_TXD0_PKT_FMT GENMASK(24, 23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_FIXED_RATE BIT(31) +#define MT_TXD1_OWN_MAC GENMASK(30, 25) +#define MT_TXD1_TID GENMASK(24, 21) +#define MT_TXD1_BIP BIT(24) +#define MT_TXD1_ETH_802_3 BIT(20) +#define MT_TXD1_HDR_INFO GENMASK(20, 16) +#define MT_TXD1_HDR_FORMAT GENMASK(15, 14) +#define MT_TXD1_TGID GENMASK(13, 12) +#define MT_TXD1_WLAN_IDX GENMASK(11, 0) + +#define MT_TXD2_POWER_OFFSET GENMASK(31, 26) +#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_HDR_PAD GENMASK(11, 10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_OWN_MAC_MAP BIT(8) +#define MT_TXD2_BF_TYPE GENMASK(6, 7) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SW_POWER_MGMT BIT(29) +#define MT_TXD3_BA_DISABLE BIT(28) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) +#define MT_TXD3_HW_AMSDU BIT(5) +#define MT_TXD3_BCM BIT(4) +#define MT_TXD3_EEOSP BIT(3) +#define MT_TXD3_EMRD BIT(2) +#define MT_TXD3_PROTECT_FRAME BIT(1) +#define MT_TXD3_NO_ACK BIT(0) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_FL BIT(15) +#define MT_TXD5_BYPASS_TBB BIT(14) +#define MT_TXD5_BYPASS_RBB BIT(13) +#define MT_TXD5_BSS_COLOR_ZERO BIT(12) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_TX_SRC GENMASK(31, 30) +#define MT_TXD6_VTA BIT(28) +#define MT_TXD6_BW GENMASK(25, 22) +#define MT_TXD6_TX_RATE GENMASK(21, 16) +#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) +#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) +#define MT_TXD6_MSDU_CNT GENMASK(9, 4) +#define MT_TXD6_DIS_MAT BIT(3) +#define MT_TXD6_DAS BIT(2) +#define MT_TXD6_AMSDU_CAP BIT(1) + +#define MT_TXD7_TXD_LEN GENMASK(31, 30) +#define MT_TXD7_IP_SUM BIT(29) +#define MT_TXD7_DROP_BY_SDO BIT(28) +#define MT_TXD7_MAC_TXD BIT(27) +#define MT_TXD7_CTXD BIT(26) +#define MT_TXD7_CTXD_CNT GENMASK(25, 22) +#define MT_TXD7_UDP_TCP_SUM BIT(15) +#define MT_TXD7_TX_TIME GENMASK(9, 0) + +#define MT_TX_RATE_STBC BIT(14) +#define MT_TX_RATE_NSS GENMASK(13, 10) +#define MT_TX_RATE_MODE GENMASK(9, 6) +#define MT_TX_RATE_SU_EXT_TONE BIT(5) +#define MT_TX_RATE_DCM BIT(4) +/* VHT/HE only use bits 0-3 */ +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27) +#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) +#define MT_TXFREE0_RX_BYTE GENMASK(15, 0) + +#define MT_TXFREE1_VER GENMASK(18, 16) + +#define MT_TXFREE_INFO_PAIR BIT(31) +#define MT_TXFREE_INFO_HEADER BIT(30) +#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12) +#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0) +#define MT_TXFREE_INFO_COUNT GENMASK(27, 24) +#define MT_TXFREE_INFO_STAT GENMASK(29, 28) + +#define MT_TXS0_BW GENMASK(31, 29) +#define MT_TXS0_TID GENMASK(28, 26) +#define MT_TXS0_AMPDU BIT(25) +#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) +#define MT_TXS0_BA_ERROR BIT(22) +#define MT_TXS0_PS_FLAG BIT(21) +#define MT_TXS0_TXOP_TIMEOUT BIT(20) +#define MT_TXS0_BIP_ERROR BIT(19) + +#define MT_TXS0_QUEUE_TIMEOUT BIT(18) +#define MT_TXS0_RTS_TIMEOUT BIT(17) +#define MT_TXS0_ACK_TIMEOUT BIT(16) +#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) + +#define MT_TXS0_TX_STATUS_HOST BIT(15) +#define MT_TXS0_TX_STATUS_MCU BIT(14) +#define MT_TXS0_TX_RATE GENMASK(13, 0) + +#define MT_TXS1_SEQNO GENMASK(31, 20) +#define MT_TXS1_RESP_RATE GENMASK(19, 16) +#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) +#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) + +#define MT_TXS2_BF_STATUS GENMASK(31, 30) +#define MT_TXS2_BAND GENMASK(29, 28) +#define MT_TXS2_WCID GENMASK(27, 16) +#define MT_TXS2_TX_DELAY GENMASK(15, 0) + +#define MT_TXS3_PID GENMASK(31, 24) +#define MT_TXS3_RATE_STBC BIT(7) +#define MT_TXS3_FIXED_RATE BIT(6) +#define MT_TXS3_SRC GENMASK(5, 4) +#define MT_TXS3_SHARED_ANTENNA BIT(3) +#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0) + +#define MT_TXS4_TIMESTAMP GENMASK(31, 0) + +#define MT_TXS5_F0_FINAL_MPDU BIT(31) +#define MT_TXS5_F0_QOS BIT(30) +#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) +#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0) +#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24) +#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0) + +#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24) +#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16) +#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8) +#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0) +#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24) +#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0) + +#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24) +#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16) +#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8) +#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0) +#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24) +#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0) + +#endif /* __MT76_CONNAC3_MAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index bc4e6c55373e..e629324a5617 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -6,320 +6,7 @@ #ifndef __MT7996_MAC_H #define __MT7996_MAC_H -#define MT_CT_PARSE_LEN 72 -#define MT_CT_DMA_BUF_NUM 2 - -#define MT_RXD0_LENGTH GENMASK(15, 0) -#define MT_RXD0_PKT_TYPE GENMASK(31, 27) - -#define MT_RXD0_MESH BIT(18) -#define MT_RXD0_MHCP BIT(19) -#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) -#define MT_RXD0_NORMAL_IP_SUM BIT(23) -#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) - -#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) -#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F -#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801 - -/* RXD DW1 */ -#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0) -#define MT_RXD1_NORMAL_GROUP_1 BIT(16) -#define MT_RXD1_NORMAL_GROUP_2 BIT(17) -#define MT_RXD1_NORMAL_GROUP_3 BIT(18) -#define MT_RXD1_NORMAL_GROUP_4 BIT(19) -#define MT_RXD1_NORMAL_GROUP_5 BIT(20) -#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) -#define MT_RXD1_NORMAL_CM BIT(23) -#define MT_RXD1_NORMAL_CLM BIT(24) -#define MT_RXD1_NORMAL_ICV_ERR BIT(25) -#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) -#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27) -#define MT_RXD1_NORMAL_SPP_EN BIT(29) -#define MT_RXD1_NORMAL_ADD_OM BIT(30) -#define MT_RXD1_NORMAL_SEC_DONE BIT(31) - -/* RXD DW2 */ -#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) -#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) -#define MT_RXD2_NORMAL_HDR_TRANS BIT(7) -#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13) -#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16) -#define MT_RXD2_NORMAL_MU_BAR BIT(21) -#define MT_RXD2_NORMAL_SW_BIT BIT(22) -#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) -#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) -#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) -#define MT_RXD2_NORMAL_INT_FRAME BIT(26) -#define MT_RXD2_NORMAL_FRAG BIT(27) -#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) -#define MT_RXD2_NORMAL_NDATA BIT(29) -#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) -#define MT_RXD2_NORMAL_BF_REPORT BIT(31) - -/* RXD DW3 */ -#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) -#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) -#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) -#define MT_RXD3_NORMAL_U2M BIT(0) -#define MT_RXD3_NORMAL_HTC_VLD BIT(18) -#define MT_RXD3_NORMAL_BEACON_MC BIT(20) -#define MT_RXD3_NORMAL_BEACON_UC BIT(21) -#define MT_RXD3_NORMAL_CO_ANT BIT(22) -#define MT_RXD3_NORMAL_FCS_ERR BIT(24) -#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) - -/* RXD DW4 */ -#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) -#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) -#define MT_RXD4_MID_AMSDU_FRAME BIT(1) -#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) - -#define MT_RXV_HDR_BAND_IDX BIT(24) - -/* RXD GROUP4 */ -#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0) - -#define MT_RXD10_SEQ_CTRL GENMASK(15, 0) -#define MT_RXD10_QOS_CTL GENMASK(31, 16) - -#define MT_RXD11_HT_CONTROL GENMASK(31, 0) - -/* P-RXV */ -#define MT_PRXV_TX_RATE GENMASK(6, 0) -#define MT_PRXV_TX_DCM BIT(4) -#define MT_PRXV_TX_ER_SU_106T BIT(5) -#define MT_PRXV_NSTS GENMASK(10, 7) -#define MT_PRXV_TXBF BIT(11) -#define MT_PRXV_HT_AD_CODE BIT(12) -#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22) -#define MT_PRXV_RCPI3 GENMASK(31, 24) -#define MT_PRXV_RCPI2 GENMASK(23, 16) -#define MT_PRXV_RCPI1 GENMASK(15, 8) -#define MT_PRXV_RCPI0 GENMASK(7, 0) -#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3) -#define MT_PRXV_HT_STBC GENMASK(10, 9) -#define MT_PRXV_TX_MODE GENMASK(14, 11) -#define MT_PRXV_FRAME_MODE GENMASK(2, 0) -#define MT_PRXV_DCM BIT(5) - -/* C-RXV */ -#define MT_CRXV_HE_NUM_USER GENMASK(26, 20) -#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27) -#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30) - -#define MT_CRXV_HE_PE_DISAMBIG BIT(1) -#define MT_CRXV_HE_UPLINK BIT(2) - -#define MT_CRXV_HE_MU_AID GENMASK(27, 17) -#define MT_CRXV_HE_BEAM_CHNG BIT(29) - -#define MT_CRXV_HE_DOPPLER BIT(0) -#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10) -#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17) - -#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) -#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) -#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) -#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) - -#define MT_CRXV_HE_RU0 GENMASK(8, 0) -#define MT_CRXV_HE_RU1 GENMASK(17, 9) -#define MT_CRXV_HE_RU2 GENMASK(26, 18) -#define MT_CRXV_HE_RU3_L GENMASK(31, 27) -#define MT_CRXV_HE_RU3_H GENMASK(3, 0) - -enum tx_header_format { - MT_HDR_FORMAT_802_3, - MT_HDR_FORMAT_CMD, - MT_HDR_FORMAT_802_11, - MT_HDR_FORMAT_802_11_EXT, -}; - -enum tx_pkt_type { - MT_TX_TYPE_CT, - MT_TX_TYPE_SF, - MT_TX_TYPE_CMD, - MT_TX_TYPE_FW, -}; - -enum tx_port_idx { - MT_TX_PORT_IDX_LMAC, - MT_TX_PORT_IDX_MCU -}; - -enum tx_mcu_port_q_idx { - MT_TX_MCU_PORT_RX_Q0 = 0x20, - MT_TX_MCU_PORT_RX_Q1, - MT_TX_MCU_PORT_RX_Q2, - MT_TX_MCU_PORT_RX_Q3, - MT_TX_MCU_PORT_RX_FWDL = 0x3e -}; - -enum tx_mgnt_type { - MT_TX_NORMAL, - MT_TX_TIMING, - MT_TX_ADDBA, -}; - -#define MT_CT_INFO_APPLY_TXD BIT(0) -#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) -#define MT_CT_INFO_MGMT_FRAME BIT(2) -#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) -#define MT_CT_INFO_HSR2_TX BIT(4) -#define MT_CT_INFO_FROM_HOST BIT(7) - -#define MT_TXD_SIZE (8 * 4) - -#define MT_TXD0_Q_IDX GENMASK(31, 25) -#define MT_TXD0_PKT_FMT GENMASK(24, 23) -#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) -#define MT_TXD0_TX_BYTES GENMASK(15, 0) - -#define MT_TXD1_FIXED_RATE BIT(31) -#define MT_TXD1_OWN_MAC GENMASK(30, 25) -#define MT_TXD1_TID GENMASK(24, 21) -#define MT_TXD1_BIP BIT(24) -#define MT_TXD1_ETH_802_3 BIT(20) -#define MT_TXD1_HDR_INFO GENMASK(20, 16) -#define MT_TXD1_HDR_FORMAT GENMASK(15, 14) -#define MT_TXD1_TGID GENMASK(13, 12) -#define MT_TXD1_WLAN_IDX GENMASK(11, 0) - -#define MT_TXD2_POWER_OFFSET GENMASK(31, 26) -#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16) -#define MT_TXD2_FRAG GENMASK(15, 14) -#define MT_TXD2_HTC_VLD BIT(13) -#define MT_TXD2_DURATION BIT(12) -#define MT_TXD2_HDR_PAD GENMASK(11, 10) -#define MT_TXD2_RTS BIT(9) -#define MT_TXD2_OWN_MAC_MAP BIT(8) -#define MT_TXD2_BF_TYPE GENMASK(6, 7) -#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) -#define MT_TXD2_SUB_TYPE GENMASK(3, 0) - -#define MT_TXD3_SN_VALID BIT(31) -#define MT_TXD3_PN_VALID BIT(30) -#define MT_TXD3_SW_POWER_MGMT BIT(29) -#define MT_TXD3_BA_DISABLE BIT(28) -#define MT_TXD3_SEQ GENMASK(27, 16) -#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) -#define MT_TXD3_TX_COUNT GENMASK(10, 6) -#define MT_TXD3_HW_AMSDU BIT(5) -#define MT_TXD3_BCM BIT(4) -#define MT_TXD3_EEOSP BIT(3) -#define MT_TXD3_EMRD BIT(2) -#define MT_TXD3_PROTECT_FRAME BIT(1) -#define MT_TXD3_NO_ACK BIT(0) - -#define MT_TXD4_PN_LOW GENMASK(31, 0) - -#define MT_TXD5_PN_HIGH GENMASK(31, 16) -#define MT_TXD5_FL BIT(15) -#define MT_TXD5_BYPASS_TBB BIT(14) -#define MT_TXD5_BYPASS_RBB BIT(13) -#define MT_TXD5_BSS_COLOR_ZERO BIT(12) -#define MT_TXD5_TX_STATUS_HOST BIT(10) -#define MT_TXD5_TX_STATUS_MCU BIT(9) -#define MT_TXD5_TX_STATUS_FMT BIT(8) -#define MT_TXD5_PID GENMASK(7, 0) - -#define MT_TXD6_TX_SRC GENMASK(31, 30) -#define MT_TXD6_VTA BIT(28) -#define MT_TXD6_BW GENMASK(25, 22) -#define MT_TXD6_TX_RATE GENMASK(21, 16) -#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) -#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) -#define MT_TXD6_MSDU_CNT GENMASK(9, 4) -#define MT_TXD6_DIS_MAT BIT(3) -#define MT_TXD6_DAS BIT(2) -#define MT_TXD6_AMSDU_CAP BIT(1) - -#define MT_TXD7_TXD_LEN GENMASK(31, 30) -#define MT_TXD7_IP_SUM BIT(29) -#define MT_TXD7_DROP_BY_SDO BIT(28) -#define MT_TXD7_MAC_TXD BIT(27) -#define MT_TXD7_CTXD BIT(26) -#define MT_TXD7_CTXD_CNT GENMASK(25, 22) -#define MT_TXD7_UDP_TCP_SUM BIT(15) -#define MT_TXD7_TX_TIME GENMASK(9, 0) - -#define MT_TX_RATE_STBC BIT(14) -#define MT_TX_RATE_NSS GENMASK(13, 10) -#define MT_TX_RATE_MODE GENMASK(9, 6) -#define MT_TX_RATE_SU_EXT_TONE BIT(5) -#define MT_TX_RATE_DCM BIT(4) -/* VHT/HE only use bits 0-3 */ -#define MT_TX_RATE_IDX GENMASK(5, 0) - -#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27) -#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) -#define MT_TXFREE0_RX_BYTE GENMASK(15, 0) - -#define MT_TXFREE1_VER GENMASK(18, 16) - -#define MT_TXFREE_INFO_PAIR BIT(31) -#define MT_TXFREE_INFO_HEADER BIT(30) -#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12) -#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0) - -#define MT_TXS0_BW GENMASK(31, 29) -#define MT_TXS0_TID GENMASK(28, 26) -#define MT_TXS0_AMPDU BIT(25) -#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) -#define MT_TXS0_BA_ERROR BIT(22) -#define MT_TXS0_PS_FLAG BIT(21) -#define MT_TXS0_TXOP_TIMEOUT BIT(20) -#define MT_TXS0_BIP_ERROR BIT(19) - -#define MT_TXS0_QUEUE_TIMEOUT BIT(18) -#define MT_TXS0_RTS_TIMEOUT BIT(17) -#define MT_TXS0_ACK_TIMEOUT BIT(16) -#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) - -#define MT_TXS0_TX_STATUS_HOST BIT(15) -#define MT_TXS0_TX_STATUS_MCU BIT(14) -#define MT_TXS0_TX_RATE GENMASK(13, 0) - -#define MT_TXS1_SEQNO GENMASK(31, 20) -#define MT_TXS1_RESP_RATE GENMASK(19, 16) -#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) -#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) - -#define MT_TXS2_BF_STATUS GENMASK(31, 30) -#define MT_TXS2_BAND GENMASK(29, 28) -#define MT_TXS2_WCID GENMASK(27, 16) -#define MT_TXS2_TX_DELAY GENMASK(15, 0) - -#define MT_TXS3_PID GENMASK(31, 24) -#define MT_TXS3_RATE_STBC BIT(7) -#define MT_TXS3_FIXED_RATE BIT(6) -#define MT_TXS3_SRC GENMASK(5, 4) -#define MT_TXS3_SHARED_ANTENNA BIT(3) -#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0) - -#define MT_TXS4_TIMESTAMP GENMASK(31, 0) - -#define MT_TXS5_F0_FINAL_MPDU BIT(31) -#define MT_TXS5_F0_QOS BIT(30) -#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) -#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0) -#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24) -#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0) - -#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24) -#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16) -#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8) -#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0) -#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24) -#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0) - -#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24) -#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16) -#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8) -#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0) -#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24) -#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0) +#include "../mt76_connac3_mac.h" struct mt7996_dfs_pulse { u32 max_width; /* us */ -- cgit From 46d3304d6552d6dfd715e66b4c28e7c70bedd2f7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 22 Jun 2023 18:50:32 +0200 Subject: wifi: mt76: connac: add connac3 mac library Introduce connac3_mac in mt76_connac library to reuse mac code shared between WiFi7 chipsets. So far connac3 library contains just radiotap parsing code. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 3 + .../net/wireless/mediatek/mt76/mt76_connac3_mac.c | 182 +++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 180 +------------------- 4 files changed, 187 insertions(+), 180 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 84c99b7e57f9..d8e8079c8b54 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index d3bb9114160f..22878f088804 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -425,4 +425,7 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, struct list_head *free_list); void mt76_connac2_tx_token_put(struct mt76_dev *dev); +/* connac3 */ +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode); #endif /* __MT76_CONNAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c new file mode 100644 index 000000000000..73e9f283d0ae --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt76_connac.h" +#include "mt76_connac3_mac.h" +#include "dma.h" + +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ + IEEE80211_RADIOTAP_HE_##f) + +static void +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, + struct ieee80211_radiotap_he *he, + __le32 *rxv) +{ + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0; + + status->bw = RATE_INFO_BW_HE_RU; + + switch (ru) { + case 0 ... 36: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; + offs = ru; + break; + case 37 ... 52: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; + offs = ru - 37; + break; + case 53 ... 60: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; + offs = ru - 53; + break; + case 61 ... 64: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; + offs = ru - 61; + break; + case 65 ... 66: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; + offs = ru - 65; + break; + case 67: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 68: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; + break; + } + + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | + le16_encode_bits(offs, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); +} + +#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) +static void +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static const struct ieee80211_radiotap_he_mu mu_known = { + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), + }; + struct ieee80211_radiotap_he_mu *he_mu; + + status->flag |= RX_FLAG_RADIOTAP_HE_MU; + + he_mu = skb_push(skb, sizeof(mu_known)); + memcpy(he_mu, &mu_known, sizeof(mu_known)); + + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); + if (status->he_dcm) + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); + + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | + MU_PREP(FLAGS2_SIG_B_SYMS_USERS, + le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); + + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; + + if (status->bw >= RATE_INFO_BW_40) { + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); + he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; + } + + if (status->bw >= RATE_INFO_BW_80) { + u32 ru_h, ru_l; + + he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; + + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); + } +} + +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static const struct ieee80211_radiotap_he known = { + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | + HE_BITS(DATA1_DATA_DCM_KNOWN) | + HE_BITS(DATA1_STBC_KNOWN) | + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), + .data2 = HE_BITS(DATA2_GI_KNOWN) | + HE_BITS(DATA2_TXBF_KNOWN) | + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN), + }; + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; + struct ieee80211_radiotap_he *he; + + status->flag |= RX_FLAG_RADIOTAP_HE; + + he = skb_push(skb, sizeof(known)); + memcpy(he, &known, sizeof(known)); + + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | + le16_encode_bits(ltf_size, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) + he->data5 |= HE_BITS(DATA5_TXBF); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); + + switch (mode) { + case MT_PHY_TYPE_HE_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + break; + case MT_PHY_TYPE_HE_EXT_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + break; + case MT_PHY_TYPE_HE_MU: + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | + HE_BITS(DATA1_UL_DL_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); + + mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv); + break; + case MT_PHY_TYPE_HE_TB: + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); + + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); + + mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 6fc9260a2e92..ac8759febe48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -13,10 +13,6 @@ #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) -#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) -#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ - IEEE80211_RADIOTAP_HE_##f) - static const struct mt7996_dfs_radar_spec etsi_radar_specs = { .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, .radar_pattern = { @@ -263,180 +259,6 @@ void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, mt76_wr(dev, MT_WTBL_ITCR, ctrl); } -static void -mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, - struct ieee80211_radiotap_he *he, - __le32 *rxv) -{ - u32 ru, offs = 0; - - ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC); - - status->bw = RATE_INFO_BW_HE_RU; - - switch (ru) { - case 0 ... 36: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; - offs = ru; - break; - case 37 ... 52: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; - offs = ru - 37; - break; - case 53 ... 60: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; - offs = ru - 53; - break; - case 61 ... 64: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; - offs = ru - 61; - break; - case 65 ... 66: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; - offs = ru - 65; - break; - case 67: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; - break; - case 68: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; - break; - } - - he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | - le16_encode_bits(offs, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); -} - -static void -mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - static const struct ieee80211_radiotap_he_mu mu_known = { - .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | - HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), - .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), - }; - struct ieee80211_radiotap_he_mu *he_mu = NULL; - - status->flag |= RX_FLAG_RADIOTAP_HE_MU; - - he_mu = skb_push(skb, sizeof(mu_known)); - memcpy(he_mu, &mu_known, sizeof(mu_known)); - -#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) - - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); - if (status->he_dcm) - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); - - he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | - MU_PREP(FLAGS2_SIG_B_SYMS_USERS, - le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); - - he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; - - if (status->bw >= RATE_INFO_BW_40) { - he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); - he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; - } - - if (status->bw >= RATE_INFO_BW_80) { - u32 ru_h, ru_l; - - he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; - - ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); - ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; - he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); - } -} - -static void -mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - static const struct ieee80211_radiotap_he known = { - .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | - HE_BITS(DATA1_DATA_DCM_KNOWN) | - HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN) | - HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN), - .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN) | - HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN), - }; - struct ieee80211_radiotap_he *he = NULL; - u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; - - status->flag |= RX_FLAG_RADIOTAP_HE; - - he = skb_push(skb, sizeof(known)); - memcpy(he, &known, sizeof(known)); - - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); - he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | - le16_encode_bits(ltf_size, - IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); - if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) - he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); - - switch (mode) { - case MT_PHY_TYPE_HE_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | - HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - - he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | - HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - break; - case MT_PHY_TYPE_HE_EXT_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - break; - case MT_PHY_TYPE_HE_MU: - he->data1 |= HE_BITS(DATA1_FORMAT_MU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); - - mt7996_mac_decode_he_radiotap_ru(status, he, rxv); - mt7996_mac_decode_he_mu_radiotap(skb, rxv); - break; - case MT_PHY_TYPE_HE_TB: - he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | - HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - - he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); - - mt7996_mac_decode_he_radiotap_ru(status, he, rxv); - break; - default: - break; - } -} - /* The HW does not translate the mac header to 802.3 for mesh point */ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) { @@ -887,7 +709,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) } if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) - mt7996_mac_decode_he_radiotap(skb, rxv, mode); + mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; -- cgit From 09bd2d7ddaedcdfa4aa3f4d54c103f984a93bd32 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Mon, 24 Jul 2023 16:57:14 +0100 Subject: net: mdio_bus: validate "addr" for mdiobus_is_registered_device() mdiobus_is_registered_device() doesn't checking that "addr" was valid before dereferencing bus->mdio_map[]. Extract the code that checks this from mdiobus_get_phy(), and use it here as well. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/E1qNxvu-00111m-1V@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/phy/mdio_bus.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index bc04048de2fa..25dcaa49ab8b 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -107,16 +107,21 @@ int mdiobus_unregister_device(struct mdio_device *mdiodev) } EXPORT_SYMBOL(mdiobus_unregister_device); -struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) +static struct mdio_device *mdiobus_find_device(struct mii_bus *bus, int addr) { bool addr_valid = addr >= 0 && addr < ARRAY_SIZE(bus->mdio_map); - struct mdio_device *mdiodev; if (WARN_ONCE(!addr_valid, "addr %d out of range\n", addr)) return NULL; - mdiodev = bus->mdio_map[addr]; + return bus->mdio_map[addr]; +} +struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) +{ + struct mdio_device *mdiodev; + + mdiodev = mdiobus_find_device(bus, addr); if (!mdiodev) return NULL; @@ -129,7 +134,7 @@ EXPORT_SYMBOL(mdiobus_get_phy); bool mdiobus_is_registered_device(struct mii_bus *bus, int addr) { - return bus->mdio_map[addr]; + return mdiobus_find_device(bus, addr) != NULL; } EXPORT_SYMBOL(mdiobus_is_registered_device); -- cgit From 20bf98c94146eb6fe62177817cb32f53e72dd2e8 Mon Sep 17 00:00:00 2001 From: Johannes Zink Date: Mon, 24 Jul 2023 12:01:31 +0200 Subject: net: stmmac: correct MAC propagation delay The IEEE1588 Standard specifies that the timestamps of Packets must be captured when the PTP message timestamp point (leading edge of first octet after the start of frame delimiter) crosses the boundary between the node and the network. As the MAC latches the timestamp at an internal point, the captured timestamp must be corrected for the additional path latency, as described in the publicly available datasheet [1]. This patch only corrects for the MAC-Internal delay, which can be read out from the MAC_Ingress_Timestamp_Latency register, since the Phy framework currently does not support querying the Phy ingress and egress latency. The Closs Domain Crossing Circuits errors as indicated in [1] are already being accounted in the stmmac_get_tx_hwtstamp() function and are not corrected here. As the Latency varies for different link speeds and MII modes of operation, the correction value needs to be updated on each link state change. As the delay also causes a phase shift in the timestamp counter compared to the rest of the network, this correction will also reduce phase error when generating PPS outputs from the timestamp counter. [1] i.MX8MP Reference Manual, rev.1 Section 11.7.2.5.3 "Timestamp correction" Signed-off-by: Johannes Zink Link: https://lore.kernel.org/r/20230719-stmmac_correct_mac_delay-v2-1-3366f38ee9a6@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 ++ .../net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 43 ++++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 6 +++ 4 files changed, 56 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 652af8f6e75f..40147ef24963 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -532,6 +532,7 @@ struct stmmac_hwtimestamp { void (*get_systime) (void __iomem *ioaddr, u64 *systime); void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time); void (*timestamp_interrupt)(struct stmmac_priv *priv); + void (*correct_latency)(struct stmmac_priv *priv); }; #define stmmac_config_hw_tstamping(__priv, __args...) \ @@ -550,6 +551,8 @@ struct stmmac_hwtimestamp { stmmac_do_void_callback(__priv, ptp, get_ptptime, __args) #define stmmac_timestamp_interrupt(__priv, __args...) \ stmmac_do_void_callback(__priv, ptp, timestamp_interrupt, __args) +#define stmmac_correct_latency(__priv, __args...) \ + stmmac_do_void_callback(__priv, ptp, correct_latency, __args) struct stmmac_tx_queue; struct stmmac_rx_queue; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index fa2c3ba7e9fe..7e0fa024e0ad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -60,6 +60,48 @@ static void config_sub_second_increment(void __iomem *ioaddr, *ssinc = data; } +static void correct_latency(struct stmmac_priv *priv) +{ + void __iomem *ioaddr = priv->ptpaddr; + u32 reg_tsic, reg_tsicsns; + u32 reg_tsec, reg_tsecsns; + u64 scaled_ns; + u32 val; + + /* MAC-internal ingress latency */ + scaled_ns = readl(ioaddr + PTP_TS_INGR_LAT); + + /* See section 11.7.2.5.3.1 "Ingress Correction" on page 4001 of + * i.MX8MP Applications Processor Reference Manual Rev. 1, 06/2021 + */ + val = readl(ioaddr + PTP_TCR); + if (val & PTP_TCR_TSCTRLSSR) + /* nanoseconds field is in decimal format with granularity of 1ns/bit */ + scaled_ns = ((u64)NSEC_PER_SEC << 16) - scaled_ns; + else + /* nanoseconds field is in binary format with granularity of ~0.466ns/bit */ + scaled_ns = ((1ULL << 31) << 16) - + DIV_U64_ROUND_CLOSEST(scaled_ns * PSEC_PER_NSEC, 466U); + + reg_tsic = scaled_ns >> 16; + reg_tsicsns = scaled_ns & 0xff00; + + /* set bit 31 for 2's compliment */ + reg_tsic |= BIT(31); + + writel(reg_tsic, ioaddr + PTP_TS_INGR_CORR_NS); + writel(reg_tsicsns, ioaddr + PTP_TS_INGR_CORR_SNS); + + /* MAC-internal egress latency */ + scaled_ns = readl(ioaddr + PTP_TS_EGR_LAT); + + reg_tsec = scaled_ns >> 16; + reg_tsecsns = scaled_ns & 0xff00; + + writel(reg_tsec, ioaddr + PTP_TS_EGR_CORR_NS); + writel(reg_tsecsns, ioaddr + PTP_TS_EGR_CORR_SNS); +} + static int init_systime(void __iomem *ioaddr, u32 sec, u32 nsec) { u32 value; @@ -221,4 +263,5 @@ const struct stmmac_hwtimestamp stmmac_ptp = { .get_systime = get_systime, .get_ptptime = get_ptptime, .timestamp_interrupt = timestamp_interrupt, + .correct_latency = correct_latency, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e1f1c034d325..19e46e8f626a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -909,6 +909,8 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) priv->hwts_tx_en = 0; priv->hwts_rx_en = 0; + stmmac_correct_latency(priv, priv); + return 0; } @@ -1094,6 +1096,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, if (priv->dma_cap.fpesel) stmmac_fpe_link_state_handle(priv, true); + + stmmac_correct_latency(priv, priv); } static const struct phylink_mac_ops stmmac_phylink_mac_ops = { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index bf619295d079..d1fe4b46f162 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -26,6 +26,12 @@ #define PTP_ACR 0x40 /* Auxiliary Control Reg */ #define PTP_ATNR 0x48 /* Auxiliary Timestamp - Nanoseconds Reg */ #define PTP_ATSR 0x4c /* Auxiliary Timestamp - Seconds Reg */ +#define PTP_TS_INGR_CORR_NS 0x58 /* Ingress timestamp correction nanoseconds */ +#define PTP_TS_EGR_CORR_NS 0x5C /* Egress timestamp correction nanoseconds*/ +#define PTP_TS_INGR_CORR_SNS 0x60 /* Ingress timestamp correction subnanoseconds */ +#define PTP_TS_EGR_CORR_SNS 0x64 /* Egress timestamp correction subnanoseconds */ +#define PTP_TS_INGR_LAT 0x68 /* MAC internal Ingress Latency */ +#define PTP_TS_EGR_LAT 0x6c /* MAC internal Egress Latency */ #define PTP_STNSUR_ADDSUB_SHIFT 31 #define PTP_DIGITAL_ROLLOVER_MODE 0x3B9ACA00 /* 10e9-1 ns */ -- cgit From 02a894046d5ab7d0010f39ea54fde7e167919d04 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 29 Jun 2023 22:39:30 +0200 Subject: wifi: mt76: mt7915: fix capabilities in non-AP mode Capabilities in vif->bss_conf are only initialized in AP mode. For other modes, they should be enabled by default, in order to avoid a mismatch. Fixes: 885f7af7e544 ("wifi: mt76: mt7915: remove mt7915_mcu_beacon_check_caps()") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 21 +++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 27 ++++++++++++---------- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 14 +++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index decb60aac9dd..eb95fb28d354 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -269,6 +269,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; mt7915_init_bitrate_mask(vif); + memset(&mvif->cap, -1, sizeof(mvif->cap)); mt7915_mcu_add_bss_info(phy, vif, true); mt7915_mcu_add_sta(dev, vif, NULL, true); @@ -657,6 +658,24 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } +static void +mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_vif_cap *vc = &mvif->cap; + + vc->ht_ldpc = vif->bss_conf.ht_ldpc; + vc->vht_ldpc = vif->bss_conf.vht_ldpc; + vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer; + vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee; + vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer; + vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee; + vc->he_ldpc = vif->bss_conf.he_ldpc; + vc->he_su_ebfer = vif->bss_conf.he_su_beamformer; + vc->he_su_ebfee = vif->bss_conf.he_su_beamformee; + vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer; +} + static int mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) @@ -667,6 +686,8 @@ mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); + mt7915_vif_check_caps(phy, vif); + err = mt7915_mcu_add_bss_info(phy, vif, true); if (err) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index bb8ec0d1d01c..5f4c2946b26b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -713,6 +713,7 @@ static void mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he *he; @@ -746,7 +747,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G)) cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT; - if (vif->bss_conf.he_ldpc && + if (mvif->cap.he_ldpc && (elem->phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) cap |= STA_REC_HE_CAP_LDPC; @@ -855,6 +856,7 @@ static void mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct sta_rec_muru *muru; struct tlv *tlv; @@ -867,9 +869,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, muru = (struct sta_rec_muru *)tlv; - muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer || - vif->bss_conf.vht_mu_beamformer || - vif->bss_conf.vht_mu_beamformee; + muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || + mvif->cap.vht_mu_ebfer || + mvif->cap.vht_mu_ebfee; if (!is_mt7915(&dev->mt76)) muru->cfg.mimo_ul_en = true; muru->cfg.ofdma_dl_en = true; @@ -1002,8 +1004,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb, mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr); if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv, - wtbl_hdr, vif->bss_conf.ht_ldpc, - vif->bss_conf.vht_ldpc); + wtbl_hdr, mvif->cap.ht_ldpc, + mvif->cap.vht_ldpc); return 0; } @@ -1012,6 +1014,7 @@ static inline bool mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; int tx_ant = hweight8(phy->mt76->chainmask) - 1; if (vif->type != NL80211_IFTYPE_STATION && @@ -1025,10 +1028,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; if (bfee) - return vif->bss_conf.he_su_beamformee && + return mvif->cap.he_su_ebfee && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); else - return vif->bss_conf.he_su_beamformer && + return mvif->cap.he_su_ebfer && HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } @@ -1036,10 +1039,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, u32 cap = sta->deflink.vht_cap.cap; if (bfee) - return vif->bss_conf.vht_su_beamformee && + return mvif->cap.vht_su_ebfee && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); else - return vif->bss_conf.vht_su_beamformer && + return mvif->cap.vht_su_ebfer && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); } @@ -1534,7 +1537,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_TX_STBC; if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (vif->bss_conf.ht_ldpc && + if (mvif->cap.ht_ldpc && (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; @@ -1560,7 +1563,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_VHT_TX_STBC; if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (vif->bss_conf.vht_ldpc && + if (mvif->cap.vht_ldpc && (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 0c7226b8c805..0456e56f6348 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -152,9 +152,23 @@ struct mt7915_sta { } twt; }; +struct mt7915_vif_cap { + bool ht_ldpc:1; + bool vht_ldpc:1; + bool he_ldpc:1; + bool vht_su_ebfer:1; + bool vht_su_ebfee:1; + bool vht_mu_ebfer:1; + bool vht_mu_ebfee:1; + bool he_su_ebfer:1; + bool he_su_ebfee:1; + bool he_mu_ebfer:1; +}; + struct mt7915_vif { struct mt76_vif mt76; /* must be first */ + struct mt7915_vif_cap cap; struct mt7915_sta sta; struct mt7915_phy *phy; -- cgit From 7d424a990e050ac09a0646edca083dcb4a516855 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 8 Jul 2023 20:29:35 +0200 Subject: wifi: mt76: split get_of_eeprom in subfunction In preparation for NVMEM support, split get_of_eeprom() in subfunction to tidy the code and facilitate the addition of alternative method to get eeprom data. No behaviour change intended. While at it also drop OF ifdef checks as OF have stubs and calling of_get_property would result in the same error returned. Signed-off-by: Christian Marangi Reviewed-by: Daniel Golle Tested-by: Daniel Golle Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/eeprom.c | 51 ++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index dce851d42e08..c3a762074be8 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -9,31 +9,35 @@ #include #include "mt76.h" -int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) +static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len) { -#if defined(CONFIG_OF) && defined(CONFIG_MTD) struct device_node *np = dev->dev->of_node; - struct mtd_info *mtd; - const __be32 *list; const void *data; - const char *part; - phandle phandle; int size; - size_t retlen; - int ret; - if (!np) + data = of_get_property(np, "mediatek,eeprom-data", &size); + if (!data) return -ENOENT; - data = of_get_property(np, "mediatek,eeprom-data", &size); - if (data) { - if (size > len) - return -EINVAL; + if (size > len) + return -EINVAL; - memcpy(eep, data, size); + memcpy(eep, data, size); - return 0; - } + return 0; +} + +static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len) +{ +#ifdef CONFIG_MTD + struct device_node *np = dev->dev->of_node; + struct mtd_info *mtd; + const __be32 *list; + const char *part; + phandle phandle; + size_t retlen; + int size; + int ret; list = of_get_property(np, "mediatek,mtd-eeprom", &size); if (!list) @@ -100,6 +104,21 @@ out_put_node: return -ENOENT; #endif } + +int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) +{ + struct device_node *np = dev->dev->of_node; + int ret; + + if (!np) + return -ENOENT; + + ret = mt76_get_of_eeprom_data(dev, eep, len); + if (!ret) + return 0; + + return mt76_get_of_epprom_from_mtd(dev, eep, offset, len); +} EXPORT_SYMBOL_GPL(mt76_get_of_eeprom); void -- cgit From 5bef3a406c6e7c4a1d5db69938a08ea70aa9c388 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 8 Jul 2023 20:29:36 +0200 Subject: wifi: mt76: add support for providing eeprom in nvmem cells Add support for providing eeprom in nvmem cells by adding nvmem cell as an alternative source for mt76_get_of_eeprom(). Nvmem cells will follow standard nvmem cell definition and needs to be called 'eeprom' to be correctly identified. Signed-off-by: Christian Marangi Reviewed-by: Daniel Golle Tested-by: Daniel Golle Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/eeprom.c | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index c3a762074be8..36564930aef1 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "mt76.h" @@ -105,6 +106,37 @@ out_put_node: #endif } +static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int len) +{ + struct device_node *np = dev->dev->of_node; + struct nvmem_cell *cell; + const void *data; + size_t retlen; + int ret = 0; + + cell = of_nvmem_cell_get(np, "eeprom"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + data = nvmem_cell_read(cell, &retlen); + nvmem_cell_put(cell); + + if (IS_ERR(data)) + return PTR_ERR(data); + + if (retlen < len) { + ret = -EINVAL; + goto exit; + } + + memcpy(eep, data, len); + +exit: + kfree(data); + + return ret; +} + int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) { struct device_node *np = dev->dev->of_node; @@ -117,7 +149,11 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) if (!ret) return 0; - return mt76_get_of_epprom_from_mtd(dev, eep, offset, len); + ret = mt76_get_of_epprom_from_mtd(dev, eep, offset, len); + if (!ret) + return 0; + + return mt76_get_of_epprom_from_nvmem(dev, eep, len); } EXPORT_SYMBOL_GPL(mt76_get_of_eeprom); -- cgit From 3ec5ac12ac8a4e6b1e085374325a5fbd1b650fd5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 14 Jul 2023 10:57:15 +0200 Subject: wifi: mt76: mt7915: remove VHT160 capability on MT7915 The IEEE80211_VHT_CAP_EXT_NSS_BW value already indicates support for half-NSS 160 MHz support, so it is wrong to also advertise full 160 MHz support. Fixes: c2f73eacee3b ("wifi: mt76: mt7915: add back 160MHz channel width support for MT7915") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ee976657bfc3..78552f10b377 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -414,7 +414,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy) if (!dev->dbdc_support) vht_cap->cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1); } else { vht_cap->cap |= -- cgit From f090d0ca0de92aa378f342011d16f5d310a8383f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 25 Jul 2023 12:37:59 +0200 Subject: wifi: mt76: mt7603: fix beacon interval after disabling a single vif When disabling beacons on a vif, intval is 0. Ensure that dev->mt76.beacon_int is not overwritten in this case, so that beacons continue to work for other interfaces. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index b65b0a88c1de..888678732f29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -161,7 +161,8 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) return; } - dev->mt76.beacon_int = intval; + if (intval) + dev->mt76.beacon_int = intval; mt76_wr(dev, MT_TBTT, FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE); -- cgit From fe0ea395f0a35103f61e107b227bf8bc4b9765df Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 25 Jul 2023 21:06:03 +0200 Subject: wifi: mt76: mt7603: fix tx filter/flush function Setting MT_TX_ABORT does not abort any transmission for a wtbl index on its own. Instead, it modifies the behavior of a queue flush to make it selectively flush packets for a particular wtbl index. Adjust powersave filtering to make use of this in order to avoid running into unnecessary timeouts while flushing Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 21 ++++++++++++++++----- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 5 ++++- drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/regs.h | 7 +++++++ 4 files changed, 28 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index de11557eb04c..99ae080502d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -178,8 +178,9 @@ mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled) mt76_wr(dev, addr + 3 * 4, val); } -void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) +void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort) { + u32 flush_mask; int i, port, queue; if (abort) { @@ -195,6 +196,18 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN | FIELD_PREP(MT_TX_ABORT_WCID, idx)); + flush_mask = MT_WF_ARB_TX_FLUSH_AC0 | + MT_WF_ARB_TX_FLUSH_AC1 | + MT_WF_ARB_TX_FLUSH_AC2 | + MT_WF_ARB_TX_FLUSH_AC3; + flush_mask <<= mac_idx; + + mt76_wr(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask); + mt76_poll(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask, 0, 20000); + mt76_wr(dev, MT_WF_ARB_TX_START_0, flush_mask); + + mt76_wr(dev, MT_TX_ABORT, 0); + for (i = 0; i < 4; i++) { mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) | @@ -202,13 +215,11 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); - mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000); + mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000); } WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY); - mt76_wr(dev, MT_TX_ABORT, 0); - mt7603_wtbl_set_skip_tx(dev, idx, false); } @@ -245,7 +256,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); if (enabled) - mt7603_filter_tx(dev, idx, false); + mt7603_filter_tx(dev, sta->vif->idx, idx, false); addr = mt7603_wtbl1_addr(idx); mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 1d4893410ca5..c213fd2a5216 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; + mvif->sta.vif = mvif; mt76_packet_id_init(&mvif->sta.wcid); eth_broadcast_addr(bc_addr); @@ -357,6 +358,7 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->smps = ~0; msta->wcid.sta = 1; msta->wcid.idx = idx; + msta->vif = mvif; mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); mt7603_wtbl_set_ps(dev, msta, false); @@ -380,12 +382,13 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; spin_lock_bh(&dev->ps_lock); __skb_queue_purge(&msta->psq); - mt7603_filter_tx(dev, wcid->idx, true); + mt7603_filter_tx(dev, mvif->idx, wcid->idx, true); spin_unlock_bh(&dev->ps_lock); spin_lock_bh(&mdev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 354b189862f7..9e58df7042ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -230,7 +230,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, bool enabled); void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, bool enabled); -void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort); +void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort); int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 3b901090b29c..a39c9a0fcb1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -309,6 +309,13 @@ enum { #define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110) #define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114) +#define MT_WF_ARB_TX_FLUSH_AC0 BIT(0) +#define MT_WF_ARB_TX_FLUSH_AC1 BIT(5) +#define MT_WF_ARB_TX_FLUSH_AC2 BIT(10) +#define MT_WF_ARB_TX_FLUSH_AC3 BIT(16) +#define MT_WF_ARB_TX_FLUSH_AC4 BIT(21) +#define MT_WF_ARB_TX_FLUSH_AC5 BIT(26) + #define MT_WF_ARB_BCN_START MT_WF_ARB(0x118) #define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n)) #define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10) -- cgit From 6db1b497b04e0e3dff755e0c2a6644c2379d32e2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:47 +0800 Subject: wifi: mt76: mt7921: move common register definition in mt792x_regs.h This is a preliminary patch in order to support new WiFi7 chips. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 443 +--------------------- drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 460 +++++++++++++++++++++++ 2 files changed, 463 insertions(+), 440 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_regs.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index b180142562a2..fefc10539586 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -4,26 +4,7 @@ #ifndef __MT7921_REGS_H #define __MT7921_REGS_H -/* MCU WFDMA1 */ -#define MT_MCU_WFDMA1_BASE 0x3000 -#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) - -#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) -#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) -#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) -#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) -#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) - -#define MT_PLE_BASE 0x820c0000 -#define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) - -#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) -#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) -#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) -#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) - -#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) -#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) +#include "../mt792x_regs.h" #define MT_MDP_BASE 0x820cd000 #define MT_MDP(ofs) (MT_MDP_BASE + (ofs)) @@ -47,266 +28,6 @@ #define MT_MDP_TO_HIF 0 #define MT_MDP_TO_WM 1 -/* TMAC: band 0(0x21000), band 1(0xa1000) */ -#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) -#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) - -#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) -#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) - -#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) -#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) -#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) -#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) - -#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) -#define MT_IFS_EIFS GENMASK(8, 0) -#define MT_IFS_RIFS GENMASK(14, 10) -#define MT_IFS_SIFS GENMASK(22, 16) -#define MT_IFS_SLOT GENMASK(30, 24) - -#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) -#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) -#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) -#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) - -#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) -#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) - -#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000) -#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) - -#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) -#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) -#define MT_DMA_DCR0_RXD_G5_EN BIT(23) - -/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */ -#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000) -#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs)) - -#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008) -#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30) -#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24) - -/* LPON: band 0(0x24200), band 1(0xa4200) */ -#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000) -#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs)) - -#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080) -#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084) - -#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4) -#define MT_LPON_TCR_SW_MODE GENMASK(1, 0) -#define MT_LPON_TCR_SW_WRITE BIT(0) - -/* ETBF: band 0(0x24000), band 1(0xa4000) */ -#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) -#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) - -#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150) -#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) -#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0) - -#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158) -#define MT_ETBF_RX_FB_ALL GENMASK(31, 24) -#define MT_ETBF_RX_FB_HE GENMASK(23, 16) -#define MT_ETBF_RX_FB_VHT GENMASK(15, 8) -#define MT_ETBF_RX_FB_HT GENMASK(7, 0) - -/* MIB: band 0(0x24800), band 1(0xa4800) */ -#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) -#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) - -#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) -#define MT_MIB_TXDUR_EN BIT(8) -#define MT_MIB_RXDUR_EN BIT(9) - -#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) -#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) - -#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780) - -#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) -#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) - -#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558) -#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564) -#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568) - -#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048) -#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0) - -#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770) -#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774) -#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c) - -#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8) -#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16) -#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0) - -#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) -#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) - -#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) -#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) -#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) - -#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) -#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4) -#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc) - -#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) -#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) - -#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690) -#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518) -#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520) -#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0) - -#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) -#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) - -#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2)) -#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2)) -#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2)) -#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) - -#define MT_WTBLON_TOP_BASE 0x820d4000 -#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) -#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) - -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) -#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) -#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) -#define MT_WTBL_UPDATE_BUSY BIT(31) - -#define MT_WTBL_BASE 0x820d8000 -#define MT_WTBL_LMAC_ID GENMASK(14, 8) -#define MT_WTBL_LMAC_DW GENMASK(7, 2) -#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ - FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ - FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) - -/* AGG: band 0(0x20800), band 1(0xa0800) */ -#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) -#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) - -#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) -#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) -#define MT_AGG_PCR0_MM_PROT BIT(0) -#define MT_AGG_PCR0_GF_PROT BIT(1) -#define MT_AGG_PCR0_BW20_PROT BIT(2) -#define MT_AGG_PCR0_BW40_PROT BIT(4) -#define MT_AGG_PCR0_BW80_PROT BIT(6) -#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8) -#define MT_AGG_PCR0_VHT_PROT BIT(13) -#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) - -#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) -#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) - -#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) -#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) -#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) - -#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) -#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) -#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) -#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) -#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) - -#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) -#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) - -/* ARB: band 0(0x20c00), band 1(0xa0c00) */ -#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000) -#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) - -#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) -#define MT_ARB_SCR_TX_DISABLE BIT(8) -#define MT_ARB_SCR_RX_DISABLE BIT(9) - -#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) - -/* RMAC: band 0(0x21400), band 1(0xa1400) */ -#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) -#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) - -#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) -#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) -#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) -#define MT_WF_RFCR_DROP_VERSION BIT(3) -#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) -#define MT_WF_RFCR_DROP_MCAST BIT(5) -#define MT_WF_RFCR_DROP_BCAST BIT(6) -#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) -#define MT_WF_RFCR_DROP_A3_MAC BIT(8) -#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) -#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) -#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) -#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) -#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) -#define MT_WF_RFCR_DROP_CTS BIT(14) -#define MT_WF_RFCR_DROP_RTS BIT(15) -#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) -#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) -#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) -#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) -#define MT_WF_RFCR_DROP_NDPA BIT(20) -#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) - -#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004) -#define MT_WF_RFCR1_DROP_ACK BIT(4) -#define MT_WF_RFCR1_DROP_BF_POLL BIT(5) -#define MT_WF_RFCR1_DROP_BA BIT(6) -#define MT_WF_RFCR1_DROP_CFEND BIT(7) -#define MT_WF_RFCR1_DROP_CFACK BIT(8) - -#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4) -#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) -#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) - -#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8) -#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) -#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380) - -/* WFDMA0 */ -#define MT_WFDMA0_BASE 0xd4000 -#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) - -#define MT_WFDMA0_RST MT_WFDMA0(0x100) -#define MT_WFDMA0_RST_LOGIC_RST BIT(4) -#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5) - -#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c) -#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0) -#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1) -#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) - -#define MT_MCU_CMD MT_WFDMA0(0x1f0) -#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0) -#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) -#define MT_MCU_CMD_STOP_DMA BIT(2) -#define MT_MCU_CMD_RESET_DONE BIT(3) -#define MT_MCU_CMD_RECOVERY_DONE BIT(4) -#define MT_MCU_CMD_NORMAL_STATE BIT(5) -#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) - -#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4) - -#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200) -#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */ -#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */ -#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */ -#define HOST_TX_DONE_INT_STS16 BIT(26) -#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/ - #define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204) #define HOST_RX_DONE_INT_ENA0 BIT(0) #define HOST_RX_DONE_INT_ENA1 BIT(1) @@ -354,56 +75,8 @@ MT_INT_TX_DONE_BAND0 | \ GENMASK(18, 4)) -#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) -#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) -#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1) -#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) -#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) -#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) -#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) -#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) -#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) -#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) -#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) -#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) -#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30) - -#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) -#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) -#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6) -#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) - #define MT_RX_DATA_RING_BASE MT_WFDMA0(0x520) -#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600) -#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604) -#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608) -#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c) -#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610) -#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614) -#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618) -#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) -#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) - -#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) -#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) - -#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) -#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) -#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) -#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c) -#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690) -#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694) - -#define MT_TX_RING_BASE MT_WFDMA0(0x300) -#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500) - -/* WFDMA CSR */ -#define MT_WFDMA_EXT_CSR_BASE 0xd7000 -#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) -#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) -#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) - #define MT_INFRA_CFG_BASE 0xfe000 #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) @@ -413,121 +86,11 @@ #define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) #define MT_HIF_REMAP_BASE_L1 0x40000 -#define MT_SWDEF_BASE 0x41f200 -#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) -#define MT_SWDEF_MODE MT_SWDEF(0x3c) -#define MT_SWDEF_NORMAL_MODE 0 -#define MT_SWDEF_ICAP_MODE 1 -#define MT_SWDEF_SPECTRUM_MODE 2 - -#define MT_TOP_BASE 0x18060000 -#define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) - -#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) -#define MT_TOP_LPCR_HOST_FW_OWN BIT(0) -#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) - -#define MT_TOP_MISC MT_TOP(0xf0) -#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) - -#define MT_MCU_WPDMA0_BASE 0x54000000 -#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs)) - -#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) -#define MT_WFDMA_NEED_REINIT BIT(1) - -#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) -#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) -#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) - -#define MT_HW_BOUND 0x70010020 -#define MT_HW_CHIPID 0x70010200 -#define MT_HW_REV 0x70010204 - -#define MT_PCIE_MAC_BASE 0x10000 -#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) -#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) -#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194) -#define MT_PCIE_MAC_PM_L0S_DIS BIT(8) - -#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) -#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) -#define MT_DMASHDL_DMASHDL_BYPASS BIT(28) -#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) -#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) -#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) -#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) -#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) -#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) -#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) -#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) - -#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2)) -#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) -#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) - -#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2)) -#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) -#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) - -#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) - -#define MT_WFDMA_HOST_CONFIG 0x7c027030 -#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) - -#define MT_UMAC(ofs) (0x74000000 + (ofs)) -#define MT_UDMA_TX_QSEL MT_UMAC(0x008) -#define MT_FW_DL_EN BIT(3) - -#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) -#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) -#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) - -#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) -#define MT_WL_RX_AGG_TO GENMASK(7, 0) -#define MT_WL_RX_AGG_LMT GENMASK(15, 8) -#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) -#define MT_WL_TX_DPH_CHK_EN BIT(17) -#define MT_WL_RX_MPSZ_PAD0 BIT(18) -#define MT_WL_RX_FLUSH BIT(19) -#define MT_TICK_1US_EN BIT(20) -#define MT_WL_RX_AGG_EN BIT(21) -#define MT_WL_RX_EN BIT(22) -#define MT_WL_TX_EN BIT(23) -#define MT_WL_RX_BUSY BIT(30) -#define MT_WL_TX_BUSY BIT(31) - -#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) -#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) -#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) - -#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) -#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) - -#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) -#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) -#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) -#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) - -#define MT_CONN_STATUS 0x7c053c10 -#define MT_WIFI_PATCH_DL_STATE BIT(0) - -#define MT_CONN_ON_LPCTL 0x7c060010 -#define PCIE_LPCR_HOST_OWN_SYNC BIT(2) -#define PCIE_LPCR_HOST_CLR_OWN BIT(1) -#define PCIE_LPCR_HOST_SET_OWN BIT(0) - #define MT_WFSYS_SW_RST_B 0x18000140 #define WFSYS_SW_RST_B BIT(0) #define WFSYS_SW_INIT_DONE BIT(4) -#define MT_CONN_ON_MISC 0x7c0600f0 -#define MT_TOP_MISC2_FW_PWR_ON BIT(0) -#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) - -#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) -#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) -#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) -#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) +#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h new file mode 100644 index 000000000000..aa6a677427a4 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -0,0 +1,460 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT792X_REGS_H +#define __MT792X_REGS_H + +/* MCU WFDMA1 */ +#define MT_MCU_WFDMA1_BASE 0x3000 +#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) + +#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) +#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + +#define MT_PLE_BASE 0x820c0000 +#define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) + +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) +#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) +#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) +#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) + +#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) +#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) + +/* TMAC: band 0(0x21000), band 1(0xa1000) */ +#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) +#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) + +#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) +#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) + +#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) +#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + +#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) +#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) +#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) +#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) + +#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) +#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) + +#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000) +#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) + +#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) +#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) +#define MT_DMA_DCR0_RXD_G5_EN BIT(23) + +/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */ +#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000) +#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs)) + +#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008) +#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30) +#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24) + +/* LPON: band 0(0x24200), band 1(0xa4200) */ +#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000) +#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs)) + +#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080) +#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084) + +#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4) +#define MT_LPON_TCR_SW_MODE GENMASK(1, 0) +#define MT_LPON_TCR_SW_WRITE BIT(0) + +/* ETBF: band 0(0x24000), band 1(0xa4000) */ +#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) +#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) + +#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150) +#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) +#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0) + +#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158) +#define MT_ETBF_RX_FB_ALL GENMASK(31, 24) +#define MT_ETBF_RX_FB_HE GENMASK(23, 16) +#define MT_ETBF_RX_FB_VHT GENMASK(15, 8) +#define MT_ETBF_RX_FB_HT GENMASK(7, 0) + +/* MIB: band 0(0x24800), band 1(0xa4800) */ +#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) +#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) + +#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) +#define MT_MIB_TXDUR_EN BIT(8) +#define MT_MIB_RXDUR_EN BIT(9) + +#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) + +#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780) + +#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) +#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558) +#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564) +#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568) + +#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048) +#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770) +#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774) +#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c) + +#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8) +#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16) +#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0) + +#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) +#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) + +#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) +#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) +#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) +#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) + +#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) +#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4) +#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc) + +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) +#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) + +#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690) +#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518) +#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) +#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) + +#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2)) +#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2)) +#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2)) +#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) + +#define MT_WTBLON_TOP_BASE 0x820d4000 +#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) + +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) +#define MT_WTBL_UPDATE_BUSY BIT(31) + +#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0) +#define MT_WTBL_ITCR_WR BIT(16) +#define MT_WTBL_ITCR_EXEC BIT(31) +#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8) +#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc) +#define MT_WTBL_SPE_IDX_SEL BIT(6) + +#define MT_WTBL_BASE 0x820d8000 +#define MT_WTBL_LMAC_ID GENMASK(14, 8) +#define MT_WTBL_LMAC_DW GENMASK(7, 2) +#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ + FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ + FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) + +/* AGG: band 0(0x20800), band 1(0xa0800) */ +#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) +#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) + +#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) +#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) +#define MT_AGG_PCR0_MM_PROT BIT(0) +#define MT_AGG_PCR0_GF_PROT BIT(1) +#define MT_AGG_PCR0_BW20_PROT BIT(2) +#define MT_AGG_PCR0_BW40_PROT BIT(4) +#define MT_AGG_PCR0_BW80_PROT BIT(6) +#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8) +#define MT_AGG_PCR0_VHT_PROT BIT(13) +#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) + +#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) +#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) + +#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) +#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) +#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) + +#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) +#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) +#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) +#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) +#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) + +#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) +#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) + +/* ARB: band 0(0x20c00), band 1(0xa0c00) */ +#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000) +#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) + +#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) +#define MT_ARB_SCR_TX_DISABLE BIT(8) +#define MT_ARB_SCR_RX_DISABLE BIT(9) + +#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) + +/* RMAC: band 0(0x21400), band 1(0xa1400) */ +#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) +#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) + +#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) +#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) +#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) +#define MT_WF_RFCR_DROP_VERSION BIT(3) +#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) +#define MT_WF_RFCR_DROP_MCAST BIT(5) +#define MT_WF_RFCR_DROP_BCAST BIT(6) +#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) +#define MT_WF_RFCR_DROP_A3_MAC BIT(8) +#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) +#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) +#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) +#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) +#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) +#define MT_WF_RFCR_DROP_CTS BIT(14) +#define MT_WF_RFCR_DROP_RTS BIT(15) +#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) +#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) +#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) +#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) +#define MT_WF_RFCR_DROP_NDPA BIT(20) +#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) + +#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004) +#define MT_WF_RFCR1_DROP_ACK BIT(4) +#define MT_WF_RFCR1_DROP_BF_POLL BIT(5) +#define MT_WF_RFCR1_DROP_BA BIT(6) +#define MT_WF_RFCR1_DROP_CFEND BIT(7) +#define MT_WF_RFCR1_DROP_CFACK BIT(8) + +#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4) +#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) +#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) + +#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8) +#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) +#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380) + +/* WFDMA0 */ +#define MT_WFDMA0_BASE 0xd4000 +#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) + +#define MT_WFDMA0_RST MT_WFDMA0(0x100) +#define MT_WFDMA0_RST_LOGIC_RST BIT(4) +#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5) + +#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) + +#define MT_MCU_CMD MT_WFDMA0(0x1f0) +#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0) +#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_DMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) + +#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4) + +#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200) +#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */ +#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */ +#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */ +#define HOST_TX_DONE_INT_STS16 BIT(26) +#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/ + +#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) +#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1) +#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) +#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) +#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) +#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) +#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) +#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30) + +#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) +#define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280) +#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) +#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6) +#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) + +#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600) +#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604) +#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608) +#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c) +#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610) +#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614) +#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618) +#define MT_WFDMA0_TX_RING15_EXT_CTRL MT_WFDMA0(0x63c) +#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) +#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) + +#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) +#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) + +#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) +#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) +#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) +#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c) +#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690) +#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694) +#define MT_WFDMA0_RX_RING6_EXT_CTRL MT_WFDMA0(0x698) +#define MT_WFDMA0_RX_RING7_EXT_CTRL MT_WFDMA0(0x69c) + +#define MT_TX_RING_BASE MT_WFDMA0(0x300) +#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500) + +/* WFDMA CSR */ +#define MT_WFDMA_EXT_CSR_BASE 0xd7000 +#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) +#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) +#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) + +#define MT_SWDEF_BASE 0x41f200 +#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) +#define MT_SWDEF_MODE MT_SWDEF(0x3c) +#define MT_SWDEF_NORMAL_MODE 0 +#define MT_SWDEF_ICAP_MODE 1 +#define MT_SWDEF_SPECTRUM_MODE 2 + +#define MT_TOP_BASE 0x18060000 +#define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) + +#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) +#define MT_TOP_LPCR_HOST_FW_OWN BIT(0) +#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) + +#define MT_TOP_MISC MT_TOP(0xf0) +#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) + +#define MT_MCU_WPDMA0_BASE 0x54000000 +#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs)) + +#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) +#define MT_WFDMA_NEED_REINIT BIT(1) + +#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) +#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) +#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) + +#define MT_HW_BOUND 0x70010020 +#define MT_HW_CHIPID 0x70010200 +#define MT_HW_REV 0x70010204 + +#define MT_PCIE_MAC_BASE 0x10000 +#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) +#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) +#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194) +#define MT_PCIE_MAC_PM_L0S_DIS BIT(8) + +#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) +#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) +#define MT_DMASHDL_DMASHDL_BYPASS BIT(28) +#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) +#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) +#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) +#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) +#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) +#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) +#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) +#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) + +#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2)) +#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) +#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) + +#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2)) +#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) +#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) + +#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) + +#define MT_WFDMA_HOST_CONFIG 0x7c027030 +#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) + +#define MT_UMAC(ofs) (0x74000000 + (ofs)) +#define MT_UDMA_TX_QSEL MT_UMAC(0x008) +#define MT_FW_DL_EN BIT(3) + +#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) +#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) +#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) + +#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) +#define MT_WL_RX_AGG_TO GENMASK(7, 0) +#define MT_WL_RX_AGG_LMT GENMASK(15, 8) +#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) +#define MT_WL_TX_DPH_CHK_EN BIT(17) +#define MT_WL_RX_MPSZ_PAD0 BIT(18) +#define MT_WL_RX_FLUSH BIT(19) +#define MT_TICK_1US_EN BIT(20) +#define MT_WL_RX_AGG_EN BIT(21) +#define MT_WL_RX_EN BIT(22) +#define MT_WL_TX_EN BIT(23) +#define MT_WL_RX_BUSY BIT(30) +#define MT_WL_TX_BUSY BIT(31) + +#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) +#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) +#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) + +#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) +#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) + +#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) +#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) +#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) +#define MT_UWFDMA0_GLO_CFG_EXT1 MT_UWFDMA0(0x2b4) +#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) + +#define MT_CONN_STATUS 0x7c053c10 +#define MT_WIFI_PATCH_DL_STATE BIT(0) + +#define MT_CONN_ON_LPCTL 0x7c060010 +#define PCIE_LPCR_HOST_SET_OWN BIT(0) +#define PCIE_LPCR_HOST_CLR_OWN BIT(1) +#define PCIE_LPCR_HOST_OWN_SYNC BIT(2) + +#define MT_CONN_ON_MISC 0x7c0600f0 +#define MT_TOP_MISC2_FW_PWR_ON BIT(0) +#define MT_TOP_MISC2_FW_N9_ON BIT(1) +#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) + +#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) +#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) +#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) +#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) + +#endif /* __MT792X_REGS_H */ -- cgit From 95a686dcaea0948d2e98fcac7f79df91c56d2f21 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:48 +0800 Subject: wifi: mt76: mt7921: convert acpisar and clc pointers to void Convert acpisar and clc pointers in mt7921_dev structure to void. This is a preliminary patch to add WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c | 5 +++-- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c index 48dd0decac5d..6feea2e515b3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c @@ -308,6 +308,7 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) u8 mt7921_acpi_get_flags(struct mt7921_phy *phy) { + struct mt7921_acpi_sar *acpisar = phy->acpisar; struct mt7921_asar_fg *fg; struct { u8 acpi_idx; @@ -319,10 +320,10 @@ u8 mt7921_acpi_get_flags(struct mt7921_phy *phy) u8 flags = BIT(0); int i, j; - if (!phy->acpisar) + if (!acpisar) return 0; - fg = phy->acpisar->fg; + fg = acpisar->fg; if (!fg) return flags; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index ec9879650174..2e29a6bda7ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -222,10 +222,9 @@ struct mt7921_phy { struct sk_buff_head scan_event_list; struct delayed_work scan_work; #ifdef CONFIG_ACPI - struct mt7921_acpi_sar *acpisar; + void *acpisar; #endif - - struct mt7921_clc *clc[MT7921_CLC_MAX_NUM]; + void *clc[MT7921_CLC_MAX_NUM]; struct work_struct roc_work; struct timer_list roc_timer; -- cgit From 15ca8970efdbe9e9cc56d334ad1556840d6f77a2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:49 +0800 Subject: wifi: mt76: mt7921: rename mt7921_vif in mt792x_vif This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 52 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 20 ++++----- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 12 ++--- 5 files changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 94b7cdfd018b..f2a6fd61863b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -141,7 +141,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) phy->slottime = 9; hw->sta_data_size = sizeof(struct mt7921_sta); - hw->vif_data_size = sizeof(struct mt7921_vif); + hw->vif_data_size = sizeof(struct mt792x_vif); if (dev->fw_features & MT7921_FW_CAP_CNM) { wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 368f92719abf..44b0122073f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -204,7 +204,7 @@ mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct sk_buff *skb = priv; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); if (status->signal > 0) @@ -819,7 +819,7 @@ static void mt7921_vif_connect_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mvif->phy->dev; struct ieee80211_hw *hw = mt76_hw(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 87067ac367eb..de8c3a02cf4b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -284,7 +284,7 @@ EXPORT_SYMBOL_GPL(mt7921_stop); static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt76_txq *mtxq; @@ -341,7 +341,7 @@ out: static void mt7921_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_sta *msta = &mvif->sta; struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); @@ -368,7 +368,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, static void mt7921_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_phy *phy = priv; mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id); @@ -399,7 +399,7 @@ void mt7921_roc_timer(struct timer_list *timer) ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); } -static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif) +static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif) { int err = 0; @@ -415,7 +415,7 @@ static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif) } static int mt7921_set_roc(struct mt7921_phy *phy, - struct mt7921_vif *vif, + struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type) @@ -450,7 +450,7 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, int duration, enum ieee80211_roc_type type) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_phy *phy = mt7921_hw_phy(hw); int err; @@ -464,7 +464,7 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_phy *phy = mt7921_hw_phy(hw); return mt7921_abort_roc(phy, mvif); @@ -507,7 +507,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; @@ -667,7 +667,7 @@ mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; /* no need to update right away, we'll get BSS_CHANGED_QOS */ queue = mt76_connac_lmac_mapping(queue); @@ -743,7 +743,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ARP_FILTER) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt76_connac_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, info); @@ -757,7 +757,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int ret, idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); @@ -798,7 +798,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt7921_mutex_acquire(dev); @@ -832,7 +832,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); if (vif->type == NL80211_IFTYPE_STATION) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mvif->wep_sta = NULL; ewma_rssi_init(&mvif->rssi); @@ -884,9 +884,9 @@ static void mt7921_tx(struct ieee80211_hw *hw, } if (vif && !control->sta) { - struct mt7921_vif *mvif; + struct mt792x_vif *mvif; - mvif = (struct mt7921_vif *)vif->drv_priv; + mvif = (struct mt792x_vif *)vif->drv_priv; wcid = &mvif->sta.wcid; } @@ -1133,7 +1133,7 @@ static void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ethtool_stats *stats, u64 *data) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; @@ -1203,7 +1203,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static u64 mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { @@ -1229,7 +1229,7 @@ static void mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { @@ -1521,7 +1521,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct inet6_dev *idev) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mvif->phy->dev; struct inet6_ifaddr *ifa; struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; @@ -1630,7 +1630,7 @@ static int mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); int err; @@ -1658,7 +1658,7 @@ static void mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); int err; @@ -1692,7 +1692,7 @@ mt7921_remove_chanctx(struct ieee80211_hw *hw, static void mt7921_ctx_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct ieee80211_chanctx_conf *ctx = priv; if (ctx != mvif->ctx) @@ -1724,7 +1724,7 @@ mt7921_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); mutex_lock(&dev->mt76.mutex); @@ -1740,7 +1740,7 @@ mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); mutex_lock(&dev->mt76.mutex); @@ -1752,7 +1752,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); u16 duration = info->duration ? info->duration : jiffies_to_msecs(HZ); @@ -1767,7 +1767,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt7921_abort_roc(mvif->phy, mvif); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index a0ad18c70b1a..4d8b4c802739 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -96,7 +96,7 @@ static int mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -543,7 +543,7 @@ EXPORT_SYMBOL_GPL(mt7921_run_firmware); int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct edca { __le16 cw_min; __le16 cw_max; @@ -635,7 +635,7 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) &req_mu, sizeof(req_mu), false); } -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id) { @@ -702,7 +702,7 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, u8 token_id) { struct mt7921_dev *dev = phy->dev; @@ -809,7 +809,7 @@ EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom); int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -848,7 +848,7 @@ static int mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -884,7 +884,7 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { u8 bss_idx; u8 dtim_period; @@ -922,7 +922,7 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int rssi = -ewma_rssi_read(&mvif->rssi); struct mt76_sta_cmd_info info = { .sta = sta, @@ -1074,7 +1074,7 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, true); } -int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, +int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx) { struct cfg80211_chan_def *chandef = &ctx->def; @@ -1148,7 +1148,7 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct ieee80211_mutable_offsets offs; struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 2e29a6bda7ad..6ec5b19f3c25 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -127,7 +127,7 @@ struct mt7921_sdio_intr { #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) #define to_rcpi(rssi) (2 * (rssi) + 220) -struct mt7921_vif; +struct mt792x_vif; struct mt7921_sta; enum mt7921_txq_id { @@ -148,7 +148,7 @@ DECLARE_EWMA(avg_signal, 10, 8) struct mt7921_sta { struct mt76_wcid wcid; /* must be first */ - struct mt7921_vif *vif; + struct mt792x_vif *vif; u32 airtime_ac[8]; @@ -162,7 +162,7 @@ struct mt7921_sta { DECLARE_EWMA(rssi, 10, 8); -struct mt7921_vif { +struct mt792x_vif { struct mt76_vif mt76; /* must be first */ struct mt7921_sta sta; @@ -497,7 +497,7 @@ void mt7921_set_ipv6_ns_work(struct work_struct *work); int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, +int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx); int mt7921_mcu_get_temperature(struct mt7921_phy *phy); @@ -550,10 +550,10 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, enum environment_cap env_cap); -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id); -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, u8 token_id); struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features); -- cgit From b7bfad2c83cdbbd7cd502bebdc75ef703c980634 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:50 +0800 Subject: wifi: mt76: mt7921: rename mt7921_sta in mt792x_sta This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 22 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 22 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 8 ++++---- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index f2a6fd61863b..df32f4f1b636 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -140,7 +140,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) phy->slottime = 9; - hw->sta_data_size = sizeof(struct mt7921_sta); + hw->sta_data_size = sizeof(struct mt792x_sta); hw->vif_data_size = sizeof(struct mt792x_vif); if (dev->fw_features & MT7921_FW_CAP_CNM) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 44b0122073f8..d4cf2ff18102 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -23,7 +23,7 @@ static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, u16 idx, bool unicast) { - struct mt7921_sta *sta; + struct mt792x_sta *sta; struct mt76_wcid *wcid; if (idx >= ARRAY_SIZE(dev->mt76.wcid)) @@ -36,7 +36,7 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, if (!wcid->sta) return NULL; - sta = container_of(wcid, struct mt7921_sta, wcid); + sta = container_of(wcid, struct mt792x_sta, wcid); if (!sta->vif) return NULL; @@ -61,7 +61,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) [IEEE80211_AC_VO] = 6 }; struct ieee80211_sta *sta; - struct mt7921_sta *msta; + struct mt792x_sta *msta; u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; LIST_HEAD(sta_poll_list); struct rate_info *rate; @@ -84,7 +84,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) break; } msta = list_first_entry(&sta_poll_list, - struct mt7921_sta, wcid.poll_list); + struct mt792x_sta, wcid.poll_list); list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); @@ -248,7 +248,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); - struct mt7921_sta *msta = NULL; + struct mt792x_sta *msta = NULL; u16 seq_ctrl = 0; __le16 fc = 0; u8 mode = 0; @@ -279,7 +279,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - msta = container_of(status->wcid, struct mt7921_sta, wcid); + msta = container_of(status->wcid, struct mt792x_sta, wcid); spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&msta->wcid.poll_list)) list_add_tail(&msta->wcid.poll_list, @@ -513,7 +513,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) { - struct mt7921_sta *msta = NULL; + struct mt792x_sta *msta = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; @@ -537,7 +537,7 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) if (!wcid) goto out; - msta = container_of(wcid, struct mt7921_sta, wcid); + msta = container_of(wcid, struct mt792x_sta, wcid); mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); if (!wcid->sta) @@ -582,7 +582,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) * 1'b0: msdu_id with the same 'wcid pair' as above. */ if (info & MT_TX_FREE_PAIR) { - struct mt7921_sta *msta; + struct mt792x_sta *msta; u16 idx; count++; @@ -592,7 +592,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) if (!sta) continue; - msta = container_of(wcid, struct mt7921_sta, wcid); + msta = container_of(wcid, struct mt792x_sta, wcid); spin_lock_bh(&mdev->sta_poll_lock); if (list_empty(&msta->wcid.poll_list)) list_add_tail(&msta->wcid.poll_list, @@ -1140,7 +1140,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, wcid = &dev->mt76.global_wcid; if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; if (time_after(jiffies, msta->last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index de8c3a02cf4b..bd449423e5b3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -342,7 +342,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_sta *msta = &mvif->sta; + struct mt792x_sta *msta = &mvif->sta; struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); int idx = msta->wcid.idx; @@ -508,7 +508,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : + struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; u8 *wcid_keyidx = &wcid->hw_key_idx; @@ -756,7 +756,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int ret, idx; @@ -797,7 +797,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt7921_mutex_acquire(dev); @@ -822,7 +822,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); mt76_connac_pm_wake(&dev->mphy, &dev->pm); @@ -877,9 +877,9 @@ static void mt7921_tx(struct ieee80211_hw *hw, int qid; if (control->sta) { - struct mt7921_sta *sta; + struct mt792x_sta *sta; - sta = (struct mt7921_sta *)control->sta->drv_priv; + sta = (struct mt792x_sta *)control->sta->drv_priv; wcid = &sta->wcid; } @@ -924,7 +924,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7921_dev *dev = mt7921_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; u16 tid = params->tid; u16 ssn = params->ssn; struct mt76_txq *mtxq; @@ -1120,7 +1120,7 @@ mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt7921_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt76_ethtool_worker_info *wi = wi_data; if (msta->vif->mt76.idx != wi->idx) @@ -1387,7 +1387,7 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct rate_info *txrate = &msta->wcid.rate; if (!txrate->legacy && !txrate->flags) @@ -1500,7 +1500,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool enabled) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 4d8b4c802739..1d1e8ee5bd3d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -343,7 +343,7 @@ int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; if (enable && !params->amsdu) msta->wcid.amsdu = false; @@ -357,7 +357,7 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, MCU_UNI_CMD(STA_REC_UPDATE), @@ -933,9 +933,9 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, .offload_fw = true, .rcpi = to_rcpi(rssi), }; - struct mt7921_sta *msta; + struct mt792x_sta *msta; - msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL; + msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL; info.wcid = msta ? &msta->wcid : &mvif->sta.wcid; info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 6ec5b19f3c25..4d409ba3fc21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -128,7 +128,7 @@ struct mt7921_sdio_intr { #define to_rcpi(rssi) (2 * (rssi) + 220) struct mt792x_vif; -struct mt7921_sta; +struct mt792x_sta; enum mt7921_txq_id { MT7921_TXQ_BAND0, @@ -145,7 +145,7 @@ enum mt7921_rxq_id { DECLARE_EWMA(avg_signal, 10, 8) -struct mt7921_sta { +struct mt792x_sta { struct mt76_wcid wcid; /* must be first */ struct mt792x_vif *vif; @@ -165,8 +165,8 @@ DECLARE_EWMA(rssi, 10, 8); struct mt792x_vif { struct mt76_vif mt76; /* must be first */ - struct mt7921_sta sta; - struct mt7921_sta *wep_sta; + struct mt792x_sta sta; + struct mt792x_sta *wep_sta; struct mt7921_phy *phy; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 978c90a034cf..32bba86727a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -32,7 +32,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; if (time_after(jiffies, msta->last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; -- cgit From 78562b2cafc61a0c08dc949eacb942ac756aae37 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:51 +0800 Subject: wifi: mt76: mt7921: rename mt7921_phy in mt792x_phy This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/acpi_sar.c | 8 +-- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 6 +-- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 14 +++--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 58 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 14 +++--- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 36 +++++++------- .../net/wireless/mediatek/mt76/mt7921/testmode.c | 4 +- 8 files changed, 72 insertions(+), 72 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c index 6feea2e515b3..06f2acdbfe1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c @@ -193,7 +193,7 @@ int mt7921_init_acpi_sar(struct mt7921_dev *dev) } static s8 -mt7921_asar_get_geo_pwr(struct mt7921_phy *phy, +mt7921_asar_get_geo_pwr(struct mt792x_phy *phy, enum nl80211_band band, s8 dyn_power) { struct mt7921_acpi_sar *asar = phy->acpisar; @@ -248,7 +248,7 @@ mt7921_asar_get_geo_pwr(struct mt7921_phy *phy, } static s8 -mt7921_asar_range_pwr(struct mt7921_phy *phy, +mt7921_asar_range_pwr(struct mt792x_phy *phy, const struct cfg80211_sar_freq_ranges *range, u8 idx) { @@ -280,7 +280,7 @@ mt7921_asar_range_pwr(struct mt7921_phy *phy, return mt7921_asar_get_geo_pwr(phy, band, limit[idx]); } -int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) +int mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) { const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; int i; @@ -306,7 +306,7 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) return 0; } -u8 mt7921_acpi_get_flags(struct mt7921_phy *phy) +u8 mt7921_acpi_get_flags(struct mt792x_phy *phy) { struct mt7921_acpi_sar *acpisar = phy->acpisar; struct mt7921_asar_fg *fg; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index d6c66e775536..baa640e8a982 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -58,7 +58,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get, mt7921_fw_debug_set, "%lld\n"); static void -mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy, +mt7921_ampdu_stat_read_phy(struct mt792x_phy *phy, struct seq_file *file) { struct mt7921_dev *dev = file->private; @@ -94,7 +94,7 @@ static int mt7921_tx_stats_show(struct seq_file *file, void *data) { struct mt7921_dev *dev = file->private; - struct mt7921_phy *phy = &dev->phy; + struct mt792x_phy *phy = &dev->phy; struct mt76_mib_stats *mib = &phy->mib; int i; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index df32f4f1b636..d383586eb429 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -60,7 +60,7 @@ static ssize_t mt7921_thermal_temp_show(struct device *dev, { switch (to_sensor_dev_attr(attr)->index) { case 0: { - struct mt7921_phy *phy = dev_get_drvdata(dev); + struct mt792x_phy *phy = dev_get_drvdata(dev); struct mt7921_dev *mdev = phy->dev; int temperature; @@ -85,7 +85,7 @@ static struct attribute *mt7921_hwmon_attrs[] = { }; ATTRIBUTE_GROUPS(mt7921_hwmon); -static int mt7921_thermal_init(struct mt7921_phy *phy) +static int mt7921_thermal_init(struct mt792x_phy *phy) { struct wiphy *wiphy = phy->mt76->hw->wiphy; struct device *hwmon; @@ -126,7 +126,7 @@ mt7921_regd_notifier(struct wiphy *wiphy, static int mt7921_init_wiphy(struct ieee80211_hw *hw) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; struct wiphy *wiphy = hw->wiphy; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index d4cf2ff18102..15c0e8be8f34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -240,7 +240,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) u16 hdr_gap; __le32 *rxv = NULL, *rxd = (__le32 *)skb->data; struct mt76_phy *mphy = &dev->mt76.phy; - struct mt7921_phy *phy = &dev->phy; + struct mt792x_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; u32 csum_status = *(u32 *)skb->cb; u32 rxd0 = le32_to_cpu(rxd[0]); @@ -699,7 +699,7 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } EXPORT_SYMBOL_GPL(mt7921_queue_rx_skb); -void mt7921_mac_reset_counters(struct mt7921_phy *phy) +void mt7921_mac_reset_counters(struct mt792x_phy *phy) { struct mt7921_dev *dev = phy->dev; int i; @@ -721,7 +721,7 @@ void mt7921_mac_reset_counters(struct mt7921_phy *phy) mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); } -void mt7921_mac_set_timing(struct mt7921_phy *phy) +void mt7921_mac_set_timing(struct mt792x_phy *phy) { s16 coverage_class = phy->coverage_class; struct mt7921_dev *dev = phy->dev; @@ -763,7 +763,7 @@ void mt7921_mac_set_timing(struct mt7921_phy *phy) } static u8 -mt7921_phy_get_nf(struct mt7921_phy *phy, int idx) +mt7921_phy_get_nf(struct mt792x_phy *phy, int idx) { return 0; } @@ -772,7 +772,7 @@ static void mt7921_phy_update_channel(struct mt76_phy *mphy, int idx) { struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); - struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv; + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; int nf; @@ -902,7 +902,7 @@ void mt7921_reset(struct mt76_dev *mdev) } EXPORT_SYMBOL_GPL(mt7921_reset); -void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) +void mt7921_mac_update_mib_stats(struct mt792x_phy *phy) { struct mt76_mib_stats *mib = &phy->mib; struct mt7921_dev *dev = phy->dev; @@ -964,7 +964,7 @@ void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) void mt7921_mac_work(struct work_struct *work) { - struct mt7921_phy *phy; + struct mt792x_phy *phy; struct mt76_phy *mphy; mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index bd449423e5b3..fc9a306344cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -10,7 +10,7 @@ #include "mcu.h" static int -mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, +mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) { int i, idx = 0; @@ -185,7 +185,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, return idx; } -void mt7921_set_stream_he_caps(struct mt7921_phy *phy) +void mt7921_set_stream_he_caps(struct mt792x_phy *phy) { struct ieee80211_sband_iftype_data *data; struct ieee80211_supported_band *band; @@ -219,7 +219,7 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy) } } -int __mt7921_start(struct mt7921_phy *phy) +int __mt7921_start(struct mt792x_phy *phy) { struct mt76_phy *mphy = phy->mt76; int err; @@ -252,7 +252,7 @@ EXPORT_SYMBOL_GPL(__mt7921_start); static int mt7921_start(struct ieee80211_hw *hw) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); int err; mt7921_mutex_acquire(phy->dev); @@ -265,7 +265,7 @@ static int mt7921_start(struct ieee80211_hw *hw) void mt7921_stop(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -286,7 +286,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt76_txq *mtxq; int idx, ret = 0; @@ -344,7 +344,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = &mvif->sta; struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); int idx = msta->wcid.idx; mt7921_mutex_acquire(dev); @@ -369,16 +369,16 @@ static void mt7921_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_phy *phy = priv; + struct mt792x_phy *phy = priv; mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id); } void mt7921_roc_work(struct work_struct *work) { - struct mt7921_phy *phy; + struct mt792x_phy *phy; - phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy, + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, roc_work); if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) @@ -394,12 +394,12 @@ void mt7921_roc_work(struct work_struct *work) void mt7921_roc_timer(struct timer_list *timer) { - struct mt7921_phy *phy = from_timer(phy, timer, roc_timer); + struct mt792x_phy *phy = from_timer(phy, timer, roc_timer); ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); } -static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif) +static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) { int err = 0; @@ -414,7 +414,7 @@ static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif) return err; } -static int mt7921_set_roc(struct mt7921_phy *phy, +static int mt7921_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, @@ -451,7 +451,7 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, enum ieee80211_roc_type type) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); int err; mt7921_mutex_acquire(phy->dev); @@ -465,12 +465,12 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); return mt7921_abort_roc(phy, mvif); } -static int mt7921_set_channel(struct mt7921_phy *phy) +static int mt7921_set_channel(struct mt792x_phy *phy) { struct mt7921_dev *dev = phy->dev; int ret; @@ -631,7 +631,7 @@ void mt7921_set_runtime_pm(struct mt7921_dev *dev) static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -710,7 +710,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u64 changed) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); @@ -994,7 +994,7 @@ static int mt7921_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt76_mib_stats *mib = &phy->mib; mt7921_mutex_acquire(phy->dev); @@ -1135,7 +1135,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { @@ -1252,7 +1252,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; mt7921_mutex_acquire(dev); @@ -1263,9 +1263,9 @@ mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) void mt7921_scan_work(struct work_struct *work) { - struct mt7921_phy *phy; + struct mt792x_phy *phy; - phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy, + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, scan_work.work); while (true) { @@ -1360,7 +1360,7 @@ static int mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); int max_nss = hweight8(hw->wiphy->available_antennas_tx); if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) @@ -1424,7 +1424,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -1448,7 +1448,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, static int mt7921_resume(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); mt7921_mutex_acquire(dev); @@ -1631,7 +1631,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); int err; @@ -1659,7 +1659,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); int err; @@ -1709,7 +1709,7 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt7921_hw_phy(hw); mt7921_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 1d1e8ee5bd3d..06fecc9dc220 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -160,7 +160,7 @@ static void mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; - struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv; + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; spin_lock_bh(&dev->mt76.lock); __skb_queue_tail(&phy->scan_event_list, skb); @@ -394,7 +394,7 @@ static int mt7921_load_clc(struct mt7921_dev *dev, const char *fw_name) const struct mt76_connac2_fw_region *region; const struct mt7921_clc *clc; struct mt76_dev *mdev = &dev->mt76; - struct mt7921_phy *phy = &dev->phy; + struct mt792x_phy *phy = &dev->phy; const struct firmware *fw; int ret, i, len, offset = 0; u8 *clc_base = NULL, hw_encap = 0; @@ -635,7 +635,7 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) &req_mu, sizeof(req_mu), false); } -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, +int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id) { @@ -702,7 +702,7 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, +int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id) { struct mt7921_dev *dev = phy->dev; @@ -732,7 +732,7 @@ int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) +int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd) { struct mt7921_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; @@ -1286,7 +1286,7 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, enum environment_cap env_cap) { - struct mt7921_phy *phy = (struct mt7921_phy *)&dev->phy; + struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy; int i, ret; /* submit all clc config */ @@ -1305,7 +1305,7 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, return 0; } -int mt7921_mcu_get_temperature(struct mt7921_phy *phy) +int mt7921_mcu_get_temperature(struct mt792x_phy *phy) { struct mt7921_dev *dev = phy->dev; struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 4d409ba3fc21..d9550b0aba61 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -168,7 +168,7 @@ struct mt792x_vif { struct mt792x_sta sta; struct mt792x_sta *wep_sta; - struct mt7921_phy *phy; + struct mt792x_phy *phy; struct ewma_rssi rssi; @@ -199,7 +199,7 @@ struct mt7921_clc { u8 data[]; } __packed; -struct mt7921_phy { +struct mt792x_phy { struct mt76_phy *mt76; struct mt7921_dev *dev; @@ -264,7 +264,7 @@ struct mt7921_dev { }; const struct mt76_bus_ops *bus_ops; - struct mt7921_phy phy; + struct mt792x_phy phy; struct work_struct reset_work; bool hw_full_reset:1; @@ -317,7 +317,7 @@ struct mt7921_txpwr { } data[TXPWR_MAX_NUM]; }; -static inline struct mt7921_phy * +static inline struct mt792x_phy * mt7921_hw_phy(struct ieee80211_hw *hw) { struct mt76_phy *phy = hw->priv; @@ -342,7 +342,7 @@ extern const struct ieee80211_ops mt7921_ops; u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); -int __mt7921_start(struct mt7921_phy *phy); +int __mt7921_start(struct mt792x_phy *phy); int mt7921_register_device(struct mt7921_dev *dev); void mt7921_unregister_device(struct mt7921_dev *dev); int mt7921_dma_init(struct mt7921_dev *dev); @@ -355,10 +355,10 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state); -int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd); +int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd); int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif); int mt7921_mcu_set_eeprom(struct mt7921_dev *dev); -int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif, +int mt7921_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl); void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb); @@ -423,8 +423,8 @@ mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt7921_dev *dev); bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); -void mt7921_mac_reset_counters(struct mt7921_phy *phy); -void mt7921_mac_set_timing(struct mt7921_phy *phy); +void mt7921_mac_reset_counters(struct mt792x_phy *phy); +void mt7921_mac_set_timing(struct mt792x_phy *phy); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, @@ -433,7 +433,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_work(struct work_struct *work); void mt7921_mac_reset_work(struct work_struct *work); -void mt7921_mac_update_mib_stats(struct mt7921_phy *phy); +void mt7921_mac_update_mib_stats(struct mt792x_phy *phy); void mt7921_reset(struct mt76_dev *mdev); int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -445,7 +445,7 @@ bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); void mt7921_stats_work(struct work_struct *work); -void mt7921_set_stream_he_caps(struct mt7921_phy *phy); +void mt7921_set_stream_he_caps(struct mt792x_phy *phy); void mt7921_update_channel(struct mt76_phy *mphy); int mt7921_init_debugfs(struct mt7921_dev *dev); @@ -499,7 +499,7 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx); -int mt7921_mcu_get_temperature(struct mt7921_phy *phy); +int mt7921_mcu_get_temperature(struct mt792x_phy *phy); int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -524,8 +524,8 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, bool enable); #ifdef CONFIG_ACPI int mt7921_init_acpi_sar(struct mt7921_dev *dev); -int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default); -u8 mt7921_acpi_get_flags(struct mt7921_phy *phy); +int mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); +u8 mt7921_acpi_get_flags(struct mt792x_phy *phy); #else static inline int mt7921_init_acpi_sar(struct mt7921_dev *dev) @@ -534,13 +534,13 @@ mt7921_init_acpi_sar(struct mt7921_dev *dev) } static inline int -mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) +mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) { return 0; } static inline u8 -mt7921_acpi_get_flags(struct mt7921_phy *phy) +mt7921_acpi_get_flags(struct mt792x_phy *phy) { return 0; } @@ -550,10 +550,10 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, enum environment_cap env_cap); -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, +int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id); -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt792x_vif *vif, +int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id); struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c index 7f408212e716..208dcb2afbe7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c @@ -113,7 +113,7 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct nlattr *tb[NUM_MT76_TM_ATTRS]; struct mt76_phy *mphy = hw->priv; - struct mt7921_phy *phy = mphy->priv; + struct mt792x_phy *phy = mphy->priv; int err; if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || @@ -150,7 +150,7 @@ int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, { struct nlattr *tb[NUM_MT76_TM_ATTRS]; struct mt76_phy *mphy = hw->priv; - struct mt7921_phy *phy = mphy->priv; + struct mt792x_phy *phy = mphy->priv; int err; if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || -- cgit From 975e122ddb7cd6f67bff974d2ea00c5568d2014c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:52 +0800 Subject: wifi: mt76: mt7921: rename mt7921_dev in mt792x_dev This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/acpi_sar.c | 12 +- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 38 +++--- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 26 ++-- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 20 ++-- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 58 ++++----- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 88 +++++++------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 74 ++++++------ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 132 ++++++++++----------- .../wireless/mediatek/mt76/mt7921/mt7921_trace.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 26 ++-- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 4 +- .../net/wireless/mediatek/mt76/mt7921/pci_mcu.c | 12 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 14 +-- .../net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 6 +- .../net/wireless/mediatek/mt76/mt7921/sdio_mcu.c | 12 +- .../net/wireless/mediatek/mt76/mt7921/testmode.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 20 ++-- .../net/wireless/mediatek/mt76/mt7921/usb_mac.c | 16 +-- 18 files changed, 282 insertions(+), 282 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c index 06f2acdbfe1c..057767ab45ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c @@ -5,7 +5,7 @@ #include "mt7921.h" static int -mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len) +mt7921_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *sar_root, *sar_unit; @@ -65,7 +65,7 @@ free: /* MTCL : Country List Table for 6G band */ static int -mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version) +mt7921_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) { *version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0) ? 1 : 2; @@ -74,7 +74,7 @@ mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version) /* MTDS : Dynamic SAR Power Table */ static int -mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version) +mt7921_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version) { int len, ret, sarlen, prelen, tblcnt; bool enable; @@ -109,7 +109,7 @@ mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version) /* MTGS : Geo SAR Power Table */ static int -mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version) +mt7921_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version) { int len, ret = 0, sarlen, prelen, tblcnt; @@ -140,7 +140,7 @@ mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version) /* MTFG : Flag Table */ static int -mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table) +mt7921_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table) { int len, ret; @@ -154,7 +154,7 @@ mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table) return ret; } -int mt7921_init_acpi_sar(struct mt7921_dev *dev) +int mt7921_init_acpi_sar(struct mt792x_dev *dev) { struct mt7921_acpi_sar *asar; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index baa640e8a982..6137a10c022a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -6,7 +6,7 @@ static int mt7921_reg_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; mt7921_mutex_acquire(dev); mt76_wr(dev, dev->mt76.debugfs_reg, val); @@ -18,7 +18,7 @@ mt7921_reg_set(void *data, u64 val) static int mt7921_reg_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; mt7921_mutex_acquire(dev); *val = mt76_rr(dev, dev->mt76.debugfs_reg); @@ -32,7 +32,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, static int mt7921_fw_debug_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; mt7921_mutex_acquire(dev); @@ -47,7 +47,7 @@ mt7921_fw_debug_set(void *data, u64 val) static int mt7921_fw_debug_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->fw_debug; @@ -61,7 +61,7 @@ static void mt7921_ampdu_stat_read_phy(struct mt792x_phy *phy, struct seq_file *file) { - struct mt7921_dev *dev = file->private; + struct mt792x_dev *dev = file->private; int bound[15], range[4], i; if (!phy) @@ -93,7 +93,7 @@ mt7921_ampdu_stat_read_phy(struct mt792x_phy *phy, static int mt7921_tx_stats_show(struct seq_file *file, void *data) { - struct mt7921_dev *dev = file->private; + struct mt792x_dev *dev = file->private; struct mt792x_phy *phy = &dev->phy; struct mt76_mib_stats *mib = &phy->mib; int i; @@ -123,7 +123,7 @@ DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats); static int mt7921_queues_acq(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); int i; mt7921_mutex_acquire(dev); @@ -154,7 +154,7 @@ mt7921_queues_acq(struct seq_file *s, void *data) static int mt7921_queues_read(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct { struct mt76_queue *q; char *queue; @@ -211,7 +211,7 @@ mt7921_seq_puts_array(struct seq_file *file, const char *str, static int mt7921_txpwr(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct mt7921_txpwr txpwr; int ret; @@ -263,7 +263,7 @@ mt7921_txpwr(struct seq_file *s, void *data) static int mt7921_pm_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; if (mt76_is_usb(&dev->mt76)) @@ -296,7 +296,7 @@ out: static int mt7921_pm_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->pm.enable_user; @@ -308,7 +308,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n"); static int mt7921_deep_sleep_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); bool enable = !!val; @@ -332,7 +332,7 @@ out: static int mt7921_deep_sleep_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->pm.ds_enable_user; @@ -345,7 +345,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get, static int mt7921_pm_stats(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct mt76_connac_pm *pm = &dev->pm; unsigned long awake_time = pm->stats.awake_time; @@ -368,7 +368,7 @@ mt7921_pm_stats(struct seq_file *s, void *data) static int mt7921_pm_idle_timeout_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; dev->pm.idle_timeout = msecs_to_jiffies(val); @@ -378,7 +378,7 @@ mt7921_pm_idle_timeout_set(void *data, u64 val) static int mt7921_pm_idle_timeout_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = jiffies_to_msecs(dev->pm.idle_timeout); @@ -390,7 +390,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get, static int mt7921_chip_reset(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; int ret = 0; switch (val) { @@ -414,7 +414,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n"); static int mt7921s_sched_quota_read(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct mt76_sdio *sdio = &dev->mt76.sdio; seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota); @@ -425,7 +425,7 @@ mt7921s_sched_quota_read(struct seq_file *s, void *data) return 0; } -int mt7921_init_debugfs(struct mt7921_dev *dev) +int mt7921_init_debugfs(struct mt792x_dev *dev) { struct dentry *dir; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 4153cd6c2a01..3c628962641b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -7,9 +7,9 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; - dev = container_of(napi, struct mt7921_dev, mt76.tx_napi); + dev = container_of(napi, struct mt792x_dev, mt76.tx_napi); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { napi_complete(napi); @@ -27,10 +27,10 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) static int mt7921_poll_rx(struct napi_struct *napi, int budget) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; int done; - dev = container_of(napi->dev, struct mt7921_dev, mt76.napi_dev); + dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { napi_complete(napi); @@ -43,7 +43,7 @@ static int mt7921_poll_rx(struct napi_struct *napi, int budget) return done; } -static void mt7921_dma_prefetch(struct mt7921_dev *dev) +static void mt7921_dma_prefetch(struct mt792x_dev *dev) { #define PREFETCH(base, depth) ((base) << 16 | (depth)) @@ -64,7 +64,7 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev) mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); } -static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) +static int mt7921_dma_disable(struct mt792x_dev *dev, bool force) { /* disable WFDMA0 */ mt76_clear(dev, MT_WFDMA0_GLO_CFG, @@ -98,7 +98,7 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) return 0; } -static int mt7921_dma_enable(struct mt7921_dev *dev) +static int mt7921_dma_enable(struct mt792x_dev *dev) { /* configure perfetch settings */ mt7921_dma_prefetch(dev); @@ -131,7 +131,7 @@ static int mt7921_dma_enable(struct mt7921_dev *dev) return 0; } -static int mt7921_dma_reset(struct mt7921_dev *dev, bool force) +static int mt7921_dma_reset(struct mt792x_dev *dev, bool force) { int i, err; @@ -154,7 +154,7 @@ static int mt7921_dma_reset(struct mt7921_dev *dev, bool force) return mt7921_dma_enable(dev); } -int mt7921_wfsys_reset(struct mt7921_dev *dev) +int mt7921_wfsys_reset(struct mt792x_dev *dev) { mt76_clear(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B); msleep(50); @@ -167,7 +167,7 @@ int mt7921_wfsys_reset(struct mt7921_dev *dev) return 0; } -int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force) +int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force) { int i, err; @@ -196,7 +196,7 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force) return 0; } -int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev) +int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; int err; @@ -221,7 +221,7 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev) return 0; } -int mt7921_dma_init(struct mt7921_dev *dev) +int mt7921_dma_init(struct mt792x_dev *dev) { int ret; @@ -286,7 +286,7 @@ int mt7921_dma_init(struct mt7921_dev *dev) return mt7921_dma_enable(dev); } -void mt7921_dma_cleanup(struct mt7921_dev *dev) +void mt7921_dma_cleanup(struct mt792x_dev *dev) { /* disable */ mt76_clear(dev, MT_WFDMA0_GLO_CFG, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index d383586eb429..bace86813b76 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -61,7 +61,7 @@ static ssize_t mt7921_thermal_temp_show(struct device *dev, switch (to_sensor_dev_attr(attr)->index) { case 0: { struct mt792x_phy *phy = dev_get_drvdata(dev); - struct mt7921_dev *mdev = phy->dev; + struct mt792x_dev *mdev = phy->dev; int temperature; mt7921_mutex_acquire(mdev); @@ -110,7 +110,7 @@ mt7921_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; @@ -127,7 +127,7 @@ static int mt7921_init_wiphy(struct ieee80211_hw *hw) { struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct wiphy *wiphy = hw->wiphy; hw->queues = 4; @@ -200,7 +200,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) } static void -mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) +mt7921_mac_init_band(struct mt792x_dev *dev, u8 band) { u32 mask, set; @@ -309,7 +309,7 @@ mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features) } EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops); -int mt7921_mac_init(struct mt7921_dev *dev) +int mt7921_mac_init(struct mt792x_dev *dev) { int i; @@ -329,7 +329,7 @@ int mt7921_mac_init(struct mt7921_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_mac_init); -static int __mt7921_init_hardware(struct mt7921_dev *dev) +static int __mt7921_init_hardware(struct mt792x_dev *dev) { int ret; @@ -352,7 +352,7 @@ out: return ret; } -static int mt7921_init_hardware(struct mt7921_dev *dev) +static int mt7921_init_hardware(struct mt792x_dev *dev) { int ret, i; @@ -374,7 +374,7 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return 0; } -static int mt7921_init_wcid(struct mt7921_dev *dev) +static int mt7921_init_wcid(struct mt792x_dev *dev) { int idx; @@ -393,7 +393,7 @@ static int mt7921_init_wcid(struct mt7921_dev *dev) static void mt7921_init_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, init_work); int ret; @@ -429,7 +429,7 @@ static void mt7921_init_work(struct work_struct *work) mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); } -int mt7921_register_device(struct mt7921_dev *dev) +int mt7921_register_device(struct mt792x_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 15c0e8be8f34..a17d70aa90da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -20,7 +20,7 @@ static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; } -static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, +static struct mt76_wcid *mt7921_rx_get_wcid(struct mt792x_dev *dev, u16 idx, bool unicast) { struct mt792x_sta *sta; @@ -43,7 +43,7 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, return &sta->vif->sta.wcid; } -bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); @@ -52,7 +52,7 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) 0, 5000); } -static void mt7921_mac_sta_poll(struct mt7921_dev *dev) +static void mt7921_mac_sta_poll(struct mt792x_dev *dev) { static const u8 ac_to_tid[] = { [IEEE80211_AC_BE] = 0, @@ -185,7 +185,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev) } static void -mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy, +mt7921_get_status_freq_info(struct mt792x_dev *dev, struct mt76_phy *mphy, struct mt76_rx_status *status, u8 chfreq) { if (chfreq > 180) { @@ -217,7 +217,7 @@ mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) } static void -mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb) { struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); @@ -231,7 +231,7 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb) } static int -mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) { u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -511,7 +511,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) return 0; } -void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) +void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) { struct mt792x_sta *msta = NULL; struct mt76_wcid *wcid; @@ -552,7 +552,7 @@ out: rcu_read_unlock(); } -static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) +static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) { struct mt76_connac_tx_free *free = data; __le32 *tx_info = (__le32 *)(data + sizeof(*free)); @@ -634,7 +634,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); __le32 *rxd = (__le32 *)data; __le32 *end = (__le32 *)&rxd[len / 4]; enum rx_pkt_type type; @@ -659,7 +659,7 @@ EXPORT_SYMBOL_GPL(mt7921_rx_check); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); __le32 *rxd = (__le32 *)skb->data; __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; @@ -701,7 +701,7 @@ EXPORT_SYMBOL_GPL(mt7921_queue_rx_skb); void mt7921_mac_reset_counters(struct mt792x_phy *phy) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; int i; for (i = 0; i < 4; i++) { @@ -724,7 +724,7 @@ void mt7921_mac_reset_counters(struct mt792x_phy *phy) void mt7921_mac_set_timing(struct mt792x_phy *phy) { s16 coverage_class = phy->coverage_class; - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; u32 val, reg_offset; u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); @@ -771,7 +771,7 @@ mt7921_phy_get_nf(struct mt792x_phy *phy, int idx) static void mt7921_phy_update_channel(struct mt76_phy *mphy, int idx) { - struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; @@ -802,7 +802,7 @@ mt7921_phy_update_channel(struct mt76_phy *mphy, int idx) void mt7921_update_channel(struct mt76_phy *mphy) { - struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); if (mt76_connac_pm_wake(mphy, &dev->pm)) return; @@ -820,7 +820,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mvif->phy->dev; + struct mt792x_dev *dev = mvif->phy->dev; struct ieee80211_hw *hw = mt76_hw(dev); if (vif->type == NL80211_IFTYPE_STATION) @@ -841,7 +841,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, /* system error recovery */ void mt7921_mac_reset_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, reset_work); struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; @@ -886,7 +886,7 @@ void mt7921_mac_reset_work(struct work_struct *work) void mt7921_reset(struct mt76_dev *mdev) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; if (!dev->hw_init_done) @@ -905,7 +905,7 @@ EXPORT_SYMBOL_GPL(mt7921_reset); void mt7921_mac_update_mib_stats(struct mt792x_phy *phy) { struct mt76_mib_stats *mib = &phy->mib; - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; int i, aggr0 = 0, aggr1; u32 val; @@ -989,10 +989,10 @@ void mt7921_mac_work(struct work_struct *work) void mt7921_pm_wake_work(struct work_struct *work) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_phy *mphy; - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, pm.wake_work); mphy = dev->phy.mt76; @@ -1022,11 +1022,11 @@ void mt7921_pm_wake_work(struct work_struct *work) void mt7921_pm_power_save_work(struct work_struct *work) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; unsigned long delta; struct mt76_phy *mphy; - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, pm.ps_work.work); mphy = dev->phy.mt76; @@ -1059,10 +1059,10 @@ out: void mt7921_coredump_work(struct work_struct *work) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; char *dump, *data; - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, coredump.work.work); if (time_is_after_jiffies(dev->coredump.last_activity + @@ -1106,7 +1106,7 @@ void mt7921_coredump_work(struct work_struct *work) /* usb_sdio */ static void -mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, +mt7921_usb_sdio_write_txwi(struct mt792x_dev *dev, struct mt76_wcid *wcid, enum mt76_txq_id qid, struct ieee80211_sta *sta, struct ieee80211_key_conf *key, int pid, struct sk_buff *skb) @@ -1123,7 +1123,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct sk_buff *skb = tx_info->skb; @@ -1189,7 +1189,7 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb); bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); mt7921_mutex_acquire(dev); mt7921_mac_sta_poll(dev); @@ -1202,8 +1202,8 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data); #if IS_ENABLED(CONFIG_IPV6) void mt7921_set_ipv6_ns_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, - ipv6_ns_work); + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + ipv6_ns_work); struct sk_buff *skb; int ret = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index fc9a306344cd..2f597fb3ae5c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -264,7 +264,7 @@ static int mt7921_start(struct ieee80211_hw *hw) void mt7921_stop(struct ieee80211_hw *hw) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -285,7 +285,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt76_txq *mtxq; int idx, ret = 0; @@ -343,7 +343,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = &mvif->sta; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int idx = msta->wcid.idx; @@ -472,7 +472,7 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, static int mt7921_set_channel(struct mt792x_phy *phy) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; int ret; cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -506,7 +506,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; @@ -578,7 +578,7 @@ out: static void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = priv; + struct mt792x_dev *dev = priv; struct ieee80211_hw *hw = mt76_hw(dev); bool pm_enable = dev->pm.enable; int err; @@ -599,7 +599,7 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) static void mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = priv; + struct mt792x_dev *dev = priv; struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); @@ -614,7 +614,7 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt7921_mcu_set_beacon_filter(dev, vif, false); } -void mt7921_set_runtime_pm(struct mt7921_dev *dev) +void mt7921_set_runtime_pm(struct mt792x_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; @@ -630,7 +630,7 @@ void mt7921_set_runtime_pm(struct mt7921_dev *dev) static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int ret = 0; @@ -686,7 +686,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, #define MT7921_FILTER_OTHER_BSS BIT(6) #define MT7921_FILTER_ENABLE BIT(31) - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); u32 flags = MT7921_FILTER_ENABLE; #define MT7921_FILTER(_fif, _type) do { \ @@ -711,7 +711,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, u64 changed) { struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); @@ -755,7 +755,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int ret, idx; @@ -796,7 +796,7 @@ EXPORT_SYMBOL_GPL(mt7921_mac_sta_add); void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; @@ -821,7 +821,7 @@ EXPORT_SYMBOL_GPL(mt7921_mac_sta_assoc); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); @@ -853,7 +853,7 @@ EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove); void mt7921_tx_worker(struct mt76_worker *w) { - struct mt7921_dev *dev = container_of(w, struct mt7921_dev, + struct mt792x_dev *dev = container_of(w, struct mt792x_dev, mt76.tx_worker); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { @@ -869,7 +869,7 @@ static void mt7921_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; @@ -907,7 +907,7 @@ static void mt7921_tx(struct ieee80211_hw *hw, static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, 0); @@ -921,7 +921,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; @@ -979,7 +979,7 @@ static int mt7921_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); if (dev->pm.ds_enable) { mt7921_mutex_acquire(dev); @@ -1087,7 +1087,7 @@ static void mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 sset, u8 *data) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); if (sset != ETH_SS_STATS) return; @@ -1105,7 +1105,7 @@ static int mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); if (sset != ETH_SS_STATS) return 0; @@ -1136,7 +1136,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, @@ -1204,7 +1204,7 @@ static u64 mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { u64 t64; @@ -1230,7 +1230,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { u64 t64; @@ -1253,7 +1253,7 @@ static void mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; mt7921_mutex_acquire(dev); phy->coverage_class = max_t(s16, coverage_class, 0); @@ -1298,7 +1298,7 @@ static int mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1312,7 +1312,7 @@ mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt7921_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; mt7921_mutex_acquire(dev); @@ -1325,7 +1325,7 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *req, struct ieee80211_scan_ies *ies) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1345,7 +1345,7 @@ out: static int mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1359,7 +1359,7 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int max_nss = hweight8(hw->wiphy->available_antennas_tx); @@ -1423,7 +1423,7 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw, static int mt7921_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->scan_work); @@ -1447,7 +1447,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, static int mt7921_resume(struct ieee80211_hw *hw) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); mt7921_mutex_acquire(dev); @@ -1468,7 +1468,7 @@ static int mt7921_resume(struct ieee80211_hw *hw) static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_dev *mdev = &dev->mt76; device_set_wakeup_enable(mdev->dev, enabled); @@ -1478,7 +1478,7 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); mt76_connac_mcu_update_gtk_rekey(hw, vif, data); @@ -1489,7 +1489,7 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy), HZ / 2); @@ -1501,7 +1501,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, bool enabled) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); @@ -1522,7 +1522,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct inet6_dev *idev) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mvif->phy->dev; + struct mt792x_dev *dev = mvif->phy->dev; struct inet6_ifaddr *ifa; struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; struct sk_buff *skb; @@ -1598,7 +1598,7 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, static int mt7921_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; mt7921_mutex_acquire(dev); @@ -1619,7 +1619,7 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt7921_mutex_acquire(dev); mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); @@ -1632,7 +1632,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; mt7921_mutex_acquire(dev); @@ -1660,7 +1660,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; mt7921_mutex_acquire(dev); @@ -1725,7 +1725,7 @@ mt7921_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mutex_lock(&dev->mt76.mutex); mvif->ctx = ctx; @@ -1741,7 +1741,7 @@ mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mutex_lock(&dev->mt76.mutex); mvif->ctx = NULL; @@ -1753,7 +1753,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_prep_tx_info *info) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); u16 duration = info->duration ? info->duration : jiffies_to_msecs(HZ); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 06fecc9dc220..db3394ba4e45 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -69,7 +69,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, } EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response); -static int mt7921_mcu_read_eeprom(struct mt7921_dev *dev, u32 offset, u8 *val) +static int mt7921_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) { struct mt7921_mcu_eeprom_info *res, req = { .addr = cpu_to_le32(round_down(offset, @@ -134,7 +134,7 @@ void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) #endif /* CONFIG_PM */ static void -mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_roc_grant_tlv *grant; struct mt76_connac2_mcu_rxd *rxd; @@ -157,7 +157,7 @@ mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; @@ -188,7 +188,7 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac, } static void -mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac_beacon_loss_event *event; struct mt76_phy *mphy = &dev->mt76.phy; @@ -202,7 +202,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_debug_msg { __le16 id; @@ -229,7 +229,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_low_power_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_mcu_lp_event { u8 state; @@ -243,7 +243,7 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_mcu_tx_done_event *event; @@ -254,7 +254,7 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -288,7 +288,7 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev, +mt7921_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -305,7 +305,7 @@ mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev, dev_kfree_skb(skb); } -void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) +void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -339,7 +339,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) } /** starec & wtbl **/ -int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { @@ -353,7 +353,7 @@ int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, enable, true); } -int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { @@ -364,7 +364,7 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, enable, false); } -static char *mt7921_patch_name(struct mt7921_dev *dev) +static char *mt7921_patch_name(struct mt792x_dev *dev) { char *ret; @@ -376,7 +376,7 @@ static char *mt7921_patch_name(struct mt7921_dev *dev) return ret; } -static char *mt7921_ram_name(struct mt7921_dev *dev) +static char *mt7921_ram_name(struct mt792x_dev *dev) { char *ret; @@ -388,7 +388,7 @@ static char *mt7921_ram_name(struct mt7921_dev *dev) return ret; } -static int mt7921_load_clc(struct mt7921_dev *dev, const char *fw_name) +static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name) { const struct mt76_connac2_fw_trailer *hdr; const struct mt76_connac2_fw_region *region; @@ -472,7 +472,7 @@ out: return ret; } -static int mt7921_load_firmware(struct mt7921_dev *dev) +static int mt7921_load_firmware(struct mt792x_dev *dev) { int ret; @@ -507,7 +507,7 @@ static int mt7921_load_firmware(struct mt7921_dev *dev) return 0; } -int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) +int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) { struct { u8 ctrl_val; @@ -520,7 +520,7 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) &data, sizeof(data), false); } -int mt7921_run_firmware(struct mt7921_dev *dev) +int mt7921_run_firmware(struct mt792x_dev *dev) { int err; @@ -541,7 +541,7 @@ int mt7921_run_firmware(struct mt7921_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_run_firmware); -int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) +int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct edca { @@ -640,7 +640,7 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, enum mt7921_roc_req type, u8 token_id) { int center_ch = ieee80211_frequency_to_channel(chan->center_freq); - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct { struct { u8 rsv[4]; @@ -705,7 +705,7 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct { struct { u8 rsv[4]; @@ -734,7 +734,7 @@ int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1; struct { @@ -791,7 +791,7 @@ int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd) return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } -int mt7921_mcu_set_eeprom(struct mt7921_dev *dev) +int mt7921_mcu_set_eeprom(struct mt792x_dev *dev) { struct req_hdr { u8 buffer_mode; @@ -807,7 +807,7 @@ int mt7921_mcu_set_eeprom(struct mt7921_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom); -int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) +int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { @@ -845,7 +845,7 @@ int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) } static int -mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, +mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; @@ -881,7 +881,7 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, } int -mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, +mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; @@ -918,7 +918,7 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, +int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state) { @@ -942,7 +942,7 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, return mt76_connac_mcu_sta_cmd(&dev->mphy, &info); } -int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) +int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; @@ -964,7 +964,7 @@ out: } EXPORT_SYMBOL_GPL(mt7921_mcu_drv_pmctrl); -int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev) +int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; @@ -986,7 +986,7 @@ out: } EXPORT_SYMBOL_GPL(mt7921_mcu_fw_pmctrl); -int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, +int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { @@ -1021,7 +1021,7 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, return 0; } -int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) +int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr) { struct mt7921_txpwr_event *event; struct mt7921_txpwr_req req = { @@ -1044,7 +1044,7 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) return 0; } -int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, +int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; @@ -1143,7 +1143,7 @@ int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, } int -mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, +mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable) @@ -1221,7 +1221,7 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, } static -int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap, struct mt7921_clc *clc, u8 idx) @@ -1283,7 +1283,7 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, return 0; } -int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap) { struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy; @@ -1307,7 +1307,7 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, int mt7921_mcu_get_temperature(struct mt792x_phy *phy) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct { u8 ctrl_id; u8 action; @@ -1322,7 +1322,7 @@ int mt7921_mcu_get_temperature(struct mt792x_phy *phy) sizeof(req), true); } -int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, +int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index d9550b0aba61..617aecd42544 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -201,7 +201,7 @@ struct mt7921_clc { struct mt792x_phy { struct mt76_phy *mt76; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; @@ -250,14 +250,14 @@ enum mt7921_eeprom_field { #define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) #define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) struct mt7921_hif_ops { - int (*init_reset)(struct mt7921_dev *dev); - int (*reset)(struct mt7921_dev *dev); - int (*mcu_init)(struct mt7921_dev *dev); - int (*drv_own)(struct mt7921_dev *dev); - int (*fw_own)(struct mt7921_dev *dev); + int (*init_reset)(struct mt792x_dev *dev); + int (*reset)(struct mt792x_dev *dev); + int (*mcu_init)(struct mt792x_dev *dev); + int (*drv_own)(struct mt792x_dev *dev); + int (*fw_own)(struct mt792x_dev *dev); }; -struct mt7921_dev { +struct mt792x_dev { union { /* must be first */ struct mt76_dev mt76; struct mt76_phy mphy; @@ -325,12 +325,12 @@ mt7921_hw_phy(struct ieee80211_hw *hw) return phy->priv; } -static inline struct mt7921_dev * +static inline struct mt792x_dev * mt7921_hw_dev(struct ieee80211_hw *hw) { struct mt76_phy *phy = hw->priv; - return container_of(phy->dev, struct mt7921_dev, mt76); + return container_of(phy->dev, struct mt792x_dev, mt76); } #define mt7921_mutex_acquire(dev) \ @@ -340,33 +340,33 @@ mt7921_hw_dev(struct ieee80211_hw *hw) extern const struct ieee80211_ops mt7921_ops; -u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); +u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); int __mt7921_start(struct mt792x_phy *phy); -int mt7921_register_device(struct mt7921_dev *dev); -void mt7921_unregister_device(struct mt7921_dev *dev); -int mt7921_dma_init(struct mt7921_dev *dev); -int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force); -int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev); -void mt7921_dma_cleanup(struct mt7921_dev *dev); -int mt7921_run_firmware(struct mt7921_dev *dev); -int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, +int mt7921_register_device(struct mt792x_dev *dev); +void mt7921_unregister_device(struct mt792x_dev *dev); +int mt7921_dma_init(struct mt792x_dev *dev); +int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force); +int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev); +void mt7921_dma_cleanup(struct mt792x_dev *dev); +int mt7921_run_firmware(struct mt792x_dev *dev); +int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, +int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state); int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd); -int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif); -int mt7921_mcu_set_eeprom(struct mt7921_dev *dev); +int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif); +int mt7921_mcu_set_eeprom(struct mt792x_dev *dev); int mt7921_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); -int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl); -void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb); -int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, +int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl); +void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb); +int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map); static inline u32 -mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr) +mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr) { u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); @@ -379,19 +379,19 @@ mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr) } static inline u32 -mt7921_l1_rr(struct mt7921_dev *dev, u32 addr) +mt7921_l1_rr(struct mt792x_dev *dev, u32 addr) { return mt76_rr(dev, mt7921_reg_map_l1(dev, addr)); } static inline void -mt7921_l1_wr(struct mt7921_dev *dev, u32 addr, u32 val) +mt7921_l1_wr(struct mt792x_dev *dev, u32 addr, u32 val) { mt76_wr(dev, mt7921_reg_map_l1(dev, addr), val); } static inline u32 -mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) +mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val) { val |= mt7921_l1_rr(dev, addr) & ~mask; mt7921_l1_wr(dev, addr, val); @@ -402,13 +402,13 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) -static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev) +static inline bool mt7921_dma_need_reinit(struct mt792x_dev *dev) { return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); } static inline void -mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, +mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, int type) { u32 hdr, len; @@ -421,8 +421,8 @@ mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, } void mt7921_stop(struct ieee80211_hw *hw); -int mt7921_mac_init(struct mt7921_dev *dev); -bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); +int mt7921_mac_init(struct mt792x_dev *dev); +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); void mt7921_mac_reset_counters(struct mt792x_phy *phy); void mt7921_mac_set_timing(struct mt792x_phy *phy); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, @@ -447,28 +447,28 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, void mt7921_stats_work(struct work_struct *work); void mt7921_set_stream_he_caps(struct mt792x_phy *phy); void mt7921_update_channel(struct mt76_phy *mphy); -int mt7921_init_debugfs(struct mt7921_dev *dev); +int mt7921_init_debugfs(struct mt792x_dev *dev); -int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, +int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable); -int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable); void mt7921_scan_work(struct work_struct *work); void mt7921_roc_work(struct work_struct *work); void mt7921_roc_timer(struct timer_list *timer); -int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif); -int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev); +int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); +int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev); void mt7921_pm_wake_work(struct work_struct *work); void mt7921_pm_power_save_work(struct work_struct *work); void mt7921_coredump_work(struct work_struct *work); -int mt7921_wfsys_reset(struct mt7921_dev *dev); -int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr); +int mt7921_wfsys_reset(struct mt792x_dev *dev); +int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr); int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, @@ -476,26 +476,26 @@ int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); -int mt7921e_driver_own(struct mt7921_dev *dev); -int mt7921e_mac_reset(struct mt7921_dev *dev); -int mt7921e_mcu_init(struct mt7921_dev *dev); -int mt7921s_wfsys_reset(struct mt7921_dev *dev); -int mt7921s_mac_reset(struct mt7921_dev *dev); -int mt7921s_init_reset(struct mt7921_dev *dev); -int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); - -int mt7921s_mcu_init(struct mt7921_dev *dev); -int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); -void mt7921_set_runtime_pm(struct mt7921_dev *dev); +int mt7921e_driver_own(struct mt792x_dev *dev); +int mt7921e_mac_reset(struct mt792x_dev *dev); +int mt7921e_mcu_init(struct mt792x_dev *dev); +int mt7921s_wfsys_reset(struct mt792x_dev *dev); +int mt7921s_mac_reset(struct mt792x_dev *dev); +int mt7921s_init_reset(struct mt792x_dev *dev); +int __mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt7921e_mcu_fw_pmctrl(struct mt792x_dev *dev); + +int mt7921s_mcu_init(struct mt792x_dev *dev); +int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev); +void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data); +void mt7921_set_runtime_pm(struct mt792x_dev *dev); void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); void mt7921_set_ipv6_ns_work(struct work_struct *work); -int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, +int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx); @@ -513,22 +513,22 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); #define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) #define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) -int mt7921u_mcu_power_on(struct mt7921_dev *dev); -int mt7921u_wfsys_reset(struct mt7921_dev *dev); -int mt7921u_dma_init(struct mt7921_dev *dev, bool resume); -int mt7921u_init_reset(struct mt7921_dev *dev); -int mt7921u_mac_reset(struct mt7921_dev *dev); -int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, +int mt7921u_mcu_power_on(struct mt792x_dev *dev); +int mt7921u_wfsys_reset(struct mt792x_dev *dev); +int mt7921u_dma_init(struct mt792x_dev *dev, bool resume); +int mt7921u_init_reset(struct mt792x_dev *dev); +int mt7921u_mac_reset(struct mt792x_dev *dev); +int mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable); #ifdef CONFIG_ACPI -int mt7921_init_acpi_sar(struct mt7921_dev *dev); +int mt7921_init_acpi_sar(struct mt792x_dev *dev); int mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); u8 mt7921_acpi_get_flags(struct mt792x_phy *phy); #else static inline int -mt7921_init_acpi_sar(struct mt7921_dev *dev) +mt7921_init_acpi_sar(struct mt792x_dev *dev) { return 0; } @@ -548,7 +548,7 @@ mt7921_acpi_get_flags(struct mt792x_phy *phy) int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); -int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap); int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h index 9bc4db67f352..9426fda69c30 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h @@ -21,7 +21,7 @@ #define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready" TRACE_EVENT(lp_event, - TP_PROTO(struct mt7921_dev *dev, u8 lp_state), + TP_PROTO(struct mt792x_dev *dev, u8 lp_state), TP_ARGS(dev, lp_state), diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 1b7f19939a69..517e4d541bdc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -41,7 +41,7 @@ mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) { - struct mt7921_dev *dev = dev_instance; + struct mt792x_dev *dev = dev_instance; mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); @@ -55,7 +55,7 @@ static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) static void mt7921_irq_tasklet(unsigned long data) { - struct mt7921_dev *dev = (struct mt7921_dev *)data; + struct mt792x_dev *dev = (struct mt792x_dev *)data; u32 intr, mask = 0; mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); @@ -97,12 +97,12 @@ static void mt7921_irq_tasklet(unsigned long data) napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); } -static int mt7921e_init_reset(struct mt7921_dev *dev) +static int mt7921e_init_reset(struct mt792x_dev *dev) { return mt7921_wpdma_reset(dev, true); } -static void mt7921e_unregister_device(struct mt7921_dev *dev) +static void mt7921e_unregister_device(struct mt792x_dev *dev) { int i; struct mt76_connac_pm *pm = &dev->pm; @@ -124,7 +124,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) tasklet_disable(&dev->mt76.irq_tasklet); } -static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) +static u32 __mt7921_reg_addr(struct mt792x_dev *dev, u32 addr) { static const struct mt76_connac_reg_map fixed_map[] = { { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ @@ -203,7 +203,7 @@ static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); return dev->bus_ops->rr(mdev, addr); @@ -211,7 +211,7 @@ static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); dev->bus_ops->wr(mdev, addr, val); @@ -219,7 +219,7 @@ static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); return dev->bus_ops->rmw(mdev, addr, mask, val); @@ -256,7 +256,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, }; struct ieee80211_ops *ops; struct mt76_bus_ops *bus_ops; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; @@ -303,7 +303,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, mdev); - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &mt7921_pcie_ops; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); @@ -373,7 +373,7 @@ err_free_pci_vec: static void mt7921_pci_remove(struct pci_dev *pdev) { struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); mt7921e_unregister_device(dev); devm_free_irq(&pdev->dev, pdev->irq, dev); @@ -385,7 +385,7 @@ static int mt7921_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; int i, err; @@ -459,7 +459,7 @@ static int mt7921_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; int i, err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 32bba86727a5..7323388327f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -10,7 +10,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct mt76_connac_hw_txp *txp; @@ -53,7 +53,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } -int mt7921e_mac_reset(struct mt7921_dev *dev) +int mt7921e_mac_reset(struct mt792x_dev *dev) { int i, err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c index 1aefbb6cf0ab..5a30cd0b9382 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c @@ -4,7 +4,7 @@ #include "mt7921.h" #include "mcu.h" -int mt7921e_driver_own(struct mt7921_dev *dev) +int mt7921e_driver_own(struct mt792x_dev *dev) { u32 reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); @@ -22,7 +22,7 @@ static int mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); enum mt76_mcuq_id txq = MT_MCUQ_WM; int ret; @@ -38,7 +38,7 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); } -int mt7921e_mcu_init(struct mt7921_dev *dev) +int mt7921e_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mt7921_mcu_ops = { .headroom = sizeof(struct mt76_connac2_mcu_txd), @@ -62,7 +62,7 @@ int mt7921e_mcu_init(struct mt7921_dev *dev) return err; } -int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) +int __mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev) { int i, err = 0; @@ -81,7 +81,7 @@ int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) return err; } -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) +int mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; @@ -101,7 +101,7 @@ out: return err; } -int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev) +int mt7921e_mcu_fw_pmctrl(struct mt792x_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index a77a309c0d60..86da0cbbdf3b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -27,7 +27,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w) struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, txrx_worker); struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { queue_work(mdev->wq, &dev->pm.wake_work); @@ -38,7 +38,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w) mt76_connac_pm_unref(&dev->mphy, &dev->pm); } -static void mt7921s_unregister_device(struct mt7921_dev *dev) +static void mt7921s_unregister_device(struct mt792x_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; @@ -122,7 +122,7 @@ static int mt7921s_probe(struct sdio_func *func, .fw_own = mt7921s_mcu_fw_pmctrl, }; struct ieee80211_ops *ops; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; @@ -136,7 +136,7 @@ static int mt7921s_probe(struct sdio_func *func, if (!mdev) return -ENOMEM; - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &mt7921_sdio_ops; sdio_set_drvdata(func, dev); @@ -196,7 +196,7 @@ error: static void mt7921s_remove(struct sdio_func *func) { - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); mt7921s_unregister_device(dev); } @@ -204,7 +204,7 @@ static void mt7921s_remove(struct sdio_func *func) static int mt7921s_suspend(struct device *__dev) { struct sdio_func *func = dev_to_sdio_func(__dev); - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; int err; @@ -277,7 +277,7 @@ restore_suspend: static int mt7921s_resume(struct device *__dev) { struct sdio_func *func = dev_to_sdio_func(__dev); - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index cff9925c41ea..8edd0291c128 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -30,7 +30,7 @@ static u32 mt7921s_read_whcr(struct mt76_dev *dev) return sdio_readl(dev->sdio.func, MCR_WHCR, NULL); } -int mt7921s_wfsys_reset(struct mt7921_dev *dev) +int mt7921s_wfsys_reset(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; u32 val, status; @@ -71,7 +71,7 @@ int mt7921s_wfsys_reset(struct mt7921_dev *dev) return 0; } -int mt7921s_init_reset(struct mt7921_dev *dev) +int mt7921s_init_reset(struct mt792x_dev *dev) { set_bit(MT76_MCU_RESET, &dev->mphy.state); @@ -91,7 +91,7 @@ int mt7921s_init_reset(struct mt7921_dev *dev) return 0; } -int mt7921s_mac_reset(struct mt7921_dev *dev) +int mt7921s_mac_reset(struct mt792x_dev *dev) { int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 177679ce1c80..360de6a0de2b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -16,7 +16,7 @@ static int mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); enum mt7921_sdio_pkt_type type = MT7921_SDIO_CMD; enum mt76_mcuq_id txq = MT_MCUQ_WM; int ret, pad; @@ -51,14 +51,14 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return ret; } -static u32 mt7921s_read_rm3r(struct mt7921_dev *dev) +static u32 mt7921s_read_rm3r(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; return sdio_readl(sdio->func, MCR_D2HRM3R, NULL); } -static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) +static u32 mt7921s_clear_rm3r_drv_own(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; u32 val; @@ -71,7 +71,7 @@ static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) return val; } -int mt7921s_mcu_init(struct mt7921_dev *dev) +int mt7921s_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mt7921s_mcu_ops = { .headroom = MT_SDIO_HDR_SIZE + @@ -97,7 +97,7 @@ int mt7921s_mcu_init(struct mt7921_dev *dev) return 0; } -int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) +int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev) { struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; @@ -133,7 +133,7 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) return 0; } -int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) +int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev) { struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c index 208dcb2afbe7..3c2165095ddd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c @@ -31,7 +31,7 @@ static const struct nla_policy mt7921_tm_policy[NUM_MT7921_TM_ATTRS] = { }; static int -mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req) +mt7921_tm_set(struct mt792x_dev *dev, struct mt7921_tm_cmd *req) { struct mt7921_rftest_cmd cmd = { .action = req->action, @@ -82,7 +82,7 @@ out: } static int -mt7921_tm_query(struct mt7921_dev *dev, struct mt7921_tm_cmd *req, +mt7921_tm_query(struct mt792x_dev *dev, struct mt7921_tm_cmd *req, struct mt7921_tm_evt *evt_resp) { struct mt7921_rftest_cmd cmd = { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 1f302c430339..898cb1de9400 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -82,7 +82,7 @@ static void mt7921u_copy(struct mt76_dev *dev, u32 offset, mutex_unlock(&usb->usb_ctrl_mtx); } -int mt7921u_mcu_power_on(struct mt7921_dev *dev) +int mt7921u_mcu_power_on(struct mt792x_dev *dev) { int ret; @@ -105,7 +105,7 @@ static int mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 pad, ep; int ret; @@ -131,7 +131,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return ret; } -static int mt7921u_mcu_init(struct mt7921_dev *dev) +static int mt7921u_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mcu_ops = { .headroom = MT_SDIO_HDR_SIZE + @@ -157,13 +157,13 @@ static int mt7921u_mcu_init(struct mt7921_dev *dev) static void mt7921u_stop(struct ieee80211_hw *hw) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt7921_hw_dev(hw); mt76u_stop_tx(&dev->mt76); mt7921_stop(hw); } -static void mt7921u_cleanup(struct mt7921_dev *dev) +static void mt7921u_cleanup(struct mt792x_dev *dev) { clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt7921u_wfsys_reset(dev); @@ -207,7 +207,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, struct usb_device *udev = interface_to_usbdev(usb_intf); struct ieee80211_ops *ops; struct ieee80211_hw *hw; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; @@ -222,7 +222,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (!mdev) return -ENOMEM; - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &hif_ops; @@ -284,7 +284,7 @@ error: static void mt7921u_disconnect(struct usb_interface *usb_intf) { - struct mt7921_dev *dev = usb_get_intfdata(usb_intf); + struct mt792x_dev *dev = usb_get_intfdata(usb_intf); cancel_work_sync(&dev->init_work); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) @@ -302,7 +302,7 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf) #ifdef CONFIG_PM static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) { - struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt792x_dev *dev = usb_get_intfdata(intf); struct mt76_connac_pm *pm = &dev->pm; int err; @@ -329,7 +329,7 @@ failed: static int mt7921u_resume(struct usb_interface *intf) { - struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt792x_dev *dev = usb_get_intfdata(intf); struct mt76_connac_pm *pm = &dev->pm; bool reinit = true; int err, i; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c index 50eb6e7fd6b5..f612873c704b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -32,7 +32,7 @@ static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) mutex_unlock(&dev->usb.usb_ctrl_mtx); } -static void mt7921u_dma_prefetch(struct mt7921_dev *dev) +static void mt7921u_dma_prefetch(struct mt792x_dev *dev) { mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), MT_WPDMA0_MAX_CNT_MASK, 4); @@ -70,7 +70,7 @@ static void mt7921u_dma_prefetch(struct mt7921_dev *dev) MT_WPDMA0_BASE_PTR_MASK, 0x2c0); } -static void mt7921u_wfdma_init(struct mt7921_dev *dev) +static void mt7921u_wfdma_init(struct mt792x_dev *dev) { mt7921u_dma_prefetch(dev); @@ -90,7 +90,7 @@ static void mt7921u_wfdma_init(struct mt7921_dev *dev) mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); } -static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev) +static int mt7921u_dma_rx_evt_ep4(struct mt792x_dev *dev) { if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) @@ -104,7 +104,7 @@ static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev) return 0; } -static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) +static void mt7921u_epctl_rst_opt(struct mt792x_dev *dev, bool reset) { u32 val; @@ -121,7 +121,7 @@ static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); } -int mt7921u_dma_init(struct mt7921_dev *dev, bool resume) +int mt7921u_dma_init(struct mt792x_dev *dev, bool resume) { int err; @@ -148,7 +148,7 @@ int mt7921u_dma_init(struct mt7921_dev *dev, bool resume) return 0; } -int mt7921u_wfsys_reset(struct mt7921_dev *dev) +int mt7921u_wfsys_reset(struct mt792x_dev *dev) { u32 val; int i; @@ -180,7 +180,7 @@ int mt7921u_wfsys_reset(struct mt7921_dev *dev) return 0; } -int mt7921u_init_reset(struct mt7921_dev *dev) +int mt7921u_init_reset(struct mt792x_dev *dev) { set_bit(MT76_RESET, &dev->mphy.state); @@ -197,7 +197,7 @@ int mt7921u_init_reset(struct mt7921_dev *dev) return mt76u_resume_rx(&dev->mt76); } -int mt7921u_mac_reset(struct mt7921_dev *dev) +int mt7921u_mac_reset(struct mt792x_dev *dev) { int err; -- cgit From 838cc6679733584d6f1c1e8423a1ad5aa5cb9ad0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:53 +0800 Subject: wifi: mt76: mt7921: rename mt7921_hif_ops in mt792x_hif_ops This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 617aecd42544..e84c6a56d40e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -249,7 +249,7 @@ enum mt7921_eeprom_field { #define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) #define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) #define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) -struct mt7921_hif_ops { +struct mt792x_hif_ops { int (*init_reset)(struct mt792x_dev *dev); int (*reset)(struct mt792x_dev *dev); int (*mcu_init)(struct mt792x_dev *dev); @@ -278,7 +278,7 @@ struct mt792x_dev { struct mt76_connac_pm pm; struct mt76_connac_coredump coredump; - const struct mt7921_hif_ops *hif_ops; + const struct mt792x_hif_ops *hif_ops; struct work_struct ipv6_ns_work; /* IPv6 addresses for WoWLAN */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 517e4d541bdc..4227b5028a6f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -247,7 +247,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt7921_update_channel, }; - static const struct mt7921_hif_ops mt7921_pcie_ops = { + static const struct mt792x_hif_ops mt7921_pcie_ops = { .init_reset = mt7921e_init_reset, .reset = mt7921e_mac_reset, .mcu_init = mt7921e_mcu_init, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 86da0cbbdf3b..b438947c2bd8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -114,7 +114,7 @@ static int mt7921s_probe(struct sdio_func *func, .rd_rp = mt76s_rd_rp, .type = MT76_BUS_SDIO, }; - static const struct mt7921_hif_ops mt7921_sdio_ops = { + static const struct mt792x_hif_ops mt7921_sdio_ops = { .init_reset = mt7921s_init_reset, .reset = mt7921s_mac_reset, .mcu_init = mt7921s_mcu_init, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 898cb1de9400..b02a6d03c645 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -191,7 +191,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt7921_update_channel, }; - static const struct mt7921_hif_ops hif_ops = { + static const struct mt792x_hif_ops hif_ops = { .mcu_init = mt7921u_mcu_init, .init_reset = mt7921u_init_reset, .reset = mt7921u_mac_reset, -- cgit From 1c42e0f283598b43b74318ef54f3d8a57ab46324 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:54 +0800 Subject: wifi: mt76: mt792x: move shared structure definition in mt792x.h This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 111 +----------------- drivers/net/wireless/mediatek/mt76/mt792x.h | 129 +++++++++++++++++++++ 2 files changed, 130 insertions(+), 110 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index e84c6a56d40e..b04d78a5d51a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -4,9 +4,7 @@ #ifndef __MT7921_H #define __MT7921_H -#include -#include -#include "../mt76_connac_mcu.h" +#include "../mt792x.h" #include "regs.h" #include "acpi_sar.h" @@ -127,9 +125,6 @@ struct mt7921_sdio_intr { #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) #define to_rcpi(rssi) (2 * (rssi) + 220) -struct mt792x_vif; -struct mt792x_sta; - enum mt7921_txq_id { MT7921_TXQ_BAND0, MT7921_TXQ_BAND1, @@ -143,39 +138,6 @@ enum mt7921_rxq_id { MT7921_RXQ_MCU_WM = 0, }; -DECLARE_EWMA(avg_signal, 10, 8) - -struct mt792x_sta { - struct mt76_wcid wcid; /* must be first */ - - struct mt792x_vif *vif; - - u32 airtime_ac[8]; - - int ack_signal; - struct ewma_avg_signal avg_ack_signal; - - unsigned long last_txs; - - struct mt76_connac_sta_key_conf bip; -}; - -DECLARE_EWMA(rssi, 10, 8); - -struct mt792x_vif { - struct mt76_vif mt76; /* must be first */ - - struct mt792x_sta sta; - struct mt792x_sta *wep_sta; - - struct mt792x_phy *phy; - - struct ewma_rssi rssi; - - struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; - struct ieee80211_chanctx_conf *ctx; -}; - enum { MT7921_CLC_POWER, MT7921_CLC_CHAN, @@ -199,40 +161,6 @@ struct mt7921_clc { u8 data[]; } __packed; -struct mt792x_phy { - struct mt76_phy *mt76; - struct mt792x_dev *dev; - - struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; - - u64 omac_mask; - - u16 noise; - - s16 coverage_class; - u8 slottime; - - u32 rx_ampdu_ts; - u32 ampdu_ref; - - struct mt76_mib_stats mib; - - u8 sta_work_count; - - struct sk_buff_head scan_event_list; - struct delayed_work scan_work; -#ifdef CONFIG_ACPI - void *acpisar; -#endif - void *clc[MT7921_CLC_MAX_NUM]; - - struct work_struct roc_work; - struct timer_list roc_timer; - wait_queue_head_t roc_wait; - u8 roc_token_id; - bool roc_grant; -}; - enum mt7921_eeprom_field { MT_EE_CHIP_ID = 0x000, MT_EE_VERSION = 0x002, @@ -249,43 +177,6 @@ enum mt7921_eeprom_field { #define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) #define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) #define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) -struct mt792x_hif_ops { - int (*init_reset)(struct mt792x_dev *dev); - int (*reset)(struct mt792x_dev *dev); - int (*mcu_init)(struct mt792x_dev *dev); - int (*drv_own)(struct mt792x_dev *dev); - int (*fw_own)(struct mt792x_dev *dev); -}; - -struct mt792x_dev { - union { /* must be first */ - struct mt76_dev mt76; - struct mt76_phy mphy; - }; - - const struct mt76_bus_ops *bus_ops; - struct mt792x_phy phy; - - struct work_struct reset_work; - bool hw_full_reset:1; - bool hw_init_done:1; - bool fw_assert:1; - - struct work_struct init_work; - - u8 fw_debug; - u8 fw_features; - - struct mt76_connac_pm pm; - struct mt76_connac_coredump coredump; - const struct mt792x_hif_ops *hif_ops; - - struct work_struct ipv6_ns_work; - /* IPv6 addresses for WoWLAN */ - struct sk_buff_head ipv6_ns_list; - - enum environment_cap country_ie_env; -}; enum { TXPWR_USER, diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h new file mode 100644 index 000000000000..2c17c2e71af1 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT792X_H +#define __MT792X_H + +#include +#include + +#include "mt76_connac_mcu.h" + +struct mt792x_vif; +struct mt792x_sta; + +enum { + MT792x_CLC_POWER, + MT792x_CLC_CHAN, + MT792x_CLC_MAX_NUM, +}; + +DECLARE_EWMA(avg_signal, 10, 8) + +struct mt792x_sta { + struct mt76_wcid wcid; /* must be first */ + + struct mt792x_vif *vif; + + u32 airtime_ac[8]; + + int ack_signal; + struct ewma_avg_signal avg_ack_signal; + + unsigned long last_txs; + + struct mt76_connac_sta_key_conf bip; +}; + +DECLARE_EWMA(rssi, 10, 8); + +struct mt792x_vif { + struct mt76_vif mt76; /* must be first */ + + struct mt792x_sta sta; + struct mt792x_sta *wep_sta; + + struct mt792x_phy *phy; + + struct ewma_rssi rssi; + + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; + struct ieee80211_chanctx_conf *ctx; +}; + +struct mt792x_phy { + struct mt76_phy *mt76; + struct mt792x_dev *dev; + + struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; + + u64 omac_mask; + + u16 noise; + + s16 coverage_class; + u8 slottime; + + u32 rx_ampdu_ts; + u32 ampdu_ref; + + struct mt76_mib_stats mib; + + u8 sta_work_count; + + struct sk_buff_head scan_event_list; + struct delayed_work scan_work; +#ifdef CONFIG_ACPI + void *acpisar; +#endif + void *clc[MT792x_CLC_MAX_NUM]; + + struct work_struct roc_work; + struct timer_list roc_timer; + wait_queue_head_t roc_wait; + u8 roc_token_id; + bool roc_grant; +}; + +struct mt792x_hif_ops { + int (*init_reset)(struct mt792x_dev *dev); + int (*reset)(struct mt792x_dev *dev); + int (*mcu_init)(struct mt792x_dev *dev); + int (*drv_own)(struct mt792x_dev *dev); + int (*fw_own)(struct mt792x_dev *dev); +}; + +struct mt792x_dev { + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + + const struct mt76_bus_ops *bus_ops; + struct mt792x_phy phy; + + struct work_struct reset_work; + bool hw_full_reset:1; + bool hw_init_done:1; + bool fw_assert:1; + bool has_eht:1; + + struct work_struct init_work; + + u8 fw_debug; + u8 fw_features; + + struct mt76_connac_pm pm; + struct mt76_connac_coredump coredump; + const struct mt792x_hif_ops *hif_ops; + + struct work_struct ipv6_ns_work; + /* IPv6 addresses for WoWLAN */ + struct sk_buff_head ipv6_ns_list; + + enum environment_cap country_ie_env; + u32 backup_l1; + u32 backup_l2; +}; + +#endif /* __MT7925_H */ -- cgit From c605d0ce025358d50209468ede7b15a3d2656c1a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:55 +0800 Subject: wifi: mt76: mt7921: move mt792x_mutex_{acquire/release} in mt792x.h This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 32 ++--- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 8 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 12 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 144 ++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 5 - drivers/net/wireless/mediatek/mt76/mt792x.h | 5 + 6 files changed, 103 insertions(+), 103 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 6137a10c022a..0c94fa7ae485 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -8,9 +8,9 @@ mt7921_reg_set(void *data, u64 val) { struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_wr(dev, dev->mt76.debugfs_reg, val); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -20,9 +20,9 @@ mt7921_reg_get(void *data, u64 *val) { struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); *val = mt76_rr(dev, dev->mt76.debugfs_reg); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -34,12 +34,12 @@ mt7921_fw_debug_set(void *data, u64 val) { struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); dev->fw_debug = (u8)val; mt7921_mcu_fw_log_2_host(dev, dev->fw_debug); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -98,7 +98,7 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) struct mt76_mib_stats *mib = &phy->mib; int i; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_ampdu_stat_read_phy(phy, file); @@ -113,7 +113,7 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) seq_puts(file, "\n"); } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -126,7 +126,7 @@ mt7921_queues_acq(struct seq_file *s, void *data) struct mt792x_dev *dev = dev_get_drvdata(s->private); int i; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); for (i = 0; i < 4; i++) { u32 ctrl, val, qlen = 0; @@ -146,7 +146,7 @@ mt7921_queues_acq(struct seq_file *s, void *data) seq_printf(s, "AC%d: queued=%d\n", i, qlen); } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -215,9 +215,9 @@ mt7921_txpwr(struct seq_file *s, void *data) struct mt7921_txpwr txpwr; int ret; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt7921_get_txpwr_info(dev, &txpwr); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); if (ret) return ret; @@ -316,7 +316,7 @@ mt7921_deep_sleep_set(void *data, u64 val) if (mt76_is_usb(&dev->mt76)) return -EOPNOTSUPP; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (pm->ds_enable_user == enable) goto out; @@ -324,7 +324,7 @@ mt7921_deep_sleep_set(void *data, u64 val) pm->ds_enable = enable && !monitor; mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -400,9 +400,9 @@ static int mt7921_chip_reset(void *data, u64 val) break; default: /* Collect the core dump before reset wifisys. */ - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt76_connac_mcu_chip_config(&dev->mt76); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); break; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index bace86813b76..100479c2e9f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -64,9 +64,9 @@ static ssize_t mt7921_thermal_temp_show(struct device *dev, struct mt792x_dev *mdev = phy->dev; int temperature; - mt7921_mutex_acquire(mdev); + mt792x_mutex_acquire(mdev); temperature = mt7921_mcu_get_temperature(phy); - mt7921_mutex_release(mdev); + mt792x_mutex_release(mdev); if (temperature < 0) return temperature; @@ -116,11 +116,11 @@ mt7921_regd_notifier(struct wiphy *wiphy, dev->mt76.region = request->dfs_region; dev->country_ie_env = request->country_ie_env; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env); mt76_connac_mcu_set_channel_domain(hw->priv); mt7921_set_tx_sar_pwr(hw, NULL); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index a17d70aa90da..49ba23ecf495 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -971,7 +971,7 @@ void mt7921_mac_work(struct work_struct *work) mac_work.work); phy = mphy->priv; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); mt76_update_survey(mphy); if (++mphy->mac_work_count == 2) { @@ -980,7 +980,7 @@ void mt7921_mac_work(struct work_struct *work) mt7921_mac_update_mib_stats(phy); } - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); mt76_tx_status_check(mphy->dev, false); ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, @@ -1191,9 +1191,9 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mac_sta_poll(dev); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return false; } @@ -1213,10 +1213,10 @@ void mt7921_set_ipv6_ns_work(struct work_struct *work) if (!skb) break; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD(OFFLOAD), true); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } while (!ret); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 2f597fb3ae5c..2cd85fdd15f6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -255,9 +255,9 @@ static int mt7921_start(struct ieee80211_hw *hw) struct mt792x_phy *phy = mt7921_hw_phy(hw); int err; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); err = __mt7921_start(phy); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } @@ -274,10 +274,10 @@ void mt7921_stop(struct ieee80211_hw *hw) cancel_work_sync(&dev->reset_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } EXPORT_SYMBOL_GPL(mt7921_stop); @@ -290,7 +290,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, struct mt76_txq *mtxq; int idx, ret = 0; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) { @@ -333,7 +333,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } @@ -347,7 +347,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, struct mt792x_phy *phy = mt7921_hw_phy(hw); int idx = msta->wcid.idx; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); @@ -355,7 +355,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta->wcid.poll_list)) @@ -384,11 +384,11 @@ void mt7921_roc_work(struct work_struct *work) if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7921_roc_iter, phy); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); ieee80211_remain_on_channel_expired(phy->mt76->hw); } @@ -406,10 +406,10 @@ static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) del_timer_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } @@ -454,9 +454,9 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, struct mt792x_phy *phy = mt7921_hw_phy(hw); int err; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); err = mt7921_set_roc(phy, mvif, chan, duration, MT7921_ROC_REQ_ROC); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } @@ -477,7 +477,7 @@ static int mt7921_set_channel(struct mt792x_phy *phy) cancel_delayed_work_sync(&phy->mt76->mac_work); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); set_bit(MT76_RESET, &phy->mt76->state); mt76_set_channel(phy->mt76); @@ -493,7 +493,7 @@ static int mt7921_set_channel(struct mt792x_phy *phy) out: clear_bit(MT76_RESET, &phy->mt76->state); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); mt76_worker_schedule(&dev->mt76.tx_worker); ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, @@ -546,7 +546,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (cmd == SET_KEY) { *wcid_keyidx = idx; @@ -570,7 +570,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key, MCU_UNI_CMD(STA_REC_UPDATE), &mvif->wep_sta->wcid, cmd); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -642,7 +642,7 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) ieee80211_wake_queues(hw); } - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (changed & IEEE80211_CONF_CHANGE_POWER) { ret = mt7921_set_tx_sar_pwr(hw, NULL); @@ -657,7 +657,7 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) } out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } @@ -698,9 +698,9 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, MT7921_FILTER(FIF_CONTROL, CONTROL); MT7921_FILTER(FIF_OTHER_BSS, OTHER_BSS); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_set_rxfilter(dev, flags, 0, 0); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); *total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL); } @@ -713,7 +713,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt792x_dev *dev = mt7921_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; @@ -749,7 +749,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, info); } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, @@ -800,7 +800,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, @@ -814,7 +814,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } EXPORT_SYMBOL_GPL(mt7921_mac_sta_assoc); @@ -909,9 +909,9 @@ static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { struct mt792x_dev *dev = mt7921_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, 0); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -935,7 +935,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mtxq = (struct mt76_txq *)txq->drv_priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); switch (action) { case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, @@ -968,7 +968,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } @@ -982,9 +982,9 @@ static int mt7921_sta_state(struct ieee80211_hw *hw, struct mt792x_dev *dev = mt7921_hw_dev(hw); if (dev->pm.ds_enable) { - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_sta_state_dp(&dev->mt76, old_state, new_state); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } return mt76_sta_state(hw, vif, sta, old_state, new_state); @@ -997,14 +997,14 @@ mt7921_get_stats(struct ieee80211_hw *hw, struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt76_mib_stats *mib = &phy->mib; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); stats->dot11RTSSuccessCount = mib->rts_cnt; stats->dot11RTSFailureCount = mib->rts_retries_cnt; stats->dot11FCSErrorCount = mib->fcs_err_cnt; stats->dot11ACKFailureCount = mib->ack_fail_cnt; - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return 0; } @@ -1144,7 +1144,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, }; int i, ei = 0; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mac_update_mib_stats(phy); @@ -1184,7 +1184,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, wi.initial_stat_idx = ei; ieee80211_iterate_stations_atomic(hw, mt7921_ethtool_worker, &wi); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); if (!wi.sta_count) return; @@ -1212,7 +1212,7 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } tsf; u16 n; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; /* TSF software read */ @@ -1220,7 +1220,7 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return tsf.t64; } @@ -1238,7 +1238,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } tsf = { .t64 = timestamp, }; u16 n; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); @@ -1246,7 +1246,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* TSF software overwrite */ mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static void @@ -1255,10 +1255,10 @@ mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt792x_dev *dev = phy->dev; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); phy->coverage_class = max_t(s16, coverage_class, 0); mt7921_mac_set_timing(phy); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } void mt7921_scan_work(struct work_struct *work) @@ -1302,9 +1302,9 @@ mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_hw_scan(mphy, vif, req); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1315,9 +1315,9 @@ mt7921_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt76_phy *mphy = hw->priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_cancel_hw_scan(mphy, vif); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int @@ -1329,7 +1329,7 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_sched_scan_req(mphy, vif, req); if (err < 0) @@ -1337,7 +1337,7 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = mt76_connac_mcu_sched_scan_enable(mphy, vif, true); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1349,9 +1349,9 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_sched_scan_enable(mphy, vif, false); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1369,7 +1369,7 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) return -EINVAL; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); phy->mt76->antenna_mask = tx_ant; phy->mt76->chainmask = tx_ant; @@ -1377,7 +1377,7 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) mt76_set_stream_caps(phy->mt76, true); mt7921_set_stream_he_caps(phy); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -1432,7 +1432,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, cancel_delayed_work_sync(&dev->pm.ps_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, @@ -1440,7 +1440,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, mt7921_mcu_set_suspend_iter, &dev->mphy); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -1450,7 +1450,7 @@ static int mt7921_resume(struct ieee80211_hw *hw) struct mt792x_dev *dev = mt7921_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); set_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, @@ -1461,7 +1461,7 @@ static int mt7921_resume(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, MT7921_WATCHDOG_TIME); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -1480,9 +1480,9 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, { struct mt792x_dev *dev = mt7921_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_update_gtk_rekey(hw, vif, data); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } #endif /* CONFIG_PM */ @@ -1503,7 +1503,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_dev *dev = mt7921_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (enabled) set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); @@ -1513,7 +1513,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, MCU_UNI_CMD(STA_REC_UPDATE)); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } #if IS_ENABLED(CONFIG_IPV6) @@ -1601,7 +1601,7 @@ static int mt7921_set_sar_specs(struct ieee80211_hw *hw, struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env); if (err < 0) @@ -1609,7 +1609,7 @@ static int mt7921_set_sar_specs(struct ieee80211_hw *hw, err = mt7921_set_tx_sar_pwr(hw, sar); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1621,9 +1621,9 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw, { struct mt792x_dev *dev = mt7921_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int @@ -1635,7 +1635,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, true, mvif->ctx); @@ -1649,7 +1649,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_NONE); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1663,7 +1663,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt792x_dev *dev = mt7921_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt7921_mcu_set_bss_pm(dev, vif, false); if (err) @@ -1673,7 +1673,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mvif->ctx); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int @@ -1711,11 +1711,11 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, { struct mt792x_phy *phy = mt7921_hw_phy(hw); - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, IEEE80211_IFACE_ITER_ACTIVE, mt7921_ctx_iter, ctx); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); } static int @@ -1757,10 +1757,10 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, u16 duration = info->duration ? info->duration : jiffies_to_msecs(HZ); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration, MT7921_ROC_REQ_JOIN); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index b04d78a5d51a..2ca8560aa523 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -224,11 +224,6 @@ mt7921_hw_dev(struct ieee80211_hw *hw) return container_of(phy->dev, struct mt792x_dev, mt76); } -#define mt7921_mutex_acquire(dev) \ - mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) -#define mt7921_mutex_release(dev) \ - mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) - extern const struct ieee80211_ops mt7921_ops; u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 2c17c2e71af1..bc7d11acfa6a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -126,4 +126,9 @@ struct mt792x_dev { u32 backup_l2; }; +#define mt792x_mutex_acquire(dev) \ + mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) +#define mt792x_mutex_release(dev) \ + mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) + #endif /* __MT7925_H */ -- cgit From 20249e1a853c412f452aa6ee0beb752360e69f17 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:56 +0800 Subject: wifi: mt76: mt7921: move mt792x_hw_dev in mt792x.h This is a preliminary patch to introduce WiFi7 chipset support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 66 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 8 --- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 8 +++ 5 files changed, 43 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 100479c2e9f1..d78cdaaf5bb6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -110,7 +110,7 @@ mt7921_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 2cd85fdd15f6..7213718ae399 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -264,7 +264,7 @@ static int mt7921_start(struct ieee80211_hw *hw) void mt7921_stop(struct ieee80211_hw *hw) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -285,7 +285,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); struct mt76_txq *mtxq; int idx, ret = 0; @@ -343,7 +343,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = &mvif->sta; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int idx = msta->wcid.idx; @@ -506,7 +506,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; @@ -630,7 +630,7 @@ void mt7921_set_runtime_pm(struct mt792x_dev *dev) static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int ret = 0; @@ -686,7 +686,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, #define MT7921_FILTER_OTHER_BSS BIT(6) #define MT7921_FILTER_ENABLE BIT(31) - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); u32 flags = MT7921_FILTER_ENABLE; #define MT7921_FILTER(_fif, _type) do { \ @@ -711,7 +711,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, u64 changed) { struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); @@ -869,7 +869,7 @@ static void mt7921_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; @@ -907,7 +907,7 @@ static void mt7921_tx(struct ieee80211_hw *hw, static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, 0); @@ -921,7 +921,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; @@ -979,7 +979,7 @@ static int mt7921_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); if (dev->pm.ds_enable) { mt792x_mutex_acquire(dev); @@ -1087,7 +1087,7 @@ static void mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 sset, u8 *data) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); if (sset != ETH_SS_STATS) return; @@ -1105,7 +1105,7 @@ static int mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); if (sset != ETH_SS_STATS) return 0; @@ -1204,7 +1204,7 @@ static u64 mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { u64 t64; @@ -1230,7 +1230,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); u8 omac_idx = mvif->mt76.omac_idx; union { u64 t64; @@ -1298,7 +1298,7 @@ static int mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1312,7 +1312,7 @@ mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt7921_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; mt792x_mutex_acquire(dev); @@ -1325,7 +1325,7 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *req, struct ieee80211_scan_ies *ies) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1345,7 +1345,7 @@ out: static int mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; @@ -1359,7 +1359,7 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); int max_nss = hweight8(hw->wiphy->available_antennas_tx); @@ -1423,7 +1423,7 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw, static int mt7921_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); cancel_delayed_work_sync(&phy->scan_work); @@ -1447,7 +1447,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, static int mt7921_resume(struct ieee80211_hw *hw) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt7921_hw_phy(hw); mt792x_mutex_acquire(dev); @@ -1468,7 +1468,7 @@ static int mt7921_resume(struct ieee80211_hw *hw) static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_dev *mdev = &dev->mt76; device_set_wakeup_enable(mdev->dev, enabled); @@ -1478,7 +1478,7 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); mt76_connac_mcu_update_gtk_rekey(hw, vif, data); @@ -1489,7 +1489,7 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy), HZ / 2); @@ -1501,7 +1501,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, bool enabled) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); @@ -1598,7 +1598,7 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, static int mt7921_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; mt792x_mutex_acquire(dev); @@ -1619,7 +1619,7 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); @@ -1632,7 +1632,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; mt792x_mutex_acquire(dev); @@ -1660,7 +1660,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; mt792x_mutex_acquire(dev); @@ -1725,7 +1725,7 @@ mt7921_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); mvif->ctx = ctx; @@ -1741,7 +1741,7 @@ mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); mvif->ctx = NULL; @@ -1753,7 +1753,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_prep_tx_info *info) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); u16 duration = info->duration ? info->duration : jiffies_to_msecs(HZ); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 2ca8560aa523..ad18fcc4a7b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -216,14 +216,6 @@ mt7921_hw_phy(struct ieee80211_hw *hw) return phy->priv; } -static inline struct mt792x_dev * -mt7921_hw_dev(struct ieee80211_hw *hw) -{ - struct mt76_phy *phy = hw->priv; - - return container_of(phy->dev, struct mt792x_dev, mt76); -} - extern const struct ieee80211_ops mt7921_ops; u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index b02a6d03c645..9d54be3d3d03 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -157,7 +157,7 @@ static int mt7921u_mcu_init(struct mt792x_dev *dev) static void mt7921u_stop(struct ieee80211_hw *hw) { - struct mt792x_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); mt76u_stop_tx(&dev->mt76); mt7921_stop(hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index bc7d11acfa6a..9c724bc156af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -126,6 +126,14 @@ struct mt792x_dev { u32 backup_l2; }; +static inline struct mt792x_dev * +mt792x_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt792x_dev, mt76); +} + #define mt792x_mutex_acquire(dev) \ mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) #define mt792x_mutex_release(dev) \ -- cgit From c74df1c067f2af0a3758a5ab02806f501473797c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:57 +0800 Subject: wifi: mt76: mt792x: introduce mt792x-lib module mt792x-lib module will contain the shared code between mt7921 and new MT79 WiFi7 chipset Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Kconfig | 4 + drivers/net/wireless/mediatek/mt76/Makefile | 4 + drivers/net/wireless/mediatek/mt76/mt7921/Kconfig | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 4 +- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 16 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 148 +----- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 535 ++------------------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 25 +- .../wireless/mediatek/mt76/mt7921/mt7921_trace.h | 51 -- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 4 + .../net/wireless/mediatek/mt76/mt7921/sdio_mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/trace.c | 12 - drivers/net/wireless/mediatek/mt76/mt792x.h | 61 +++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 469 ++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt792x_mac.c | 136 ++++++ drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 3 - drivers/net/wireless/mediatek/mt76/mt792x_trace.c | 14 + drivers/net/wireless/mediatek/mt76/mt792x_trace.h | 51 ++ 20 files changed, 807 insertions(+), 738 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/trace.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_core.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_trace.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_trace.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 18152c16c36f..1ddf195597a8 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -29,6 +29,10 @@ config MT76_CONNAC_LIB tristate select MT76_CORE +config MT792x_LIB + tristate + select MT76_CONNAC_LIB + source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index d8e8079c8b54..a20eebba04ba 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o +obj-$(CONFIG_MT792x_LIB) += mt792x-lib.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ @@ -19,6 +20,7 @@ mt76-sdio-y := sdio.o sdio_txrx.o CFLAGS_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src) CFLAGS_mt76x02_trace.o := -I$(src) +CFLAGS_mt792x_trace.o := -I$(src) mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \ @@ -29,6 +31,8 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o +mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o + obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT7603E) += mt7603/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig index adff2d7350b5..b92630cdf88b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: ISC config MT7921_COMMON tristate - select MT76_CONNAC_LIB + select MT792x_LIB select WANT_DEV_COREDUMP config MT7921E diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index e5d2d2e131a2..fd82dff76dae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -5,9 +5,7 @@ obj-$(CONFIG_MT7921E) += mt7921e.o obj-$(CONFIG_MT7921S) += mt7921s.o obj-$(CONFIG_MT7921U) += mt7921u.o -CFLAGS_trace.o := -I$(src) - -mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o +mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o mt7921-common-$(CONFIG_ACPI) += acpi_sar.o mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 0c94fa7ae485..59920cffee6a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -67,7 +67,7 @@ mt7921_ampdu_stat_read_phy(struct mt792x_phy *phy, if (!phy) return; - mt7921_mac_update_mib_stats(phy); + mt792x_mac_update_mib_stats(phy); /* Tx ampdu stat */ for (i = 0; i < ARRAY_SIZE(range); i++) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index d78cdaaf5bb6..449ce34a6dcf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -12,7 +12,7 @@ static const struct ieee80211_iface_limit if_limits[] = { { - .max = MT7921_MAX_INTERFACES, + .max = MT792x_MAX_INTERFACES, .types = BIT(NL80211_IFTYPE_STATION) }, { @@ -25,7 +25,7 @@ static const struct ieee80211_iface_combination if_comb[] = { { .limits = if_limits, .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = MT7921_MAX_INTERFACES, + .max_interfaces = MT792x_MAX_INTERFACES, .num_different_channels = 1, .beacon_int_infra_match = true, }, @@ -126,7 +126,7 @@ mt7921_regd_notifier(struct wiphy *wiphy, static int mt7921_init_wiphy(struct ieee80211_hw *hw) { - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt792x_dev *dev = phy->dev; struct wiphy *wiphy = hw->wiphy; @@ -319,7 +319,7 @@ int mt7921_mac_init(struct mt792x_dev *dev) /* enable hardware rx header translation */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN); - for (i = 0; i < MT7921_WTBL_SIZE; i++) + for (i = 0; i < MT792x_WTBL_SIZE; i++) mt7921_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); for (i = 0; i < 2; i++) @@ -379,7 +379,7 @@ static int mt7921_init_wcid(struct mt792x_dev *dev) int idx; /* Beacon and mgmt frames should occupy wcid 0 */ - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); if (idx) return -ENOSPC; @@ -437,7 +437,7 @@ int mt7921_register_device(struct mt792x_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; - dev->mt76.tx_worker.fn = mt7921_tx_worker; + dev->mt76.tx_worker.fn = mt792x_tx_worker; INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work); INIT_WORK(&dev->pm.wake_work, mt7921_pm_wake_work); @@ -447,7 +447,7 @@ int mt7921_register_device(struct mt792x_dev *dev) if (mt76_is_sdio(&dev->mt76)) init_waitqueue_head(&dev->mt76.sdio.wait); spin_lock_init(&dev->pm.txq_lock); - INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work); INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work); INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work); #if IS_ENABLED(CONFIG_IPV6) @@ -461,7 +461,7 @@ int mt7921_register_device(struct mt792x_dev *dev) INIT_WORK(&dev->init_work, mt7921_init_work); INIT_WORK(&dev->phy.roc_work, mt7921_roc_work); - timer_setup(&dev->phy.roc_timer, mt7921_roc_timer, 0); + timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0); init_waitqueue_head(&dev->phy.roc_wait); dev->pm.idle_timeout = MT7921_PM_TIMEOUT; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 49ba23ecf495..40f006664ad7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -15,6 +15,15 @@ #define MT_WTBL_AC0_CTT_OFFSET 20 +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask) +{ + mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); + + return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, + 0, 5000); +} + static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) { return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; @@ -43,15 +52,6 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt792x_dev *dev, return &sta->vif->sta.wcid; } -bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask) -{ - mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, - FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); - - return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, - 0, 5000); -} - static void mt7921_mac_sta_poll(struct mt792x_dev *dev) { static const u8 ac_to_tid[] = { @@ -528,7 +528,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) if (pid < MT_PACKET_ID_FIRST) return; - if (wcidx >= MT7921_WTBL_SIZE) + if (wcidx >= MT792x_WTBL_SIZE) return; rcu_read_lock(); @@ -721,47 +721,6 @@ void mt7921_mac_reset_counters(struct mt792x_phy *phy) mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); } -void mt7921_mac_set_timing(struct mt792x_phy *phy) -{ - s16 coverage_class = phy->coverage_class; - struct mt792x_dev *dev = phy->dev; - u32 val, reg_offset; - u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); - u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); - bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; - int sifs = is_2ghz ? 10 : 16, offset; - - if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) - return; - - mt76_set(dev, MT_ARB_SCR(0), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); - udelay(1); - - offset = 3 * coverage_class; - reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); - - mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset); - mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset); - mt76_wr(dev, MT_TMAC_ICR0(0), - FIELD_PREP(MT_IFS_EIFS, 360) | - FIELD_PREP(MT_IFS_RIFS, 2) | - FIELD_PREP(MT_IFS_SIFS, sifs) | - FIELD_PREP(MT_IFS_SLOT, phy->slottime)); - - if (phy->slottime < 20 || !is_2ghz) - val = MT7921_CFEND_RATE_DEFAULT; - else - val = MT7921_CFEND_RATE_11B; - - mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val); - mt76_clear(dev, MT_ARB_SCR(0), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); -} - static u8 mt7921_phy_get_nf(struct mt792x_phy *phy, int idx) { @@ -902,91 +861,6 @@ void mt7921_reset(struct mt76_dev *mdev) } EXPORT_SYMBOL_GPL(mt7921_reset); -void mt7921_mac_update_mib_stats(struct mt792x_phy *phy) -{ - struct mt76_mib_stats *mib = &phy->mib; - struct mt792x_dev *dev = phy->dev; - int i, aggr0 = 0, aggr1; - u32 val; - - mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0), - MT_MIB_SDR3_FCS_ERR_MASK); - mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0), - MT_MIB_ACK_FAIL_COUNT_MASK); - mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0), - MT_MIB_BA_FAIL_COUNT_MASK); - mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0), - MT_MIB_RTS_COUNT_MASK); - mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), - MT_MIB_RTS_FAIL_COUNT_MASK); - - mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0)); - mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0)); - mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0)); - - val = mt76_rr(dev, MT_MIB_SDR32(0)); - mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val); - mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val); - - val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0)); - mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val); - mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val); - - val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0)); - mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val); - mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val); - mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val); - mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val); - - mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0)); - mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0)); - mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0)); - mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0)); - - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { - val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); - mib->tx_amsdu[i] += val; - mib->tx_amsdu_cnt += val; - } - - for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { - u32 val2; - - val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); - val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); - - phy->mt76->aggr_stats[aggr0++] += val & 0xffff; - phy->mt76->aggr_stats[aggr0++] += val >> 16; - phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff; - phy->mt76->aggr_stats[aggr1++] += val2 >> 16; - } -} - -void mt7921_mac_work(struct work_struct *work) -{ - struct mt792x_phy *phy; - struct mt76_phy *mphy; - - mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, - mac_work.work); - phy = mphy->priv; - - mt792x_mutex_acquire(phy->dev); - - mt76_update_survey(mphy); - if (++mphy->mac_work_count == 2) { - mphy->mac_work_count = 0; - - mt7921_mac_update_mib_stats(phy); - } - - mt792x_mutex_release(phy->dev); - - mt76_tx_status_check(mphy->dev, false); - ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); -} - void mt7921_pm_wake_work(struct work_struct *work) { struct mt792x_dev *dev; @@ -1013,7 +887,7 @@ void mt7921_pm_wake_work(struct work_struct *work) } if (test_bit(MT76_STATE_RUNNING, &mphy->state)) ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); } ieee80211_wake_queues(mphy->hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 7213718ae399..223968807516 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -244,7 +244,7 @@ int __mt7921_start(struct mt792x_phy *phy) set_bit(MT76_STATE_RUNNING, &mphy->state); ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); return 0; } @@ -252,7 +252,7 @@ EXPORT_SYMBOL_GPL(__mt7921_start); static int mt7921_start(struct ieee80211_hw *hw) { - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int err; mt792x_mutex_acquire(phy->dev); @@ -265,7 +265,7 @@ static int mt7921_start(struct ieee80211_hw *hw) void mt7921_stop(struct ieee80211_hw *hw) { struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -281,19 +281,19 @@ void mt7921_stop(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(mt7921_stop); -static int mt7921_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int +mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt76_txq *mtxq; int idx, ret = 0; mt792x_mutex_acquire(dev); mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) { + if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { ret = -ENOSPC; goto out; } @@ -311,7 +311,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - idx = MT7921_WTBL_RESERVED - mvif->mt76.idx; + idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; @@ -338,33 +338,6 @@ out: return ret; } -static void mt7921_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_sta *msta = &mvif->sta; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); - int idx = msta->wcid.idx; - - mt792x_mutex_acquire(dev); - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); - - rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - - dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); - phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); - mt792x_mutex_release(dev); - - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); - - mt76_packet_id_flush(&dev->mt76, &msta->wcid); -} - static void mt7921_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { @@ -392,13 +365,6 @@ void mt7921_roc_work(struct work_struct *work) ieee80211_remain_on_channel_expired(phy->mt76->hw); } -void mt7921_roc_timer(struct timer_list *timer) -{ - struct mt792x_phy *phy = from_timer(phy, timer, roc_timer); - - ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); -} - static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) { int err = 0; @@ -451,7 +417,7 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, enum ieee80211_roc_type type) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int err; mt792x_mutex_acquire(phy->dev); @@ -465,7 +431,7 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); return mt7921_abort_roc(phy, mvif); } @@ -486,7 +452,7 @@ static int mt7921_set_channel(struct mt792x_phy *phy) if (ret) goto out; - mt7921_mac_set_timing(phy); + mt792x_mac_set_timeing(phy); mt7921_mac_reset_counters(phy); phy->noise = 0; @@ -497,7 +463,7 @@ out: mt76_worker_schedule(&dev->mt76.tx_worker); ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); return ret; } @@ -631,7 +597,7 @@ void mt7921_set_runtime_pm(struct mt792x_dev *dev) static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -662,20 +628,6 @@ out: return ret; } -static int -mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - unsigned int link_id, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - - /* no need to update right away, we'll get BSS_CHANGED_QOS */ - queue = mt76_connac_lmac_mapping(queue); - mvif->queue_params[queue] = *params; - - return 0; -} - static void mt7921_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -710,7 +662,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u64 changed) { - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt792x_dev *dev = mt792x_hw_dev(hw); mt792x_mutex_acquire(dev); @@ -720,7 +672,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (slottime != phy->slottime) { phy->slottime = slottime; - mt7921_mac_set_timing(phy); + mt792x_mac_set_timeing(phy); } } @@ -760,7 +712,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int ret, idx; - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); if (idx < 0) return -ENOSPC; @@ -851,60 +803,6 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove); -void mt7921_tx_worker(struct mt76_worker *w) -{ - struct mt792x_dev *dev = container_of(w, struct mt792x_dev, - mt76.tx_worker); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return; - } - - mt76_txq_schedule_all(&dev->mphy); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); -} - -static void mt7921_tx(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt76_phy *mphy = hw->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - int qid; - - if (control->sta) { - struct mt792x_sta *sta; - - sta = (struct mt792x_sta *)control->sta->drv_priv; - wcid = &sta->wcid; - } - - if (vif && !control->sta) { - struct mt792x_vif *mvif; - - mvif = (struct mt792x_vif *)vif->drv_priv; - wcid = &mvif->sta.wcid; - } - - if (mt76_connac_pm_ref(mphy, &dev->pm)) { - mt76_tx(mphy, control->sta, wcid, skb); - mt76_connac_pm_unref(mphy, &dev->pm); - return; - } - - qid = skb_get_queue_mapping(skb); - if (qid >= MT_TXQ_PSD) { - qid = IEEE80211_AC_BE; - skb_set_queue_mapping(skb, qid); - } - - mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb); -} - static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { struct mt792x_dev *dev = mt792x_hw_dev(hw); @@ -990,277 +888,6 @@ static int mt7921_sta_state(struct ieee80211_hw *hw, return mt76_sta_state(hw, vif, sta, old_state, new_state); } -static int -mt7921_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt76_mib_stats *mib = &phy->mib; - - mt792x_mutex_acquire(phy->dev); - - stats->dot11RTSSuccessCount = mib->rts_cnt; - stats->dot11RTSFailureCount = mib->rts_retries_cnt; - stats->dot11FCSErrorCount = mib->fcs_err_cnt; - stats->dot11ACKFailureCount = mib->ack_fail_cnt; - - mt792x_mutex_release(phy->dev); - - return 0; -} - -static const char mt7921_gstrings_stats[][ETH_GSTRING_LEN] = { - /* tx counters */ - "tx_ampdu_cnt", - "tx_mpdu_attempts", - "tx_mpdu_success", - "tx_pkt_ebf_cnt", - "tx_pkt_ibf_cnt", - "tx_ampdu_len:0-1", - "tx_ampdu_len:2-10", - "tx_ampdu_len:11-19", - "tx_ampdu_len:20-28", - "tx_ampdu_len:29-37", - "tx_ampdu_len:38-46", - "tx_ampdu_len:47-55", - "tx_ampdu_len:56-79", - "tx_ampdu_len:80-103", - "tx_ampdu_len:104-127", - "tx_ampdu_len:128-151", - "tx_ampdu_len:152-175", - "tx_ampdu_len:176-199", - "tx_ampdu_len:200-223", - "tx_ampdu_len:224-247", - "ba_miss_count", - "tx_beamformer_ppdu_iBF", - "tx_beamformer_ppdu_eBF", - "tx_beamformer_rx_feedback_all", - "tx_beamformer_rx_feedback_he", - "tx_beamformer_rx_feedback_vht", - "tx_beamformer_rx_feedback_ht", - "tx_msdu_pack_1", - "tx_msdu_pack_2", - "tx_msdu_pack_3", - "tx_msdu_pack_4", - "tx_msdu_pack_5", - "tx_msdu_pack_6", - "tx_msdu_pack_7", - "tx_msdu_pack_8", - /* rx counters */ - "rx_mpdu_cnt", - "rx_ampdu_cnt", - "rx_ampdu_bytes_cnt", - "rx_ba_cnt", - /* per vif counters */ - "v_tx_mode_cck", - "v_tx_mode_ofdm", - "v_tx_mode_ht", - "v_tx_mode_ht_gf", - "v_tx_mode_vht", - "v_tx_mode_he_su", - "v_tx_mode_he_ext_su", - "v_tx_mode_he_tb", - "v_tx_mode_he_mu", - "v_tx_bw_20", - "v_tx_bw_40", - "v_tx_bw_80", - "v_tx_bw_160", - "v_tx_mcs_0", - "v_tx_mcs_1", - "v_tx_mcs_2", - "v_tx_mcs_3", - "v_tx_mcs_4", - "v_tx_mcs_5", - "v_tx_mcs_6", - "v_tx_mcs_7", - "v_tx_mcs_8", - "v_tx_mcs_9", - "v_tx_mcs_10", - "v_tx_mcs_11", - "v_tx_nss_1", - "v_tx_nss_2", - "v_tx_nss_3", - "v_tx_nss_4", -}; - -static void -mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 sset, u8 *data) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - if (sset != ETH_SS_STATS) - return; - - memcpy(data, *mt7921_gstrings_stats, sizeof(mt7921_gstrings_stats)); - - if (mt76_is_sdio(&dev->mt76)) - return; - - data += sizeof(mt7921_gstrings_stats); - page_pool_ethtool_stats_get_strings(data); -} - -static int -mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int sset) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - if (sset != ETH_SS_STATS) - return 0; - - if (mt76_is_sdio(&dev->mt76)) - return ARRAY_SIZE(mt7921_gstrings_stats); - - return ARRAY_SIZE(mt7921_gstrings_stats) + - page_pool_ethtool_stats_get_count(); -} - -static void -mt7921_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) -{ - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct mt76_ethtool_worker_info *wi = wi_data; - - if (msta->vif->mt76.idx != wi->idx) - return; - - mt76_ethtool_worker(wi, &msta->wcid.stats, false); -} - -static -void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ethtool_stats *stats, u64 *data) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); - struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt792x_dev *dev = phy->dev; - struct mt76_mib_stats *mib = &phy->mib; - struct mt76_ethtool_worker_info wi = { - .data = data, - .idx = mvif->mt76.idx, - }; - int i, ei = 0; - - mt792x_mutex_acquire(dev); - - mt7921_mac_update_mib_stats(phy); - - data[ei++] = mib->tx_ampdu_cnt; - data[ei++] = mib->tx_mpdu_attempts_cnt; - data[ei++] = mib->tx_mpdu_success_cnt; - data[ei++] = mib->tx_pkt_ebf_cnt; - data[ei++] = mib->tx_pkt_ibf_cnt; - - /* Tx ampdu stat */ - for (i = 0; i < 15; i++) - data[ei++] = phy->mt76->aggr_stats[i]; - - data[ei++] = phy->mib.ba_miss_cnt; - - /* Tx Beamformer monitor */ - data[ei++] = mib->tx_bf_ibf_ppdu_cnt; - data[ei++] = mib->tx_bf_ebf_ppdu_cnt; - - /* Tx Beamformer Rx feedback monitor */ - data[ei++] = mib->tx_bf_rx_fb_all_cnt; - data[ei++] = mib->tx_bf_rx_fb_he_cnt; - data[ei++] = mib->tx_bf_rx_fb_vht_cnt; - data[ei++] = mib->tx_bf_rx_fb_ht_cnt; - - /* Tx amsdu info (pack-count histogram) */ - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) - data[ei++] = mib->tx_amsdu[i]; - - /* rx counters */ - data[ei++] = mib->rx_mpdu_cnt; - data[ei++] = mib->rx_ampdu_cnt; - data[ei++] = mib->rx_ampdu_bytes_cnt; - data[ei++] = mib->rx_ba_cnt; - - /* Add values for all stations owned by this vif */ - wi.initial_stat_idx = ei; - ieee80211_iterate_stations_atomic(hw, mt7921_ethtool_worker, &wi); - - mt792x_mutex_release(dev); - - if (!wi.sta_count) - return; - - ei += wi.worker_stat_count; - - if (!mt76_is_sdio(&dev->mt76)) { - mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); - stats_size += page_pool_ethtool_stats_get_count(); - } - - if (ei != stats_size) - dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, stats_size); -} - -static u64 -mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; - union { - u64 t64; - u32 t32[2]; - } tsf; - u16 n; - - mt792x_mutex_acquire(dev); - - n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; - /* TSF software read */ - mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE); - tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); - tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); - - mt792x_mutex_release(dev); - - return tsf.t64; -} - -static void -mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 timestamp) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; - union { - u64 t64; - u32 t32[2]; - } tsf = { .t64 = timestamp, }; - u16 n; - - mt792x_mutex_acquire(dev); - - n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; - mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); - mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]); - /* TSF software overwrite */ - mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); - - mt792x_mutex_release(dev); -} - -static void -mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) -{ - struct mt792x_phy *phy = mt7921_hw_phy(hw); - struct mt792x_dev *dev = phy->dev; - - mt792x_mutex_acquire(dev); - phy->coverage_class = max_t(s16, coverage_class, 0); - mt7921_mac_set_timing(phy); - mt792x_mutex_release(dev); -} - void mt7921_scan_work(struct work_struct *work) { struct mt792x_phy *phy; @@ -1360,7 +987,7 @@ static int mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int max_nss = hweight8(hw->wiphy->available_antennas_tx); if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) @@ -1382,49 +1009,12 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) return 0; } -static void mt7921_sta_statistics(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct station_info *sinfo) -{ - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct rate_info *txrate = &msta->wcid.rate; - - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; - } - sinfo->tx_failed = msta->wcid.stats.tx_failed; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - - sinfo->tx_retries = msta->wcid.stats.tx_retries; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); - - sinfo->txrate.flags = txrate->flags; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); - - sinfo->ack_signal = (s8)msta->ack_signal; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); - - sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); -} - #ifdef CONFIG_PM static int mt7921_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -1448,7 +1038,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, static int mt7921_resume(struct ieee80211_hw *hw) { struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); mt792x_mutex_acquire(dev); @@ -1459,21 +1049,13 @@ static int mt7921_resume(struct ieee80211_hw *hw) &dev->mphy); ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); mt792x_mutex_release(dev); return 0; } -static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt76_dev *mdev = &dev->mt76; - - device_set_wakeup_enable(mdev->dev, enabled); -} - static void mt7921_set_rekey_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) @@ -1486,15 +1068,6 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw, } #endif /* CONFIG_PM */ -static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy), - HZ / 2); -} - static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1588,7 +1161,7 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, return err; } - mt7921_init_acpi_sar_power(mt7921_hw_phy(hw), !sar); + mt7921_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); err = mt76_connac_mcu_set_rate_txpower(mphy); @@ -1631,7 +1204,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; @@ -1659,7 +1232,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; @@ -1709,7 +1282,7 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { - struct mt792x_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); mt792x_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, @@ -1718,36 +1291,6 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, mt792x_mutex_release(phy->dev); } -static int -mt7921_assign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf, - struct ieee80211_chanctx_conf *ctx) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - mutex_lock(&dev->mt76.mutex); - mvif->ctx = ctx; - mutex_unlock(&dev->mt76.mutex); - - return 0; -} - -static void -mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf, - struct ieee80211_chanctx_conf *ctx) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - mutex_lock(&dev->mt76.mutex); - mvif->ctx = NULL; - mutex_unlock(&dev->mt76.mutex); -} - static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info) @@ -1773,13 +1316,13 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, } const struct ieee80211_ops mt7921_ops = { - .tx = mt7921_tx, + .tx = mt792x_tx, .start = mt7921_start, .stop = mt7921_stop, .add_interface = mt7921_add_interface, - .remove_interface = mt7921_remove_interface, + .remove_interface = mt792x_remove_interface, .config = mt7921_config, - .conf_tx = mt7921_conf_tx, + .conf_tx = mt792x_conf_tx, .configure_filter = mt7921_configure_filter, .bss_info_changed = mt7921_bss_info_changed, .start_ap = mt7921_start_ap, @@ -1797,19 +1340,19 @@ const struct ieee80211_ops mt7921_ops = { .release_buffered_frames = mt76_release_buffered_frames, .channel_switch_beacon = mt7921_channel_switch_beacon, .get_txpower = mt76_get_txpower, - .get_stats = mt7921_get_stats, - .get_et_sset_count = mt7921_get_et_sset_count, - .get_et_strings = mt7921_get_et_strings, - .get_et_stats = mt7921_get_et_stats, - .get_tsf = mt7921_get_tsf, - .set_tsf = mt7921_set_tsf, + .get_stats = mt792x_get_stats, + .get_et_sset_count = mt792x_get_et_sset_count, + .get_et_strings = mt792x_get_et_strings, + .get_et_stats = mt792x_get_et_stats, + .get_tsf = mt792x_get_tsf, + .set_tsf = mt792x_set_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, .set_antenna = mt7921_set_antenna, - .set_coverage_class = mt7921_set_coverage_class, + .set_coverage_class = mt792x_set_coverage_class, .hw_scan = mt7921_hw_scan, .cancel_hw_scan = mt7921_cancel_hw_scan, - .sta_statistics = mt7921_sta_statistics, + .sta_statistics = mt792x_sta_statistics, .sched_scan_start = mt7921_start_sched_scan, .sched_scan_stop = mt7921_stop_sched_scan, CFG80211_TESTMODE_CMD(mt7921_testmode_cmd) @@ -1817,18 +1360,18 @@ const struct ieee80211_ops mt7921_ops = { #ifdef CONFIG_PM .suspend = mt7921_suspend, .resume = mt7921_resume, - .set_wakeup = mt7921_set_wakeup, + .set_wakeup = mt792x_set_wakeup, .set_rekey_data = mt7921_set_rekey_data, #endif /* CONFIG_PM */ - .flush = mt7921_flush, + .flush = mt792x_flush, .set_sar_specs = mt7921_set_sar_specs, .remain_on_channel = mt7921_remain_on_channel, .cancel_remain_on_channel = mt7921_cancel_remain_on_channel, .add_chanctx = mt7921_add_chanctx, .remove_chanctx = mt7921_remove_chanctx, .change_chanctx = mt7921_change_chanctx, - .assign_vif_chanctx = mt7921_assign_vif_chanctx, - .unassign_vif_chanctx = mt7921_unassign_vif_chanctx, + .assign_vif_chanctx = mt792x_assign_vif_chanctx, + .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, .mgd_prepare_tx = mt7921_mgd_prepare_tx, .mgd_complete_tx = mt7921_mgd_complete_tx, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index db3394ba4e45..3dd9ff5e466b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -4,9 +4,9 @@ #include #include #include "mt7921.h" -#include "mt7921_trace.h" #include "mcu.h" #include "../mt76_connac2_mac.h" +#include "../mt792x_trace.h" #define MT_STA_BFER BIT(0) #define MT_STA_BFEE BIT(1) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index ad18fcc4a7b0..4722952bb846 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -8,15 +8,8 @@ #include "regs.h" #include "acpi_sar.h" -#define MT7921_MAX_INTERFACES 4 -#define MT7921_WTBL_SIZE 20 -#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1) -#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \ - MT7921_MAX_INTERFACES) - #define MT7921_PM_TIMEOUT (HZ / 12) #define MT7921_HW_SCAN_TIMEOUT (HZ / 10) -#define MT7921_WATCHDOG_TIME (HZ / 4) #define MT7921_TX_RING_SIZE 2048 #define MT7921_TX_MCU_RING_SIZE 256 @@ -43,9 +36,6 @@ #define MT7921_EEPROM_BLOCK_SIZE 16 -#define MT7921_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ -#define MT7921_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ - #define MT7921_SKU_RATE_NUM 161 #define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM #define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1) @@ -208,14 +198,6 @@ struct mt7921_txpwr { } data[TXPWR_MAX_NUM]; }; -static inline struct mt792x_phy * -mt7921_hw_phy(struct ieee80211_hw *hw) -{ - struct mt76_phy *phy = hw->priv; - - return phy->priv; -} - extern const struct ieee80211_ops mt7921_ops; u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); @@ -300,25 +282,21 @@ mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt792x_dev *dev); -bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); void mt7921_mac_reset_counters(struct mt792x_phy *phy); -void mt7921_mac_set_timing(struct mt792x_phy *phy); +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void mt7921_mac_work(struct work_struct *work); void mt7921_mac_reset_work(struct work_struct *work); -void mt7921_mac_update_mib_stats(struct mt792x_phy *phy); void mt7921_reset(struct mt76_dev *mdev); int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7921_tx_worker(struct mt76_worker *w); bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); @@ -338,7 +316,6 @@ int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, bool enable); void mt7921_scan_work(struct work_struct *work); void mt7921_roc_work(struct work_struct *work); -void mt7921_roc_timer(struct timer_list *timer); int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h deleted file mode 100644 index 9426fda69c30..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* - * Copyright (C) 2021 Lorenzo Bianconi - */ - -#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define __MT7921_TRACE_H - -#include -#include "mt7921.h" - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM mt7921 - -#define MAXNAME 32 -#define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ - wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) -#define DEV_PR_FMT "%s" -#define DEV_PR_ARG __entry->wiphy_name -#define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready" - -TRACE_EVENT(lp_event, - TP_PROTO(struct mt792x_dev *dev, u8 lp_state), - - TP_ARGS(dev, lp_state), - - TP_STRUCT__entry( - DEV_ENTRY - __field(u8, lp_state) - ), - - TP_fast_assign( - DEV_ASSIGN; - __entry->lp_state = lp_state; - ), - - TP_printk( - DEV_PR_FMT " %s", - DEV_PR_ARG, LP_STATE_PR_ARG - ) -); - -#endif - -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE mt7921_trace - -#include diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index fefc10539586..c5ca1b931584 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -93,4 +93,8 @@ #define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) #define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 360de6a0de2b..310eeca024ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -23,7 +23,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, /* We just return in case firmware assertion to avoid blocking the * common workqueue to run, for example, the coredump work might be - * blocked by mt7921_mac_work that is excuting register access via sdio + * blocked by mt792x_mac_work that is excuting register access via sdio * bus. */ if (dev->fw_assert) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c deleted file mode 100644 index 4dc3c7b89ebd..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: ISC -/* - * Copyright (C) 2021 Lorenzo Bianconi - */ - -#include - -#ifndef __CHECKER__ -#define CREATE_TRACE_POINTS -#include "mt7921_trace.h" - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 9c724bc156af..83236a6c300e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -9,6 +9,19 @@ #include "mt76_connac_mcu.h" +#define MT792x_MAX_INTERFACES 4 +#define MT792x_WTBL_SIZE 20 +#define MT792x_WTBL_RESERVED (MT792x_WTBL_SIZE - 1) +#define MT792x_WTBL_STA (MT792x_WTBL_RESERVED - MT792x_MAX_INTERFACES) + +#define MT792x_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +#define MT792x_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + +/* NOTE: used to map mt76_rates. idx may change if firmware expands table */ +#define MT792x_BASIC_RATES_TBL 11 + +#define MT792x_WATCHDOG_TIME (HZ / 4) + struct mt792x_vif; struct mt792x_sta; @@ -134,9 +147,57 @@ mt792x_hw_dev(struct ieee80211_hw *hw) return container_of(phy->dev, struct mt792x_dev, mt76); } +static inline struct mt792x_phy * +mt792x_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + #define mt792x_mutex_acquire(dev) \ mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) #define mt792x_mutex_release(dev) \ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) +void mt792x_mac_update_mib_stats(struct mt792x_phy *phy); +void mt792x_mac_set_timeing(struct mt792x_phy *phy); +void mt792x_mac_work(struct work_struct *work); +void mt792x_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb); +int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params); +int mt792x_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats); +u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 timestamp); +void mt792x_tx_worker(struct mt76_worker *w); +void mt792x_roc_timer(struct timer_list *timer); +void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx); +void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx); +void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled); +void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 sset, u8 *data); +int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int sset); +void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data); +void mt792x_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct station_info *sinfo); +void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); + #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c new file mode 100644 index 000000000000..fa648b133397 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include + +#include "mt792x.h" +#include "mt792x_regs.h" + +void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + int qid; + + if (control->sta) { + struct mt792x_sta *sta; + + sta = (struct mt792x_sta *)control->sta->drv_priv; + wcid = &sta->wcid; + } + + if (vif && !control->sta) { + struct mt792x_vif *mvif; + + mvif = (struct mt792x_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + + if (mt76_connac_pm_ref(mphy, &dev->pm)) { + mt76_tx(mphy, control->sta, wcid, skb); + mt76_connac_pm_unref(mphy, &dev->pm); + return; + } + + qid = skb_get_queue_mapping(skb); + if (qid >= MT_TXQ_PSD) { + qid = IEEE80211_AC_BE; + skb_set_queue_mapping(skb, qid); + } + + mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb); +} +EXPORT_SYMBOL_GPL(mt792x_tx); + +void mt792x_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = &mvif->sta; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int idx = msta->wcid.idx; + + mt792x_mutex_acquire(dev); + mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); + mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); + phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); + mt792x_mutex_release(dev); + + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + mt76_packet_id_flush(&dev->mt76, &msta->wcid); +} +EXPORT_SYMBOL_GPL(mt792x_remove_interface); + +int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + /* no need to update right away, we'll get BSS_CHANGED_QOS */ + queue = mt76_connac_lmac_mapping(queue); + mvif->queue_params[queue] = *params; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_conf_tx); + +int mt792x_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt76_mib_stats *mib = &phy->mib; + + mt792x_mutex_acquire(phy->dev); + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + mt792x_mutex_release(phy->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_get_stats); + +u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u8 omac_idx = mvif->mt76.omac_idx; + union { + u64 t64; + u32 t32[2]; + } tsf; + u16 n; + + mt792x_mutex_acquire(dev); + + n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; + /* TSF software read */ + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE); + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); + + mt792x_mutex_release(dev); + + return tsf.t64; +} +EXPORT_SYMBOL_GPL(mt792x_get_tsf); + +void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 timestamp) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u8 omac_idx = mvif->mt76.omac_idx; + union { + u64 t64; + u32 t32[2]; + } tsf = { .t64 = timestamp, }; + u16 n; + + mt792x_mutex_acquire(dev); + + n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; + mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); + mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]); + /* TSF software overwrite */ + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); + + mt792x_mutex_release(dev); +} +EXPORT_SYMBOL_GPL(mt792x_set_tsf); + +void mt792x_tx_worker(struct mt76_worker *w) +{ + struct mt792x_dev *dev = container_of(w, struct mt792x_dev, + mt76.tx_worker); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return; + } + + mt76_txq_schedule_all(&dev->mphy); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); +} +EXPORT_SYMBOL_GPL(mt792x_tx_worker); + +void mt792x_roc_timer(struct timer_list *timer) +{ + struct mt792x_phy *phy = from_timer(phy, timer, roc_timer); + + ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); +} +EXPORT_SYMBOL_GPL(mt792x_roc_timer); + +void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + wait_event_timeout(dev->mt76.tx_wait, + !mt76_has_tx_pending(&dev->mphy), HZ / 2); +} +EXPORT_SYMBOL_GPL(mt792x_flush); + +int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mvif->ctx = ctx; + mutex_unlock(&dev->mt76.mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_assign_vif_chanctx); + +void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mvif->ctx = NULL; + mutex_unlock(&dev->mt76.mutex); +} +EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx); + +void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_dev *mdev = &dev->mt76; + + device_set_wakeup_enable(mdev->dev, enabled); +} +EXPORT_SYMBOL_GPL(mt792x_set_wakeup); + +static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = { + /* tx counters */ + "tx_ampdu_cnt", + "tx_mpdu_attempts", + "tx_mpdu_success", + "tx_pkt_ebf_cnt", + "tx_pkt_ibf_cnt", + "tx_ampdu_len:0-1", + "tx_ampdu_len:2-10", + "tx_ampdu_len:11-19", + "tx_ampdu_len:20-28", + "tx_ampdu_len:29-37", + "tx_ampdu_len:38-46", + "tx_ampdu_len:47-55", + "tx_ampdu_len:56-79", + "tx_ampdu_len:80-103", + "tx_ampdu_len:104-127", + "tx_ampdu_len:128-151", + "tx_ampdu_len:152-175", + "tx_ampdu_len:176-199", + "tx_ampdu_len:200-223", + "tx_ampdu_len:224-247", + "ba_miss_count", + "tx_beamformer_ppdu_iBF", + "tx_beamformer_ppdu_eBF", + "tx_beamformer_rx_feedback_all", + "tx_beamformer_rx_feedback_he", + "tx_beamformer_rx_feedback_vht", + "tx_beamformer_rx_feedback_ht", + "tx_msdu_pack_1", + "tx_msdu_pack_2", + "tx_msdu_pack_3", + "tx_msdu_pack_4", + "tx_msdu_pack_5", + "tx_msdu_pack_6", + "tx_msdu_pack_7", + "tx_msdu_pack_8", + /* rx counters */ + "rx_mpdu_cnt", + "rx_ampdu_cnt", + "rx_ampdu_bytes_cnt", + "rx_ba_cnt", + /* per vif counters */ + "v_tx_mode_cck", + "v_tx_mode_ofdm", + "v_tx_mode_ht", + "v_tx_mode_ht_gf", + "v_tx_mode_vht", + "v_tx_mode_he_su", + "v_tx_mode_he_ext_su", + "v_tx_mode_he_tb", + "v_tx_mode_he_mu", + "v_tx_mode_eht_su", + "v_tx_mode_eht_trig", + "v_tx_mode_eht_mu", + "v_tx_bw_20", + "v_tx_bw_40", + "v_tx_bw_80", + "v_tx_bw_160", + "v_tx_mcs_0", + "v_tx_mcs_1", + "v_tx_mcs_2", + "v_tx_mcs_3", + "v_tx_mcs_4", + "v_tx_mcs_5", + "v_tx_mcs_6", + "v_tx_mcs_7", + "v_tx_mcs_8", + "v_tx_mcs_9", + "v_tx_mcs_10", + "v_tx_mcs_11", + "v_tx_mcs_12", + "v_tx_mcs_13", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", +}; + +void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset != ETH_SS_STATS) + return; + + memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats)); + + data += sizeof(mt792x_gstrings_stats); + page_pool_ethtool_stats_get_strings(data); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_strings); + +int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int sset) +{ + if (sset != ETH_SS_STATS) + return 0; + + return ARRAY_SIZE(mt792x_gstrings_stats) + + page_pool_ethtool_stats_get_count(); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_sset_count); + +static void +mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt76_ethtool_worker_info *wi = wi_data; + + if (msta->vif->mt76.idx != wi->idx) + return; + + mt76_ethtool_worker(wi, &msta->wcid.stats, true); +} + +void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + int stats_size = ARRAY_SIZE(mt792x_gstrings_stats); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + struct mt76_mib_stats *mib = &phy->mib; + struct mt76_ethtool_worker_info wi = { + .data = data, + .idx = mvif->mt76.idx, + }; + int i, ei = 0; + + mt792x_mutex_acquire(dev); + + mt792x_mac_update_mib_stats(phy); + + data[ei++] = mib->tx_ampdu_cnt; + data[ei++] = mib->tx_mpdu_attempts_cnt; + data[ei++] = mib->tx_mpdu_success_cnt; + data[ei++] = mib->tx_pkt_ebf_cnt; + data[ei++] = mib->tx_pkt_ibf_cnt; + + /* Tx ampdu stat */ + for (i = 0; i < 15; i++) + data[ei++] = phy->mt76->aggr_stats[i]; + + data[ei++] = phy->mib.ba_miss_cnt; + + /* Tx Beamformer monitor */ + data[ei++] = mib->tx_bf_ibf_ppdu_cnt; + data[ei++] = mib->tx_bf_ebf_ppdu_cnt; + + /* Tx Beamformer Rx feedback monitor */ + data[ei++] = mib->tx_bf_rx_fb_all_cnt; + data[ei++] = mib->tx_bf_rx_fb_he_cnt; + data[ei++] = mib->tx_bf_rx_fb_vht_cnt; + data[ei++] = mib->tx_bf_rx_fb_ht_cnt; + + /* Tx amsdu info (pack-count histogram) */ + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) + data[ei++] = mib->tx_amsdu[i]; + + /* rx counters */ + data[ei++] = mib->rx_mpdu_cnt; + data[ei++] = mib->rx_ampdu_cnt; + data[ei++] = mib->rx_ampdu_bytes_cnt; + data[ei++] = mib->rx_ba_cnt; + + /* Add values for all stations owned by this vif */ + wi.initial_stat_idx = ei; + ieee80211_iterate_stations_atomic(hw, mt792x_ethtool_worker, &wi); + + mt792x_mutex_release(dev); + + if (!wi.sta_count) + return; + + ei += wi.worker_stat_count; + + mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); + stats_size += page_pool_ethtool_stats_get_count(); + + if (ei != stats_size) + dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, + stats_size); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_stats); + +void mt792x_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct station_info *sinfo) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct rate_info *txrate = &msta->wcid.rate; + + if (!txrate->legacy && !txrate->flags) + return; + + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + + sinfo->ack_signal = (s8)msta->ack_signal; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); + + sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); +} +EXPORT_SYMBOL_GPL(mt792x_sta_statistics); + +void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + + mt792x_mutex_acquire(dev); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt792x_mac_set_timeing(phy); + + mt792x_mutex_release(dev); +} +EXPORT_SYMBOL_GPL(mt792x_set_coverage_class); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Lorenzo Bianconi "); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c new file mode 100644 index 000000000000..862cca816aae --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include + +#include "mt792x.h" +#include "mt792x_regs.h" + +void mt792x_mac_work(struct work_struct *work) +{ + struct mt792x_phy *phy; + struct mt76_phy *mphy; + + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv; + + mt792x_mutex_acquire(phy->dev); + + mt76_update_survey(mphy); + if (++mphy->mac_work_count == 2) { + mphy->mac_work_count = 0; + + mt792x_mac_update_mib_stats(phy); + } + + mt792x_mutex_release(phy->dev); + + mt76_tx_status_check(mphy->dev, false); + ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, + MT792x_WATCHDOG_TIME); +} +EXPORT_SYMBOL_GPL(mt792x_mac_work); + +void mt792x_mac_set_timeing(struct mt792x_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt792x_dev *dev = phy->dev; + u32 val, reg_offset; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); + bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; + int sifs = is_2ghz ? 10 : 16, offset; + + if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) + return; + + mt76_set(dev, MT_ARB_SCR(0), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + + mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset); + mt76_wr(dev, MT_TMAC_ICR0(0), + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20 || !is_2ghz) + val = MT792x_CFEND_RATE_DEFAULT; + else + val = MT792x_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR(0), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); +} +EXPORT_SYMBOL_GPL(mt792x_mac_set_timeing); + +void mt792x_mac_update_mib_stats(struct mt792x_phy *phy) +{ + struct mt76_mib_stats *mib = &phy->mib; + struct mt792x_dev *dev = phy->dev; + int i, aggr0 = 0, aggr1; + u32 val; + + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0), + MT_MIB_SDR3_FCS_ERR_MASK); + mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0), + MT_MIB_ACK_FAIL_COUNT_MASK); + mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0), + MT_MIB_BA_FAIL_COUNT_MASK); + mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0), + MT_MIB_RTS_COUNT_MASK); + mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), + MT_MIB_RTS_FAIL_COUNT_MASK); + + mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0)); + mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0)); + mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0)); + + val = mt76_rr(dev, MT_MIB_SDR32(0)); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val); + + val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0)); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val); + + val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0)); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val); + + mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0)); + mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0)); + mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0)); + mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0)); + + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { + val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); + mib->tx_amsdu[i] += val; + mib->tx_amsdu_cnt += val; + } + + for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { + u32 val2; + + val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); + val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); + + phy->mt76->aggr_stats[aggr0++] += val & 0xffff; + phy->mt76->aggr_stats[aggr0++] += val >> 16; + phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff; + phy->mt76->aggr_stats[aggr1++] += val2 >> 16; + } +} +EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h index aa6a677427a4..5f2407fbf95f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -157,9 +157,6 @@ #define MT_WTBLON_TOP_BASE 0x820d4000 #define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) -#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) -#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) #define MT_WTBL_UPDATE_BUSY BIT(31) #define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0) diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_trace.c b/drivers/net/wireless/mediatek/mt76/mt792x_trace.c new file mode 100644 index 000000000000..b6f284fb929d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_trace.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2023 Lorenzo Bianconi + */ + +#include + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt792x_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(lp_event); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_trace.h b/drivers/net/wireless/mediatek/mt76/mt792x_trace.h new file mode 100644 index 000000000000..61f2aa260656 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_trace.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (C) 2023 Lorenzo Bianconi + */ + +#if !defined(__MT792X_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT792X_TRACE_H + +#include +#include "mt792x.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mt792x + +#define MAXNAME 32 +#define DEV_ENTRY __array(char, wiphy_name, 32) +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ + wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) +#define DEV_PR_FMT "%s" +#define DEV_PR_ARG __entry->wiphy_name +#define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready" + +TRACE_EVENT(lp_event, + TP_PROTO(struct mt792x_dev *dev, u8 lp_state), + + TP_ARGS(dev, lp_state), + + TP_STRUCT__entry( + DEV_ENTRY + __field(u8, lp_state) + ), + + TP_fast_assign( + DEV_ASSIGN; + __entry->lp_state = lp_state; + ), + + TP_printk( + DEV_PR_FMT " %s", + DEV_PR_ARG, LP_STATE_PR_ARG + ) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mt792x_trace + +#include -- cgit From 311f121c240967ad4add9e4b00fbd5204e9b93f7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:58 +0800 Subject: wifi: mt76: mt7921: move mac shared code in mt792x-lib module Reduce duplicated code moving mac shared code in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 170 +-------------------- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 - drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 6 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 20 +++ drivers/net/wireless/mediatek/mt76/mt792x_mac.c | 148 ++++++++++++++++++ 10 files changed, 187 insertions(+), 184 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 59920cffee6a..7d5211b99340 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -396,7 +396,7 @@ static int mt7921_chip_reset(void *data, u64 val) switch (val) { case 1: /* Reset wifisys directly. */ - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); break; default: /* Collect the core dump before reset wifisys. */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 40f006664ad7..70382194825a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -29,29 +29,6 @@ static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; } -static struct mt76_wcid *mt7921_rx_get_wcid(struct mt792x_dev *dev, - u16 idx, bool unicast) -{ - struct mt792x_sta *sta; - struct mt76_wcid *wcid; - - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) - return NULL; - - wcid = rcu_dereference(dev->mt76.wcid[idx]); - if (unicast || !wcid) - return wcid; - - if (!wcid->sta) - return NULL; - - sta = container_of(wcid, struct mt792x_sta, wcid); - if (!sta->vif) - return NULL; - - return &sta->vif->sta.wcid; -} - static void mt7921_mac_sta_poll(struct mt792x_dev *dev) { static const u8 ac_to_tid[] = { @@ -184,52 +161,6 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) } } -static void -mt7921_get_status_freq_info(struct mt792x_dev *dev, struct mt76_phy *mphy, - struct mt76_rx_status *status, u8 chfreq) -{ - if (chfreq > 180) { - status->band = NL80211_BAND_6GHZ; - chfreq = (chfreq - 181) * 4 + 1; - } else if (chfreq > 14) { - status->band = NL80211_BAND_5GHZ; - } else { - status->band = NL80211_BAND_2GHZ; - } - status->freq = ieee80211_channel_to_frequency(chfreq, status->band); -} - -static void -mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct sk_buff *skb = priv; - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); - - if (status->signal > 0) - return; - - if (!ether_addr_equal(vif->addr, hdr->addr1)) - return; - - ewma_rssi_add(&mvif->rssi, -status->signal); -} - -static void -mt7921_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); - - if (!ieee80211_is_assoc_resp(hdr->frame_control) && - !ieee80211_is_auth(hdr->frame_control)) - return; - - ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7921_mac_rssi_iter, skb); -} - static int mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) { @@ -276,7 +207,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); - status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); + status->wcid = mt792x_rx_get_wcid(dev, idx, unicast); if (status->wcid) { msta = container_of(status->wcid, struct mt792x_sta, wcid); @@ -287,7 +218,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->mt76.sta_poll_lock); } - mt7921_get_status_freq_info(dev, mphy, status, chfreq); + mt792x_get_status_freq_info(status, chfreq); switch (status->band) { case NL80211_BAND_5GHZ: @@ -496,7 +427,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_8023; } - mt7921_mac_assoc_rssi(dev, skb); + mt792x_mac_assoc_rssi(dev, skb); if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode); @@ -699,81 +630,6 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } EXPORT_SYMBOL_GPL(mt7921_queue_rx_skb); -void mt7921_mac_reset_counters(struct mt792x_phy *phy) -{ - struct mt792x_dev *dev = phy->dev; - int i; - - for (i = 0; i < 4; i++) { - mt76_rr(dev, MT_TX_AGG_CNT(0, i)); - mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); - } - - dev->mt76.phy.survey_time = ktime_get_boottime(); - memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); - - /* reset airtime counters */ - mt76_rr(dev, MT_MIB_SDR9(0)); - mt76_rr(dev, MT_MIB_SDR36(0)); - mt76_rr(dev, MT_MIB_SDR37(0)); - - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); -} - -static u8 -mt7921_phy_get_nf(struct mt792x_phy *phy, int idx) -{ - return 0; -} - -static void -mt7921_phy_update_channel(struct mt76_phy *mphy, int idx) -{ - struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); - struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; - struct mt76_channel_state *state; - u64 busy_time, tx_time, rx_time, obss_time; - int nf; - - busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), - MT_MIB_SDR9_BUSY_MASK); - tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), - MT_MIB_SDR36_TXTIME_MASK); - rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), - MT_MIB_SDR37_RXTIME_MASK); - obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), - MT_MIB_OBSSTIME_MASK); - - nf = mt7921_phy_get_nf(phy, idx); - if (!phy->noise) - phy->noise = nf << 4; - else if (nf) - phy->noise += nf - (phy->noise >> 4); - - state = mphy->chan_state; - state->cc_busy += busy_time; - state->cc_tx += tx_time; - state->cc_rx += rx_time + obss_time; - state->cc_bss_rx += rx_time; - state->noise = -(phy->noise >> 4); -} - -void mt7921_update_channel(struct mt76_phy *mphy) -{ - struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); - - if (mt76_connac_pm_wake(mphy, &dev->pm)) - return; - - mt7921_phy_update_channel(mphy, 0); - /* reset obss airtime */ - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); - - mt76_connac_power_save_sched(mphy, &dev->pm); -} -EXPORT_SYMBOL_GPL(mt7921_update_channel); - static void mt7921_vif_connect_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) @@ -843,24 +699,6 @@ void mt7921_mac_reset_work(struct work_struct *work) mt76_connac_power_save_sched(&dev->mt76.phy, pm); } -void mt7921_reset(struct mt76_dev *mdev) -{ - struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - struct mt76_connac_pm *pm = &dev->pm; - - if (!dev->hw_init_done) - return; - - if (dev->hw_full_reset) - return; - - if (pm->suspended) - return; - - queue_work(dev->mt76.wq, &dev->reset_work); -} -EXPORT_SYMBOL_GPL(mt7921_reset); - void mt7921_pm_wake_work(struct work_struct *work) { struct mt792x_dev *dev; @@ -975,7 +813,7 @@ void mt7921_coredump_work(struct work_struct *work) dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, GFP_KERNEL); - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); } /* usb_sdio */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 223968807516..73f29fed216f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -240,7 +240,7 @@ int __mt7921_start(struct mt792x_phy *phy) if (err) return err; - mt7921_mac_reset_counters(phy); + mt792x_mac_reset_counters(phy); set_bit(MT76_STATE_RUNNING, &mphy->state); ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, @@ -454,7 +454,7 @@ static int mt7921_set_channel(struct mt792x_phy *phy) mt792x_mac_set_timeing(phy); - mt7921_mac_reset_counters(phy); + mt792x_mac_reset_counters(phy); phy->noise = 0; out: diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 3dd9ff5e466b..ed02fa48841c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -25,7 +25,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, if (!skb) { dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", cmd, seq); - mt7921_reset(mdev); + mt792x_reset(mdev); return -ETIMEDOUT; } @@ -958,7 +958,7 @@ out: mutex_unlock(&pm->mutex); if (err) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -980,7 +980,7 @@ out: mutex_unlock(&pm->mutex); if (err) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 4722952bb846..31fa51b8695e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -282,7 +282,6 @@ mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt792x_dev *dev); -void mt7921_mac_reset_counters(struct mt792x_phy *phy); bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -291,7 +290,6 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_reset_work(struct work_struct *work); -void mt7921_reset(struct mt76_dev *mdev); int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, @@ -302,7 +300,6 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); void mt7921_stats_work(struct work_struct *work); void mt7921_set_stream_he_caps(struct mt792x_phy *phy); -void mt7921_update_channel(struct mt76_phy *mphy); int mt7921_init_debugfs(struct mt792x_dev *dev); int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 4227b5028a6f..67eaa6232a02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -245,7 +245,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; static const struct mt792x_hif_ops mt7921_pcie_ops = { .init_reset = mt7921e_init_reset, @@ -450,7 +450,7 @@ restore_suspend: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -500,7 +500,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index b438947c2bd8..f0117ac34594 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -102,7 +102,7 @@ static int mt7921s_probe(struct sdio_func *func, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; static const struct mt76_bus_ops mt7921s_ops = { .rr = mt76s_rr, @@ -269,7 +269,7 @@ restore_suspend: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -302,7 +302,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 9d54be3d3d03..3bf902cacd28 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -189,7 +189,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; static const struct mt792x_hif_ops hif_ops = { .mcu_init = mt7921u_mcu_init, @@ -322,7 +322,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -364,7 +364,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 83236a6c300e..f0f9fb3fd970 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -155,11 +155,31 @@ mt792x_hw_phy(struct ieee80211_hw *hw) return phy->priv; } +static inline void +mt792x_get_status_freq_info(struct mt76_rx_status *status, u8 chfreq) +{ + if (chfreq > 180) { + status->band = NL80211_BAND_6GHZ; + chfreq = (chfreq - 181) * 4 + 1; + } else if (chfreq > 14) { + status->band = NL80211_BAND_5GHZ; + } else { + status->band = NL80211_BAND_2GHZ; + } + status->freq = ieee80211_channel_to_frequency(chfreq, status->band); +} + #define mt792x_mutex_acquire(dev) \ mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) #define mt792x_mutex_release(dev) \ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) +void mt792x_reset(struct mt76_dev *mdev); +void mt792x_update_channel(struct mt76_phy *mphy); +void mt792x_mac_reset_counters(struct mt792x_phy *phy); +void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb); +struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, + bool unicast); void mt792x_mac_update_mib_stats(struct mt792x_phy *phy); void mt792x_mac_set_timeing(struct mt792x_phy *phy); void mt792x_mac_work(struct work_struct *work); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c index 862cca816aae..130b4352cf92 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -134,3 +134,151 @@ void mt792x_mac_update_mib_stats(struct mt792x_phy *phy) } } EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats); + +struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, + bool unicast) +{ + struct mt792x_sta *sta; + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + return NULL; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (unicast || !wcid) + return wcid; + + if (!wcid->sta) + return NULL; + + sta = container_of(wcid, struct mt792x_sta, wcid); + if (!sta->vif) + return NULL; + + return &sta->vif->sta.wcid; +} +EXPORT_SYMBOL_GPL(mt792x_rx_get_wcid); + +static void +mt792x_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct sk_buff *skb = priv; + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (status->signal > 0) + return; + + if (!ether_addr_equal(vif->addr, hdr->addr1)) + return; + + ewma_rssi_add(&mvif->rssi, -status->signal); +} + +void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (!ieee80211_is_assoc_resp(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) + return; + + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt792x_mac_rssi_iter, skb); +} +EXPORT_SYMBOL_GPL(mt792x_mac_assoc_rssi); + +void mt792x_mac_reset_counters(struct mt792x_phy *phy) +{ + struct mt792x_dev *dev = phy->dev; + int i; + + for (i = 0; i < 4; i++) { + mt76_rr(dev, MT_TX_AGG_CNT(0, i)); + mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); + } + + dev->mt76.phy.survey_time = ktime_get_boottime(); + memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); + + /* reset airtime counters */ + mt76_rr(dev, MT_MIB_SDR9(0)); + mt76_rr(dev, MT_MIB_SDR36(0)); + mt76_rr(dev, MT_MIB_SDR37(0)); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); +} +EXPORT_SYMBOL_GPL(mt792x_mac_reset_counters); + +static u8 +mt792x_phy_get_nf(struct mt792x_phy *phy, int idx) +{ + return 0; +} + +static void +mt792x_phy_update_channel(struct mt76_phy *mphy, int idx) +{ + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; + struct mt76_channel_state *state; + u64 busy_time, tx_time, rx_time, obss_time; + int nf; + + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), + MT_MIB_SDR9_BUSY_MASK); + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), + MT_MIB_SDR36_TXTIME_MASK); + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), + MT_MIB_SDR37_RXTIME_MASK); + obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), + MT_MIB_OBSSTIME_MASK); + + nf = mt792x_phy_get_nf(phy, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); + + state = mphy->chan_state; + state->cc_busy += busy_time; + state->cc_tx += tx_time; + state->cc_rx += rx_time + obss_time; + state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); +} + +void mt792x_update_channel(struct mt76_phy *mphy) +{ + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); + + if (mt76_connac_pm_wake(mphy, &dev->pm)) + return; + + mt792x_phy_update_channel(mphy, 0); + /* reset obss airtime */ + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); + mt76_connac_power_save_sched(mphy, &dev->pm); +} +EXPORT_SYMBOL_GPL(mt792x_update_channel); + +void mt792x_reset(struct mt76_dev *mdev) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt76_connac_pm *pm = &dev->pm; + + if (!dev->hw_init_done) + return; + + if (dev->hw_full_reset) + return; + + if (pm->suspended) + return; + + queue_work(dev->mt76.wq, &dev->reset_work); +} +EXPORT_SYMBOL_GPL(mt792x_reset); -- cgit From c693f2f068c0b21235994b7722bc635e854857a1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:05:59 +0800 Subject: wifi: mt76: mt7921: move dma shared code in mt792x-lib module Reduce duplicated code moving dma shared code in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 102 +-------------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 7 -- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 2 - drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 10 ++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 98 +++++++++++++++++++- drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 3 + 8 files changed, 119 insertions(+), 111 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 3c628962641b..9dcda35cdf73 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -25,24 +25,6 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) return 0; } -static int mt7921_poll_rx(struct napi_struct *napi, int budget) -{ - struct mt792x_dev *dev; - int done; - - dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - napi_complete(napi); - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return 0; - } - done = mt76_dma_rx_poll(napi, budget); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); - - return done; -} - static void mt7921_dma_prefetch(struct mt792x_dev *dev) { #define PREFETCH(base, depth) ((base) << 16 | (depth)) @@ -64,40 +46,6 @@ static void mt7921_dma_prefetch(struct mt792x_dev *dev) mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); } -static int mt7921_dma_disable(struct mt792x_dev *dev, bool force) -{ - /* disable WFDMA0 */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) - return -ETIMEDOUT; - - /* disable dmashdl */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - - if (force) { - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - } - - return 0; -} - static int mt7921_dma_enable(struct mt792x_dev *dev) { /* configure perfetch settings */ @@ -135,7 +83,7 @@ static int mt7921_dma_reset(struct mt792x_dev *dev, bool force) { int i, err; - err = mt7921_dma_disable(dev, force); + err = mt792x_dma_disable(dev, force); if (err) return err; @@ -154,19 +102,6 @@ static int mt7921_dma_reset(struct mt792x_dev *dev, bool force) return mt7921_dma_enable(dev); } -int mt7921_wfsys_reset(struct mt792x_dev *dev) -{ - mt76_clear(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B); - msleep(50); - mt76_set(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B); - - if (!__mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B, - WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500)) - return -ETIMEDOUT; - - return 0; -} - int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force) { int i, err; @@ -182,7 +117,7 @@ int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force) mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); if (force) { - err = mt7921_wfsys_reset(dev); + err = mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); if (err) return err; } @@ -202,7 +137,7 @@ int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev) int err; /* check if the wpdma must be reinitialized */ - if (mt7921_dma_need_reinit(dev)) { + if (mt792x_dma_need_reinit(dev)) { /* disable interrutpts */ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); @@ -227,7 +162,7 @@ int mt7921_dma_init(struct mt792x_dev *dev) mt76_dma_attach(&dev->mt76); - ret = mt7921_dma_disable(dev, true); + ret = mt792x_dma_disable(dev, true); if (ret) return ret; @@ -275,7 +210,7 @@ int mt7921_dma_init(struct mt792x_dev *dev) if (ret) return ret; - ret = mt76_init_queues(dev, mt7921_poll_rx); + ret = mt76_init_queues(dev, mt792x_poll_rx); if (ret < 0) return ret; @@ -285,30 +220,3 @@ int mt7921_dma_init(struct mt792x_dev *dev) return mt7921_dma_enable(dev); } - -void mt7921_dma_cleanup(struct mt792x_dev *dev) -{ - /* disable */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1); - - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_dma_cleanup(&dev->mt76); -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 31fa51b8695e..b8699c942b34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -208,7 +208,6 @@ void mt7921_unregister_device(struct mt792x_dev *dev); int mt7921_dma_init(struct mt792x_dev *dev); int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force); int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev); -void mt7921_dma_cleanup(struct mt792x_dev *dev); int mt7921_run_firmware(struct mt792x_dev *dev); int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); @@ -262,11 +261,6 @@ mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val) #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) -static inline bool mt7921_dma_need_reinit(struct mt792x_dev *dev) -{ - return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); -} - static inline void mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, int type) @@ -319,7 +313,6 @@ int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev); void mt7921_pm_wake_work(struct work_struct *work); void mt7921_pm_power_save_work(struct work_struct *work); void mt7921_coredump_work(struct work_struct *work); -int mt7921_wfsys_reset(struct mt792x_dev *dev); int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr); int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 67eaa6232a02..4d929cf8d854 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -117,8 +117,8 @@ static void mt7921e_unregister_device(struct mt792x_dev *dev) mt76_connac2_tx_token_put(&dev->mt76); __mt7921_mcu_drv_pmctrl(dev); - mt7921_dma_cleanup(dev); - mt7921_wfsys_reset(dev); + mt792x_dma_cleanup(dev); + mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); skb_queue_purge(&dev->mt76.mcu.res_q); tasklet_disable(&dev->mt76.irq_tasklet); @@ -337,7 +337,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - ret = mt7921_wfsys_reset(dev); + ret = mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); if (ret) goto err_free_dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index c5ca1b931584..083d655f82e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -87,8 +87,6 @@ #define MT_HIF_REMAP_BASE_L1 0x40000 #define MT_WFSYS_SW_RST_B 0x18000140 -#define WFSYS_SW_RST_B BIT(0) -#define WFSYS_SW_INIT_DONE BIT(4) #define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) #define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 3bf902cacd28..c7368cf676a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -349,7 +349,7 @@ static int mt7921u_resume(struct usb_interface *intf) msleep(20); } - if (reinit || mt7921_dma_need_reinit(dev)) { + if (reinit || mt792x_dma_need_reinit(dev)) { err = mt7921u_dma_init(dev, true); if (err) goto failed; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index f0f9fb3fd970..fa199cc05c60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -8,6 +8,7 @@ #include #include "mt76_connac_mcu.h" +#include "mt792x_regs.h" #define MT792x_MAX_INTERFACES 4 #define MT792x_WTBL_SIZE 20 @@ -169,6 +170,11 @@ mt792x_get_status_freq_info(struct mt76_rx_status *status, u8 chfreq) status->freq = ieee80211_channel_to_frequency(chfreq, status->band); } +static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev) +{ + return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + #define mt792x_mutex_acquire(dev) \ mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) #define mt792x_mutex_release(dev) \ @@ -219,5 +225,9 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo); void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); +void mt792x_dma_cleanup(struct mt792x_dev *dev); +int mt792x_dma_disable(struct mt792x_dev *dev, bool force); +int mt792x_poll_rx(struct napi_struct *napi, int budget); +int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr); #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index fa648b133397..b176ce53996e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -4,7 +4,7 @@ #include #include "mt792x.h" -#include "mt792x_regs.h" +#include "dma.h" void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) @@ -465,5 +465,101 @@ void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) } EXPORT_SYMBOL_GPL(mt792x_set_coverage_class); +int mt792x_dma_disable(struct mt792x_dev *dev, bool force) +{ + /* disable WFDMA0 */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) + return -ETIMEDOUT; + + /* disable dmashdl */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + if (force) { + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_dma_disable); + +void mt792x_dma_cleanup(struct mt792x_dev *dev) +{ + /* disable */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1); + + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_dma_cleanup(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792x_dma_cleanup); + +int mt792x_poll_rx(struct napi_struct *napi, int budget) +{ + struct mt792x_dev *dev; + int done; + + dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + done = mt76_dma_rx_poll(napi, budget); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); + + return done; +} +EXPORT_SYMBOL_GPL(mt792x_poll_rx); + +int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr) +{ + mt76_clear(dev, addr, WFSYS_SW_RST_B); + msleep(50); + mt76_set(dev, addr, WFSYS_SW_RST_B); + + if (!__mt76_poll_msec(&dev->mt76, addr, WFSYS_SW_INIT_DONE, + WFSYS_SW_INIT_DONE, 500)) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_wfsys_reset); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h index 5f2407fbf95f..9c6308ef4cb3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -454,4 +454,7 @@ #define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) #define MT_WF_SW_SER_DONE_SUSPEND BIT(7) +#define WFSYS_SW_RST_B BIT(0) +#define WFSYS_SW_INIT_DONE BIT(4) + #endif /* __MT792X_REGS_H */ -- cgit From 974e759c3fd99813bd2b537acb8bb936c5f2bae7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:06:00 +0800 Subject: wifi: mt76: mt7921: move debugfs shared code in mt792x-lib module Reduce duplicated code moving debugfs shared code in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 3 +- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 178 +-------------------- drivers/net/wireless/mediatek/mt76/mt792x.h | 6 + .../net/wireless/mediatek/mt76/mt792x_debugfs.c | 168 +++++++++++++++++++ 4 files changed, 183 insertions(+), 172 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index a20eebba04ba..a45853ab958f 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -31,7 +31,8 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o -mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o +mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \ + mt792x_debugfs.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 7d5211b99340..616b66a3fde2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -57,128 +57,7 @@ mt7921_fw_debug_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get, mt7921_fw_debug_set, "%lld\n"); -static void -mt7921_ampdu_stat_read_phy(struct mt792x_phy *phy, - struct seq_file *file) -{ - struct mt792x_dev *dev = file->private; - int bound[15], range[4], i; - - if (!phy) - return; - - mt792x_mac_update_mib_stats(phy); - - /* Tx ampdu stat */ - for (i = 0; i < ARRAY_SIZE(range); i++) - range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); - - for (i = 0; i < ARRAY_SIZE(bound); i++) - bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; - - seq_printf(file, "\nPhy0\n"); - - seq_printf(file, "Length: %8d | ", bound[0]); - for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) - seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); - - seq_puts(file, "\nCount: "); - for (i = 0; i < ARRAY_SIZE(bound); i++) - seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]); - seq_puts(file, "\n"); - - seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); -} - -static int -mt7921_tx_stats_show(struct seq_file *file, void *data) -{ - struct mt792x_dev *dev = file->private; - struct mt792x_phy *phy = &dev->phy; - struct mt76_mib_stats *mib = &phy->mib; - int i; - - mt792x_mutex_acquire(dev); - - mt7921_ampdu_stat_read_phy(phy, file); - - seq_puts(file, "Tx MSDU stat:\n"); - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { - seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ", - i + 1, mib->tx_amsdu[i]); - if (mib->tx_amsdu_cnt) - seq_printf(file, "(%3d%%)\n", - mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt); - else - seq_puts(file, "\n"); - } - - mt792x_mutex_release(dev); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats); - -static int -mt7921_queues_acq(struct seq_file *s, void *data) -{ - struct mt792x_dev *dev = dev_get_drvdata(s->private); - int i; - - mt792x_mutex_acquire(dev); - - for (i = 0; i < 4; i++) { - u32 ctrl, val, qlen = 0; - int j; - - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); - ctrl = BIT(31) | BIT(11) | (i << 24); - - for (j = 0; j < 32; j++) { - if (val & BIT(j)) - continue; - - mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); - qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, - GENMASK(11, 0)); - } - seq_printf(s, "AC%d: queued=%d\n", i, qlen); - } - - mt792x_mutex_release(dev); - - return 0; -} - -static int -mt7921_queues_read(struct seq_file *s, void *data) -{ - struct mt792x_dev *dev = dev_get_drvdata(s->private); - struct { - struct mt76_queue *q; - char *queue; - } queue_map[] = { - { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, - { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, - { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, - }; - int i; - - for (i = 0; i < ARRAY_SIZE(queue_map); i++) { - struct mt76_queue *q = queue_map[i].q; - - if (!q) - continue; - - seq_printf(s, - "%s: queued=%d head=%d tail=%d\n", - queue_map[i].queue, q->queued, q->head, - q->tail); - } - - return 0; -} +DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats); static void mt7921_seq_puts_array(struct seq_file *file, const char *str, @@ -342,51 +221,8 @@ mt7921_deep_sleep_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get, mt7921_deep_sleep_set, "%lld\n"); -static int -mt7921_pm_stats(struct seq_file *s, void *data) -{ - struct mt792x_dev *dev = dev_get_drvdata(s->private); - struct mt76_connac_pm *pm = &dev->pm; - - unsigned long awake_time = pm->stats.awake_time; - unsigned long doze_time = pm->stats.doze_time; - - if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) - awake_time += jiffies - pm->stats.last_wake_event; - else - doze_time += jiffies - pm->stats.last_doze_event; - - seq_printf(s, "awake time: %14u\ndoze time: %15u\n", - jiffies_to_msecs(awake_time), - jiffies_to_msecs(doze_time)); - - seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake); - - return 0; -} - -static int -mt7921_pm_idle_timeout_set(void *data, u64 val) -{ - struct mt792x_dev *dev = data; - - dev->pm.idle_timeout = msecs_to_jiffies(val); - - return 0; -} - -static int -mt7921_pm_idle_timeout_get(void *data, u64 *val) -{ - struct mt792x_dev *dev = data; - - *val = jiffies_to_msecs(dev->pm.idle_timeout); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get, - mt7921_pm_idle_timeout_set, "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get, + mt792x_pm_idle_timeout_set, "%lld\n"); static int mt7921_chip_reset(void *data, u64 val) { @@ -435,23 +271,23 @@ int mt7921_init_debugfs(struct mt792x_dev *dev) if (mt76_is_mmio(&dev->mt76)) debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", - dir, mt7921_queues_read); + dir, mt792x_queues_read); else debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir, mt76_queues_read); debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, - mt7921_queues_acq); + mt792x_queues_acq); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, mt7921_txpwr); - debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops); + debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops); debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); debugfs_create_file("idle-timeout", 0600, dir, dev, &fops_pm_idle_timeout); debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset); debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, - mt7921_pm_stats); + mt792x_pm_stats); debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); if (mt76_is_sdio(&dev->mt76)) debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir, diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index fa199cc05c60..1fd53a29fef1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -229,5 +229,11 @@ void mt792x_dma_cleanup(struct mt792x_dev *dev); int mt792x_dma_disable(struct mt792x_dev *dev, bool force); int mt792x_poll_rx(struct napi_struct *napi, int budget); int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr); +int mt792x_tx_stats_show(struct seq_file *file, void *data); +int mt792x_queues_acq(struct seq_file *s, void *data); +int mt792x_queues_read(struct seq_file *s, void *data); +int mt792x_pm_stats(struct seq_file *s, void *data); +int mt792x_pm_idle_timeout_set(void *data, u64 val); +int mt792x_pm_idle_timeout_get(void *data, u64 *val); #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c new file mode 100644 index 000000000000..9858d9a93851 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt792x.h" + +static void +mt792x_ampdu_stat_read_phy(struct mt792x_phy *phy, + struct seq_file *file) +{ + struct mt792x_dev *dev = file->private; + int bound[15], range[4], i; + + if (!phy) + return; + + mt792x_mac_update_mib_stats(phy); + + /* Tx ampdu stat */ + for (i = 0; i < ARRAY_SIZE(range); i++) + range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); + + for (i = 0; i < ARRAY_SIZE(bound); i++) + bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; + + seq_puts(file, "\nPhy0\n"); + + seq_printf(file, "Length: %8d | ", bound[0]); + for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) + seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); + + seq_puts(file, "\nCount: "); + for (i = 0; i < ARRAY_SIZE(bound); i++) + seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]); + seq_puts(file, "\n"); + + seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); +} + +int mt792x_tx_stats_show(struct seq_file *file, void *data) +{ + struct mt792x_dev *dev = file->private; + struct mt792x_phy *phy = &dev->phy; + struct mt76_mib_stats *mib = &phy->mib; + int i; + + mt792x_mutex_acquire(dev); + + mt792x_ampdu_stat_read_phy(phy, file); + + seq_puts(file, "Tx MSDU stat:\n"); + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { + seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ", + i + 1, mib->tx_amsdu[i]); + if (mib->tx_amsdu_cnt) + seq_printf(file, "(%3d%%)\n", + mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt); + else + seq_puts(file, "\n"); + } + + mt792x_mutex_release(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_tx_stats_show); + +int mt792x_queues_acq(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + int i; + + mt792x_mutex_acquire(dev); + + for (i = 0; i < 4; i++) { + u32 ctrl, val, qlen = 0; + int j; + + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); + ctrl = BIT(31) | BIT(11) | (i << 24); + + for (j = 0; j < 32; j++) { + if (val & BIT(j)) + continue; + + mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); + qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, + GENMASK(11, 0)); + } + seq_printf(s, "AC%d: queued=%d\n", i, qlen); + } + + mt792x_mutex_release(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_queues_acq); + +int mt792x_queues_read(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + struct { + struct mt76_queue *q; + char *queue; + } queue_map[] = { + { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, + { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, + { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) { + struct mt76_queue *q = queue_map[i].q; + + if (!q) + continue; + + seq_printf(s, + "%s: queued=%d head=%d tail=%d\n", + queue_map[i].queue, q->queued, q->head, + q->tail); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_queues_read); + +int mt792x_pm_stats(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + struct mt76_connac_pm *pm = &dev->pm; + + unsigned long awake_time = pm->stats.awake_time; + unsigned long doze_time = pm->stats.doze_time; + + if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) + awake_time += jiffies - pm->stats.last_wake_event; + else + doze_time += jiffies - pm->stats.last_doze_event; + + seq_printf(s, "awake time: %14u\ndoze time: %15u\n", + jiffies_to_msecs(awake_time), + jiffies_to_msecs(doze_time)); + + seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_stats); + +int mt792x_pm_idle_timeout_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + + dev->pm.idle_timeout = msecs_to_jiffies(val); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_set); + +int mt792x_pm_idle_timeout_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = jiffies_to_msecs(dev->pm.idle_timeout); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_get); -- cgit From e8a264ccd2de0db8ffc2c6ed2c23644ed15854d4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:06:01 +0800 Subject: wifi: mt76: mt7921: move init shared code in mt792x-lib module Reduce duplicated code moving init shared code in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 254 +-------------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 5 - drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 4 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 22 ++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 227 ++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt792x_mac.c | 29 +++ 8 files changed, 288 insertions(+), 261 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 449ce34a6dcf..0a6f8f42b2e4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -10,50 +10,6 @@ #include "../mt76_connac2_mac.h" #include "mcu.h" -static const struct ieee80211_iface_limit if_limits[] = { - { - .max = MT792x_MAX_INTERFACES, - .types = BIT(NL80211_IFTYPE_STATION) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_AP) - } -}; - -static const struct ieee80211_iface_combination if_comb[] = { - { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = MT792x_MAX_INTERFACES, - .num_different_channels = 1, - .beacon_int_infra_match = true, - }, -}; - -static const struct ieee80211_iface_limit if_limits_chanctx[] = { - { - .max = 2, - .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) - } -}; - -static const struct ieee80211_iface_combination if_comb_chanctx[] = { - { - .limits = if_limits_chanctx, - .n_limits = ARRAY_SIZE(if_limits_chanctx), - .max_interfaces = 2, - .num_different_channels = 2, - .beacon_int_infra_match = false, - } -}; - static ssize_t mt7921_thermal_temp_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -123,192 +79,6 @@ mt7921_regd_notifier(struct wiphy *wiphy, mt792x_mutex_release(dev); } -static int -mt7921_init_wiphy(struct ieee80211_hw *hw) -{ - struct mt792x_phy *phy = mt792x_hw_phy(hw); - struct mt792x_dev *dev = phy->dev; - struct wiphy *wiphy = hw->wiphy; - - hw->queues = 4; - hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - hw->netdev_features = NETIF_F_RXCSUM; - - hw->radiotap_timestamp.units_pos = - IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; - - phy->slottime = 9; - - hw->sta_data_size = sizeof(struct mt792x_sta); - hw->vif_data_size = sizeof(struct mt792x_vif); - - if (dev->fw_features & MT7921_FW_CAP_CNM) { - wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->iface_combinations = if_comb_chanctx; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx); - } else { - wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->iface_combinations = if_comb; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); - } - wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | - WIPHY_FLAG_4ADDR_STATION); - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); - wiphy->max_remain_on_channel_duration = 5000; - wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; - wiphy->max_scan_ssids = 4; - wiphy->max_sched_scan_plan_interval = - MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; - wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; - wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; - wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; - wiphy->max_sched_scan_reqs = 1; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | - WIPHY_FLAG_SPLIT_SCAN_6GHZ; - wiphy->reg_notifier = mt7921_regd_notifier; - - wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | - NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); - - ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); - ieee80211_hw_set(hw, HAS_RATE_CONTROL); - ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); - ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); - ieee80211_hw_set(hw, WANT_MONITOR_VIF); - ieee80211_hw_set(hw, SUPPORTS_PS); - ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); - ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); - ieee80211_hw_set(hw, CONNECTION_MONITOR); - - if (dev->pm.enable) - ieee80211_hw_set(hw, CONNECTION_MONITOR); - - hw->max_tx_fragments = 4; - - return 0; -} - -static void -mt7921_mac_init_band(struct mt792x_dev *dev, u8 band) -{ - u32 mask, set; - - mt76_rmw_field(dev, MT_TMAC_CTCR0(band), - MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); - mt76_set(dev, MT_TMAC_CTCR0(band), - MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | - MT_TMAC_CTCR0_INS_DDLMT_EN); - - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - - /* enable MIB tx-rx time reporting */ - mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); - mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); - - mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); - /* disable rx rate report by default due to hw issues */ - mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); - - /* filter out non-resp frames and get instantaneous signal reporting */ - mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM; - set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | - FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); - mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); -} - -static u8 -mt7921_get_offload_capability(struct device *dev, const char *fw_wm) -{ - const struct mt76_connac2_fw_trailer *hdr; - struct mt7921_realease_info *rel_info; - const struct firmware *fw; - int ret, i, offset = 0; - const u8 *data, *end; - u8 offload_caps = 0; - - ret = request_firmware(&fw, fw_wm, dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev, "Invalid firmware\n"); - goto out; - } - - data = fw->data; - hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); - - for (i = 0; i < hdr->n_region; i++) { - const struct mt76_connac2_fw_region *region; - - region = (const void *)((const u8 *)hdr - - (hdr->n_region - i) * sizeof(*region)); - offset += le32_to_cpu(region->len); - } - - data += offset + 16; - rel_info = (struct mt7921_realease_info *)data; - data += sizeof(*rel_info); - end = data + le16_to_cpu(rel_info->len); - - while (data < end) { - rel_info = (struct mt7921_realease_info *)data; - data += sizeof(*rel_info); - - if (rel_info->tag == MT7921_FW_TAG_FEATURE) { - struct mt7921_fw_features *features; - - features = (struct mt7921_fw_features *)data; - offload_caps = features->data; - break; - } - - data += le16_to_cpu(rel_info->len) + rel_info->pad_len; - } - -out: - release_firmware(fw); - - return offload_caps; -} - -struct ieee80211_ops * -mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features) -{ - struct ieee80211_ops *ops; - - ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL); - if (!ops) - return NULL; - - *fw_features = mt7921_get_offload_capability(dev, drv_data); - if (!(*fw_features & MT7921_FW_CAP_CNM)) { - ops->remain_on_channel = NULL; - ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; - ops->assign_vif_chanctx = NULL; - ops->unassign_vif_chanctx = NULL; - ops->mgd_prepare_tx = NULL; - ops->mgd_complete_tx = NULL; - } - return ops; -} -EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops); - int mt7921_mac_init(struct mt792x_dev *dev) { int i; @@ -323,7 +93,7 @@ int mt7921_mac_init(struct mt792x_dev *dev) mt7921_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); for (i = 0; i < 2; i++) - mt7921_mac_init_band(dev, i); + mt792x_mac_init_band(dev, i); return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0); } @@ -374,23 +144,6 @@ static int mt7921_init_hardware(struct mt792x_dev *dev) return 0; } -static int mt7921_init_wcid(struct mt792x_dev *dev) -{ - int idx; - - /* Beacon and mgmt frames should occupy wcid 0 */ - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); - if (idx) - return -ENOSPC; - - dev->mt76.global_wcid.idx = idx; - dev->mt76.global_wcid.hw_key_idx = -1; - dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET; - rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); - - return 0; -} - static void mt7921_init_work(struct work_struct *work) { struct mt792x_dev *dev = container_of(work, struct mt792x_dev, @@ -479,14 +232,15 @@ int mt7921_register_device(struct mt792x_dev *dev) mt7921_init_acpi_sar(dev); - ret = mt7921_init_wcid(dev); + ret = mt792x_init_wcid(dev); if (ret) return ret; - ret = mt7921_init_wiphy(hw); + ret = mt792x_init_wiphy(hw); if (ret) return ret; + hw->wiphy->reg_notifier = mt7921_regd_notifier; dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index b8699c942b34..fc952c30ca07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -22,9 +22,6 @@ #define MT7921_MCU_INIT_RETRY_COUNT 10 #define MT7921_WFSYS_INIT_RETRY_COUNT 2 -#define MT7921_FW_TAG_FEATURE 4 -#define MT7921_FW_CAP_CNM BIT(7) - #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" @@ -400,6 +397,4 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, enum mt7921_roc_req type, u8 token_id); int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id); -struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev, - void *drv_data, u8 *fw_features); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 4d929cf8d854..58f6f5a76498 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -288,8 +288,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (mt7921_disable_aspm) mt76_pci_disable_aspm(pdev); - ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data, - &features); + ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7921_ops, + (void *)id->driver_data, &features); if (!ops) { ret = -ENOMEM; goto err_free_pci_vec; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index f0117ac34594..84b388656941 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -127,8 +127,8 @@ static int mt7921s_probe(struct sdio_func *func, u8 features; int ret; - ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data, - &features); + ops = mt792x_get_mac80211_ops(&func->dev, &mt7921_ops, + (void *)id->driver_data, &features); if (!ops) return -ENOMEM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index c7368cf676a9..0a31e7076324 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -212,8 +212,8 @@ static int mt7921u_probe(struct usb_interface *usb_intf, u8 features; int ret; - ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info, - &features); + ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops, + (void *)id->driver_info, &features); if (!ops) return -ENOMEM; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 1fd53a29fef1..f13779d19983 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -18,6 +18,9 @@ #define MT792x_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT792x_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ +#define MT792x_FW_TAG_FEATURE 4 +#define MT792x_FW_CAP_CNM BIT(7) + /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ #define MT792x_BASIC_RATES_TBL 11 @@ -26,6 +29,18 @@ struct mt792x_vif; struct mt792x_sta; +struct mt792x_realease_info { + __le16 len; + u8 pad_len; + u8 tag; +} __packed; + +struct mt792x_fw_features { + u8 segment; + u8 data; + u8 rsv[14]; +} __packed; + enum { MT792x_CLC_POWER, MT792x_CLC_CHAN, @@ -183,6 +198,7 @@ static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev) void mt792x_reset(struct mt76_dev *mdev); void mt792x_update_channel(struct mt76_phy *mphy); void mt792x_mac_reset_counters(struct mt792x_phy *phy); +void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band); void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb); struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, bool unicast); @@ -235,5 +251,11 @@ int mt792x_queues_read(struct seq_file *s, void *data); int mt792x_pm_stats(struct seq_file *s, void *data); int mt792x_pm_idle_timeout_set(void *data, u64 val); int mt792x_pm_idle_timeout_get(void *data, u64 *val); +int mt792x_init_wiphy(struct ieee80211_hw *hw); +struct ieee80211_ops * +mt792x_get_mac80211_ops(struct device *dev, + const struct ieee80211_ops *mac80211_ops, + void *drv_data, u8 *fw_features); +int mt792x_init_wcid(struct mt792x_dev *dev); #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index b176ce53996e..87d2a614e590 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -2,10 +2,55 @@ /* Copyright (C) 2023 MediaTek Inc. */ #include +#include #include "mt792x.h" #include "dma.h" +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = MT792x_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) + } +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = MT792x_MAX_INTERFACES, + .num_different_channels = 1, + .beacon_int_infra_match = true, + }, +}; + +static const struct ieee80211_iface_limit if_limits_chanctx[] = { + { + .max = 2, + .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) + } +}; + +static const struct ieee80211_iface_combination if_comb_chanctx[] = { + { + .limits = if_limits_chanctx, + .n_limits = ARRAY_SIZE(if_limits_chanctx), + .max_interfaces = 2, + .num_different_channels = 2, + .beacon_int_infra_match = false, + } +}; + void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { @@ -561,5 +606,187 @@ int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr) } EXPORT_SYMBOL_GPL(mt792x_wfsys_reset); +int mt792x_init_wiphy(struct ieee80211_hw *hw) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; + if (dev->has_eht) { + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT; + } else { + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + } + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + + phy->slottime = 9; + + hw->sta_data_size = sizeof(struct mt792x_sta); + hw->vif_data_size = sizeof(struct mt792x_vif); + + if (dev->fw_features & MT792x_FW_CAP_CNM) { + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + wiphy->iface_combinations = if_comb_chanctx; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx); + } else { + wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + } + wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | + WIPHY_FLAG_4ADDR_STATION); + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); + wiphy->max_remain_on_channel_duration = 5000; + wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; + wiphy->max_scan_ssids = 4; + wiphy->max_sched_scan_plan_interval = + MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; + wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; + wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; + wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; + wiphy->max_sched_scan_reqs = 1; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_SPLIT_SCAN_6GHZ; + + wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + + ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + ieee80211_hw_set(hw, CONNECTION_MONITOR); + + if (dev->pm.enable) + ieee80211_hw_set(hw, CONNECTION_MONITOR); + + hw->max_tx_fragments = 4; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_wiphy); + +static u8 +mt792x_get_offload_capability(struct device *dev, const char *fw_wm) +{ + const struct mt76_connac2_fw_trailer *hdr; + struct mt792x_realease_info *rel_info; + const struct firmware *fw; + int ret, i, offset = 0; + const u8 *data, *end; + u8 offload_caps = 0; + + ret = request_firmware(&fw, fw_wm, dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev, "Invalid firmware\n"); + goto out; + } + + data = fw->data; + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + + for (i = 0; i < hdr->n_region; i++) { + const struct mt76_connac2_fw_region *region; + + region = (const void *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); + offset += le32_to_cpu(region->len); + } + + data += offset + 16; + rel_info = (struct mt792x_realease_info *)data; + data += sizeof(*rel_info); + end = data + le16_to_cpu(rel_info->len); + + while (data < end) { + rel_info = (struct mt792x_realease_info *)data; + data += sizeof(*rel_info); + + if (rel_info->tag == MT792x_FW_TAG_FEATURE) { + struct mt792x_fw_features *features; + + features = (struct mt792x_fw_features *)data; + offload_caps = features->data; + break; + } + + data += le16_to_cpu(rel_info->len) + rel_info->pad_len; + } + +out: + release_firmware(fw); + + return offload_caps; +} + +struct ieee80211_ops * +mt792x_get_mac80211_ops(struct device *dev, + const struct ieee80211_ops *mac80211_ops, + void *drv_data, u8 *fw_features) +{ + struct ieee80211_ops *ops; + + ops = devm_kmemdup(dev, mac80211_ops, sizeof(struct ieee80211_ops), + GFP_KERNEL); + if (!ops) + return NULL; + + *fw_features = mt792x_get_offload_capability(dev, drv_data); + if (!(*fw_features & MT792x_FW_CAP_CNM)) { + ops->remain_on_channel = NULL; + ops->cancel_remain_on_channel = NULL; + ops->add_chanctx = NULL; + ops->remove_chanctx = NULL; + ops->change_chanctx = NULL; + ops->assign_vif_chanctx = NULL; + ops->unassign_vif_chanctx = NULL; + ops->mgd_prepare_tx = NULL; + ops->mgd_complete_tx = NULL; + } + return ops; +} +EXPORT_SYMBOL_GPL(mt792x_get_mac80211_ops); + +int mt792x_init_wcid(struct mt792x_dev *dev) +{ + int idx; + + /* Beacon and mgmt frames should occupy wcid 0 */ + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); + if (idx) + return -ENOSPC; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx = -1; + dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET; + rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_wcid); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c index 130b4352cf92..9603c4eedb2b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -282,3 +282,32 @@ void mt792x_reset(struct mt76_dev *mdev) queue_work(dev->mt76.wq, &dev->reset_work); } EXPORT_SYMBOL_GPL(mt792x_reset); + +void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band) +{ + u32 mask, set; + + mt76_rmw_field(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); + mt76_set(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + + /* enable MIB tx-rx time reporting */ + mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); + mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); + + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); + /* disable rx rate report by default due to hw issues */ + mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); + + /* filter out non-resp frames and get instantaneous signal reporting */ + mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM; + set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | + FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); + mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); +} +EXPORT_SYMBOL_GPL(mt792x_mac_init_band); -- cgit From c9072f112fcf7b31c33a0097a3e020fe077f82bf Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:06:02 +0800 Subject: wifi: mt76: mt792x: introduce mt792x_irq_map mt792x_irq_map will be use to share the irq code shared between mt7921 and mt7925 Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 9 ++-- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 53 ++++++++++++++-------- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 8 ++-- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 17 ------- drivers/net/wireless/mediatek/mt76/mt792x.h | 14 ++++++ drivers/net/wireless/mediatek/mt76/mt792x_regs.h | 19 ++++++++ 6 files changed, 77 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 9dcda35cdf73..1ac66526eb02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -19,7 +19,8 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) mt76_connac_tx_cleanup(&dev->mt76); if (napi_complete(napi)) - mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL); + mt76_connac_irq_enable(&dev->mt76, + dev->irq_map->tx.all_complete_mask); mt76_connac_pm_unref(&dev->mphy, &dev->pm); return 0; @@ -72,8 +73,8 @@ static int mt7921_dma_enable(struct mt792x_dev *dev) /* enable interrupts for TX/RX rings */ mt76_connac_irq_enable(&dev->mt76, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); return 0; @@ -139,7 +140,7 @@ int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev) /* check if the wpdma must be reinitialized */ if (mt792x_dma_need_reinit(dev)) { /* disable interrutpts */ - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); err = mt7921_wpdma_reset(dev, false); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 58f6f5a76498..606a7e41a240 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -31,19 +31,22 @@ MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support"); static void mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + const struct mt792x_irq_map *irq_map = dev->irq_map; + if (q == MT_RXQ_MAIN) - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA); + mt76_connac_irq_enable(mdev, irq_map->rx.data_complete_mask); else if (q == MT_RXQ_MCU_WA) - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2); + mt76_connac_irq_enable(mdev, irq_map->rx.wm2_complete_mask); else - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM); + mt76_connac_irq_enable(mdev, irq_map->rx.wm_complete_mask); } static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) { struct mt792x_dev *dev = dev_instance; - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; @@ -56,9 +59,10 @@ static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) static void mt7921_irq_tasklet(unsigned long data) { struct mt792x_dev *dev = (struct mt792x_dev *)data; + const struct mt792x_irq_map *irq_map = dev->irq_map; u32 intr, mask = 0; - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, irq_map->host_irq_enable, 0); intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA); intr &= dev->mt76.mmio.irqmask; @@ -67,8 +71,8 @@ static void mt7921_irq_tasklet(unsigned long data) trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); mask |= intr & MT_INT_RX_DONE_ALL; - if (intr & MT_INT_TX_DONE_MCU) - mask |= MT_INT_TX_DONE_MCU; + if (intr & irq_map->tx.mcu_complete_mask) + mask |= irq_map->tx.mcu_complete_mask; if (intr & MT_INT_MCU_CMD) { u32 intr_sw; @@ -77,23 +81,23 @@ static void mt7921_irq_tasklet(unsigned long data) /* ack MCU2HOST_SW_INT_STA */ mt76_wr(dev, MT_MCU_CMD, intr_sw); if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) { - mask |= MT_INT_RX_DONE_DATA; - intr |= MT_INT_RX_DONE_DATA; + mask |= irq_map->rx.data_complete_mask; + intr |= irq_map->rx.data_complete_mask; } } - mt76_set_irq_mask(&dev->mt76, MT_WFDMA0_HOST_INT_ENA, mask, 0); + mt76_set_irq_mask(&dev->mt76, irq_map->host_irq_enable, mask, 0); - if (intr & MT_INT_TX_DONE_ALL) + if (intr & irq_map->tx.all_complete_mask) napi_schedule(&dev->mt76.tx_napi); - if (intr & MT_INT_RX_DONE_WM) + if (intr & irq_map->rx.wm_complete_mask) napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); - if (intr & MT_INT_RX_DONE_WM2) + if (intr & irq_map->rx.wm2_complete_mask) napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); - if (intr & MT_INT_RX_DONE_DATA) + if (intr & irq_map->rx.data_complete_mask) napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); } @@ -254,6 +258,18 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .drv_own = mt7921e_mcu_drv_pmctrl, .fw_own = mt7921e_mcu_fw_pmctrl, }; + static const struct mt792x_irq_map irq_map = { + .host_irq_enable = MT_WFDMA0_HOST_INT_ENA, + .tx = { + .all_complete_mask = MT_INT_TX_DONE_ALL, + .mcu_complete_mask = MT_INT_TX_DONE_MCU, + }, + .rx = { + .data_complete_mask = MT_INT_RX_DONE_DATA, + .wm_complete_mask = MT_INT_RX_DONE_WM, + .wm2_complete_mask = MT_INT_RX_DONE_WM2, + }, + }; struct ieee80211_ops *ops; struct mt76_bus_ops *bus_ops; struct mt792x_dev *dev; @@ -306,6 +322,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &mt7921_pcie_ops; + dev->irq_map = &irq_map; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); @@ -341,7 +358,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (ret) goto err_free_dev; - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, irq_map.host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); @@ -424,7 +441,7 @@ static int mt7921_pci_suspend(struct device *device) MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); /* disable interrupt */ - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); synchronize_irq(pdev->irq); tasklet_kill(&mdev->irq_tasklet); @@ -472,8 +489,8 @@ static int mt7921_pci_resume(struct device *device) /* enable interrupt */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); mt76_connac_irq_enable(&dev->mt76, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); /* put dma enabled */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 7323388327f4..1f508244d615 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -61,7 +61,7 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); set_bit(MT76_RESET, &dev->mphy.state); @@ -92,9 +92,9 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) dev->fw_assert = false; clear_bit(MT76_MCU_RESET, &dev->mphy.state); - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + mt76_wr(dev, dev->irq_map->host_irq_enable, + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); err = mt7921e_driver_own(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 083d655f82e5..43427a3a48af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -29,18 +29,6 @@ #define MT_MDP_TO_WM 1 #define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204) -#define HOST_RX_DONE_INT_ENA0 BIT(0) -#define HOST_RX_DONE_INT_ENA1 BIT(1) -#define HOST_RX_DONE_INT_ENA2 BIT(2) -#define HOST_RX_DONE_INT_ENA3 BIT(3) -#define HOST_TX_DONE_INT_ENA0 BIT(4) -#define HOST_TX_DONE_INT_ENA1 BIT(5) -#define HOST_TX_DONE_INT_ENA2 BIT(6) -#define HOST_TX_DONE_INT_ENA3 BIT(7) -#define HOST_TX_DONE_INT_ENA4 BIT(8) -#define HOST_TX_DONE_INT_ENA5 BIT(9) -#define HOST_TX_DONE_INT_ENA6 BIT(10) -#define HOST_TX_DONE_INT_ENA7 BIT(11) #define HOST_TX_DONE_INT_ENA8 BIT(12) #define HOST_TX_DONE_INT_ENA9 BIT(13) #define HOST_TX_DONE_INT_ENA10 BIT(14) @@ -48,14 +36,10 @@ #define HOST_TX_DONE_INT_ENA12 BIT(16) #define HOST_TX_DONE_INT_ENA13 BIT(17) #define HOST_TX_DONE_INT_ENA14 BIT(18) -#define HOST_RX_COHERENT_EN BIT(20) -#define HOST_TX_COHERENT_EN BIT(21) #define HOST_RX_DONE_INT_ENA4 BIT(22) #define HOST_RX_DONE_INT_ENA5 BIT(23) #define HOST_TX_DONE_INT_ENA16 BIT(26) #define HOST_TX_DONE_INT_ENA17 BIT(27) -#define MCU2HOST_SW_INT_ENA BIT(29) -#define HOST_TX_DONE_INT_ENA18 BIT(30) /* WFDMA interrupt */ #define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2 @@ -67,7 +51,6 @@ #define MT_INT_TX_DONE_MCU_WM HOST_TX_DONE_INT_ENA17 #define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16 #define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0 -#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA #define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \ MT_INT_TX_DONE_FWDL) diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index f13779d19983..6fd1f542da17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -114,6 +114,19 @@ struct mt792x_phy { bool roc_grant; }; +struct mt792x_irq_map { + u32 host_irq_enable; + struct { + u32 all_complete_mask; + u32 mcu_complete_mask; + } tx; + struct { + u32 data_complete_mask; + u32 wm_complete_mask; + u32 wm2_complete_mask; + } rx; +}; + struct mt792x_hif_ops { int (*init_reset)(struct mt792x_dev *dev); int (*reset)(struct mt792x_dev *dev); @@ -145,6 +158,7 @@ struct mt792x_dev { struct mt76_connac_pm pm; struct mt76_connac_coredump coredump; const struct mt792x_hif_ops *hif_ops; + const struct mt792x_irq_map *irq_map; struct work_struct ipv6_ns_work; /* IPv6 addresses for WoWLAN */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h index 9c6308ef4cb3..a99af23e4b56 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -301,6 +301,25 @@ #define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) #define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30) +#define HOST_RX_DONE_INT_ENA0 BIT(0) +#define HOST_RX_DONE_INT_ENA1 BIT(1) +#define HOST_RX_DONE_INT_ENA2 BIT(2) +#define HOST_RX_DONE_INT_ENA3 BIT(3) +#define HOST_TX_DONE_INT_ENA0 BIT(4) +#define HOST_TX_DONE_INT_ENA1 BIT(5) +#define HOST_TX_DONE_INT_ENA2 BIT(6) +#define HOST_TX_DONE_INT_ENA3 BIT(7) +#define HOST_TX_DONE_INT_ENA4 BIT(8) +#define HOST_TX_DONE_INT_ENA5 BIT(9) +#define HOST_TX_DONE_INT_ENA6 BIT(10) +#define HOST_TX_DONE_INT_ENA7 BIT(11) +#define HOST_RX_COHERENT_EN BIT(20) +#define HOST_TX_COHERENT_EN BIT(21) +#define MCU2HOST_SW_INT_ENA BIT(29) +#define HOST_TX_DONE_INT_ENA18 BIT(30) + +#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA + #define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) #define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280) #define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) -- cgit From ff6551740000eac6a63445d30d5bac5c0ca900c3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:14 +0800 Subject: wifi: mt76: mt792x: move more dma shared code in mt792x_dma Rely on irq_map support, move more dma shared code between mt7921 and mt7925 in mt792x_dma.c Move the following dma code in mt792x-lib - mt792x_dma_enable - mt792x_dma_reset - mt792x_wpdma_reset - mt792x_wpdma_reinit_cond Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 156 +--------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 - drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 88 +----- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/pci_mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 9 +- drivers/net/wireless/mediatek/mt76/mt792x_core.c | 96 ------ drivers/net/wireless/mediatek/mt76/mt792x_dma.c | 344 +++++++++++++++++++++ 9 files changed, 364 insertions(+), 337 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_dma.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index a45853ab958f..d6231948dd6e 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -32,7 +32,7 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \ - mt792x_debugfs.o + mt792x_debugfs.o mt792x_dma.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 1ac66526eb02..fdc598e099f6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -5,158 +5,6 @@ #include "../dma.h" #include "../mt76_connac2_mac.h" -static int mt7921_poll_tx(struct napi_struct *napi, int budget) -{ - struct mt792x_dev *dev; - - dev = container_of(napi, struct mt792x_dev, mt76.tx_napi); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - napi_complete(napi); - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return 0; - } - - mt76_connac_tx_cleanup(&dev->mt76); - if (napi_complete(napi)) - mt76_connac_irq_enable(&dev->mt76, - dev->irq_map->tx.all_complete_mask); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); - - return 0; -} - -static void mt7921_dma_prefetch(struct mt792x_dev *dev) -{ -#define PREFETCH(base, depth) ((base) << 16 | (depth)) - - mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4)); - - mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); -} - -static int mt7921_dma_enable(struct mt792x_dev *dev) -{ - /* configure perfetch settings */ - mt7921_dma_prefetch(dev); - - /* reset dma idx */ - mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); - - /* configure delay interrupt */ - mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); - - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_WB_DDONE | - MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | - MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); - - /* enable interrupts for TX/RX rings */ - mt76_connac_irq_enable(&dev->mt76, - dev->irq_map->tx.all_complete_mask | - MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); - mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); - - return 0; -} - -static int mt7921_dma_reset(struct mt792x_dev *dev, bool force) -{ - int i, err; - - err = mt792x_dma_disable(dev, force); - if (err) - return err; - - /* reset hw queues */ - for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_reset(dev, dev->mphy.q_tx[i]); - - for (i = 0; i < __MT_MCUQ_MAX; i++) - mt76_queue_reset(dev, dev->mt76.q_mcu[i]); - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_reset(dev, &dev->mt76.q_rx[i]); - - mt76_tx_status_check(&dev->mt76, true); - - return mt7921_dma_enable(dev); -} - -int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force) -{ - int i, err; - - /* clean up hw queues */ - for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++) - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); - - if (force) { - err = mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); - if (err) - return err; - } - err = mt7921_dma_reset(dev, force); - if (err) - return err; - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_rx_reset(dev, i); - - return 0; -} - -int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev) -{ - struct mt76_connac_pm *pm = &dev->pm; - int err; - - /* check if the wpdma must be reinitialized */ - if (mt792x_dma_need_reinit(dev)) { - /* disable interrutpts */ - mt76_wr(dev, dev->irq_map->host_irq_enable, 0); - mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); - - err = mt7921_wpdma_reset(dev, false); - if (err) { - dev_err(dev->mt76.dev, "wpdma reset failed\n"); - return err; - } - - /* enable interrutpts */ - mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - pm->stats.lp_wake++; - } - - return 0; -} - int mt7921_dma_init(struct mt792x_dev *dev) { int ret; @@ -216,8 +64,8 @@ int mt7921_dma_init(struct mt792x_dev *dev) return ret; netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7921_poll_tx); + mt792x_poll_tx); napi_enable(&dev->mt76.tx_napi); - return mt7921_dma_enable(dev); + return mt792x_dma_enable(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index fc952c30ca07..b797d8bab5e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -203,8 +203,6 @@ int __mt7921_start(struct mt792x_phy *phy); int mt7921_register_device(struct mt792x_dev *dev); void mt7921_unregister_device(struct mt792x_dev *dev); int mt7921_dma_init(struct mt792x_dev *dev); -int mt7921_wpdma_reset(struct mt792x_dev *dev, bool force); -int mt7921_wpdma_reinit_cond(struct mt792x_dev *dev); int mt7921_run_firmware(struct mt792x_dev *dev); int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 606a7e41a240..d11406c87df7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -10,7 +10,6 @@ #include "mt7921.h" #include "../mt76_connac2_mac.h" #include "mcu.h" -#include "../trace.h" static const struct pci_device_id mt7921_pci_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961), @@ -28,82 +27,9 @@ static bool mt7921_disable_aspm; module_param_named(disable_aspm, mt7921_disable_aspm, bool, 0644); MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support"); -static void -mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) -{ - struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - const struct mt792x_irq_map *irq_map = dev->irq_map; - - if (q == MT_RXQ_MAIN) - mt76_connac_irq_enable(mdev, irq_map->rx.data_complete_mask); - else if (q == MT_RXQ_MCU_WA) - mt76_connac_irq_enable(mdev, irq_map->rx.wm2_complete_mask); - else - mt76_connac_irq_enable(mdev, irq_map->rx.wm_complete_mask); -} - -static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) -{ - struct mt792x_dev *dev = dev_instance; - - mt76_wr(dev, dev->irq_map->host_irq_enable, 0); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return IRQ_NONE; - - tasklet_schedule(&dev->mt76.irq_tasklet); - - return IRQ_HANDLED; -} - -static void mt7921_irq_tasklet(unsigned long data) -{ - struct mt792x_dev *dev = (struct mt792x_dev *)data; - const struct mt792x_irq_map *irq_map = dev->irq_map; - u32 intr, mask = 0; - - mt76_wr(dev, irq_map->host_irq_enable, 0); - - intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA); - intr &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr); - - trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); - - mask |= intr & MT_INT_RX_DONE_ALL; - if (intr & irq_map->tx.mcu_complete_mask) - mask |= irq_map->tx.mcu_complete_mask; - - if (intr & MT_INT_MCU_CMD) { - u32 intr_sw; - - intr_sw = mt76_rr(dev, MT_MCU_CMD); - /* ack MCU2HOST_SW_INT_STA */ - mt76_wr(dev, MT_MCU_CMD, intr_sw); - if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) { - mask |= irq_map->rx.data_complete_mask; - intr |= irq_map->rx.data_complete_mask; - } - } - - mt76_set_irq_mask(&dev->mt76, irq_map->host_irq_enable, mask, 0); - - if (intr & irq_map->tx.all_complete_mask) - napi_schedule(&dev->mt76.tx_napi); - - if (intr & irq_map->rx.wm_complete_mask) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); - - if (intr & irq_map->rx.wm2_complete_mask) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); - - if (intr & irq_map->rx.data_complete_mask) - napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); -} - static int mt7921e_init_reset(struct mt792x_dev *dev) { - return mt7921_wpdma_reset(dev, true); + return mt792x_wpdma_reset(dev, true); } static void mt7921e_unregister_device(struct mt792x_dev *dev) @@ -122,7 +48,7 @@ static void mt7921e_unregister_device(struct mt792x_dev *dev) mt76_connac2_tx_token_put(&dev->mt76); __mt7921_mcu_drv_pmctrl(dev); mt792x_dma_cleanup(dev); - mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); + mt792x_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); tasklet_disable(&dev->mt76.irq_tasklet); @@ -245,7 +171,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .tx_complete_skb = mt76_connac_tx_complete_skb, .rx_check = mt7921_rx_check, .rx_skb = mt7921_queue_rx_skb, - .rx_poll_complete = mt7921_rx_poll_complete, + .rx_poll_complete = mt792x_rx_poll_complete, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, @@ -324,7 +250,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, dev->hif_ops = &mt7921_pcie_ops; dev->irq_map = &irq_map; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); + tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev); dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; @@ -354,7 +280,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - ret = mt792x_wfsys_reset(dev, MT_WFSYS_SW_RST_B); + ret = mt792x_wfsys_reset(dev); if (ret) goto err_free_dev; @@ -362,7 +288,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler, + ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto err_free_dev; @@ -484,7 +410,7 @@ static int mt7921_pci_resume(struct device *device) if (err < 0) goto failed; - mt7921_wpdma_reinit_cond(dev); + mt792x_wpdma_reinit_cond(dev); /* enable interrupt */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 1f508244d615..bd3f004d1a18 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -80,7 +80,7 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); - mt7921_wpdma_reset(dev, true); + mt792x_wpdma_reset(dev, true); local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c index 5a30cd0b9382..57bd02746f5f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c @@ -91,7 +91,7 @@ int mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev) if (err < 0) goto out; - mt7921_wpdma_reinit_cond(dev); + mt792x_wpdma_reinit_cond(dev); clear_bit(MT76_STATE_PM, &mphy->state); pm->stats.last_wake_event = jiffies; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 6fd1f542da17..894fb0fe8cba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -256,9 +256,16 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, struct station_info *sinfo); void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); void mt792x_dma_cleanup(struct mt792x_dev *dev); +int mt792x_dma_enable(struct mt792x_dev *dev); +int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force); +int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev); int mt792x_dma_disable(struct mt792x_dev *dev, bool force); +irqreturn_t mt792x_irq_handler(int irq, void *dev_instance); +void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); +int mt792x_poll_tx(struct napi_struct *napi, int budget); int mt792x_poll_rx(struct napi_struct *napi, int budget); -int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr); +void mt792x_irq_tasklet(unsigned long data); +int mt792x_wfsys_reset(struct mt792x_dev *dev); int mt792x_tx_stats_show(struct seq_file *file, void *data); int mt792x_queues_acq(struct seq_file *s, void *data); int mt792x_queues_read(struct seq_file *s, void *data); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index 87d2a614e590..a4aa9694de7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -510,102 +510,6 @@ void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) } EXPORT_SYMBOL_GPL(mt792x_set_coverage_class); -int mt792x_dma_disable(struct mt792x_dev *dev, bool force) -{ - /* disable WFDMA0 */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) - return -ETIMEDOUT; - - /* disable dmashdl */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - - if (force) { - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - } - - return 0; -} -EXPORT_SYMBOL_GPL(mt792x_dma_disable); - -void mt792x_dma_cleanup(struct mt792x_dev *dev) -{ - /* disable */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1); - - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_dma_cleanup(&dev->mt76); -} -EXPORT_SYMBOL_GPL(mt792x_dma_cleanup); - -int mt792x_poll_rx(struct napi_struct *napi, int budget) -{ - struct mt792x_dev *dev; - int done; - - dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - napi_complete(napi); - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return 0; - } - done = mt76_dma_rx_poll(napi, budget); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); - - return done; -} -EXPORT_SYMBOL_GPL(mt792x_poll_rx); - -int mt792x_wfsys_reset(struct mt792x_dev *dev, u32 addr) -{ - mt76_clear(dev, addr, WFSYS_SW_RST_B); - msleep(50); - mt76_set(dev, addr, WFSYS_SW_RST_B); - - if (!__mt76_poll_msec(&dev->mt76, addr, WFSYS_SW_INIT_DONE, - WFSYS_SW_INIT_DONE, 500)) - return -ETIMEDOUT; - - return 0; -} -EXPORT_SYMBOL_GPL(mt792x_wfsys_reset); - int mt792x_init_wiphy(struct ieee80211_hw *hw) { struct mt792x_phy *phy = mt792x_hw_phy(hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c new file mode 100644 index 000000000000..a3dbd3865b2f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include +#include + +#include "mt792x.h" +#include "dma.h" +#include "trace.h" + +irqreturn_t mt792x_irq_handler(int irq, void *dev_instance) +{ + struct mt792x_dev *dev = dev_instance; + + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + tasklet_schedule(&dev->mt76.irq_tasklet); + + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(mt792x_irq_handler); + +void mt792x_irq_tasklet(unsigned long data) +{ + struct mt792x_dev *dev = (struct mt792x_dev *)data; + const struct mt792x_irq_map *irq_map = dev->irq_map; + u32 intr, mask = 0; + + mt76_wr(dev, irq_map->host_irq_enable, 0); + + intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA); + intr &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr); + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + mask |= intr & (irq_map->rx.data_complete_mask | + irq_map->rx.wm_complete_mask | + irq_map->rx.wm2_complete_mask); + if (intr & dev->irq_map->tx.mcu_complete_mask) + mask |= dev->irq_map->tx.mcu_complete_mask; + + if (intr & MT_INT_MCU_CMD) { + u32 intr_sw; + + intr_sw = mt76_rr(dev, MT_MCU_CMD); + /* ack MCU2HOST_SW_INT_STA */ + mt76_wr(dev, MT_MCU_CMD, intr_sw); + if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) { + mask |= irq_map->rx.data_complete_mask; + intr |= irq_map->rx.data_complete_mask; + } + } + + mt76_set_irq_mask(&dev->mt76, irq_map->host_irq_enable, mask, 0); + + if (intr & dev->irq_map->tx.all_complete_mask) + napi_schedule(&dev->mt76.tx_napi); + + if (intr & irq_map->rx.wm_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); + + if (intr & irq_map->rx.wm2_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); + + if (intr & irq_map->rx.data_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); +} +EXPORT_SYMBOL_GPL(mt792x_irq_tasklet); + +void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + const struct mt792x_irq_map *irq_map = dev->irq_map; + + if (q == MT_RXQ_MAIN) + mt76_connac_irq_enable(mdev, irq_map->rx.data_complete_mask); + else if (q == MT_RXQ_MCU_WA) + mt76_connac_irq_enable(mdev, irq_map->rx.wm2_complete_mask); + else + mt76_connac_irq_enable(mdev, irq_map->rx.wm_complete_mask); +} +EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete); + +#define PREFETCH(base, depth) ((base) << 16 | (depth)) +static void mt792x_dma_prefetch(struct mt792x_dev *dev) +{ + mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4)); + + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); +} + +int mt792x_dma_enable(struct mt792x_dev *dev) +{ + /* configure perfetch settings */ + mt792x_dma_prefetch(dev); + + /* reset dma idx */ + mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); + + /* configure delay interrupt */ + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); + + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_WB_DDONE | + MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | + MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); + + /* enable interrupts for TX/RX rings */ + mt76_connac_irq_enable(&dev->mt76, + dev->irq_map->tx.all_complete_mask | + dev->irq_map->rx.data_complete_mask | + dev->irq_map->rx.wm2_complete_mask | + dev->irq_map->rx.wm_complete_mask | + MT_INT_MCU_CMD); + mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_dma_enable); + +static int +mt792x_dma_reset(struct mt792x_dev *dev, bool force) +{ + int i, err; + + err = mt792x_dma_disable(dev, force); + if (err) + return err; + + /* reset hw queues */ + for (i = 0; i < __MT_TXQ_MAX; i++) + mt76_queue_reset(dev, dev->mphy.q_tx[i]); + + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_reset(dev, dev->mt76.q_mcu[i]); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_reset(dev, &dev->mt76.q_rx[i]); + + mt76_tx_status_check(&dev->mt76, true); + + return mt792x_dma_enable(dev); +} + +int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force) +{ + int i, err; + + /* clean up hw queues */ + for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); + + if (force) { + err = mt792x_wfsys_reset(dev); + if (err) + return err; + } + err = mt792x_dma_reset(dev, force); + if (err) + return err; + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_reset(dev, i); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_wpdma_reset); + +int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev) +{ + struct mt76_connac_pm *pm = &dev->pm; + int err; + + /* check if the wpdma must be reinitialized */ + if (mt792x_dma_need_reinit(dev)) { + /* disable interrutpts */ + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); + + err = mt792x_wpdma_reset(dev, false); + if (err) { + dev_err(dev->mt76.dev, "wpdma reset failed\n"); + return err; + } + + /* enable interrutpts */ + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + pm->stats.lp_wake++; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_wpdma_reinit_cond); + +int mt792x_dma_disable(struct mt792x_dev *dev, bool force) +{ + /* disable WFDMA0 */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) + return -ETIMEDOUT; + + /* disable dmashdl */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + if (force) { + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_dma_disable); + +void mt792x_dma_cleanup(struct mt792x_dev *dev) +{ + /* disable */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1); + + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_dma_cleanup(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792x_dma_cleanup); + +int mt792x_poll_tx(struct napi_struct *napi, int budget) +{ + struct mt792x_dev *dev; + + dev = container_of(napi, struct mt792x_dev, mt76.tx_napi); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + + mt76_connac_tx_cleanup(&dev->mt76); + if (napi_complete(napi)) + mt76_connac_irq_enable(&dev->mt76, + dev->irq_map->tx.all_complete_mask); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_poll_tx); + +int mt792x_poll_rx(struct napi_struct *napi, int budget) +{ + struct mt792x_dev *dev; + int done; + + dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + done = mt76_dma_rx_poll(napi, budget); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); + + return done; +} +EXPORT_SYMBOL_GPL(mt792x_poll_rx); + +int mt792x_wfsys_reset(struct mt792x_dev *dev) +{ + u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140; + + mt76_clear(dev, addr, WFSYS_SW_RST_B); + msleep(50); + mt76_set(dev, addr, WFSYS_SW_RST_B); + + if (!__mt76_poll_msec(&dev->mt76, addr, WFSYS_SW_INIT_DONE, + WFSYS_SW_INIT_DONE, 500)) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_wfsys_reset); + -- cgit From 5c041325cd0b1307b196c686f87f8531d4d3f105 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:15 +0800 Subject: wifi: mt76: mt7921: move hif_ops macro in mt792x.h Move the following hif_ops macro in mt792x.h: - mt7925_init_reset - mt7925_dev_reset - mt7925_mcu_init - __mt7925_mcu_drv_pmctrl - __mt7925_mcu_fw_pmctrl Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 6 ------ drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/testmode.c | 2 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 6 ++++++ 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 0a6f8f42b2e4..6b8e31110fdf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -107,7 +107,7 @@ static int __mt7921_init_hardware(struct mt792x_dev *dev) * which should be set before firmware download stage. */ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - ret = mt7921_mcu_init(dev); + ret = mt792x_mcu_init(dev); if (ret) goto out; @@ -133,7 +133,7 @@ static int mt7921_init_hardware(struct mt792x_dev *dev) if (!ret) break; - mt7921_init_reset(dev); + mt792x_init_reset(dev); } if (i == MT7921_MCU_INIT_RETRY_COUNT) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 70382194825a..25d853a75a23 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -672,7 +672,7 @@ void mt7921_mac_reset_work(struct work_struct *work) for (i = 0; i < 10; i++) { mutex_lock(&dev->mt76.mutex); - ret = mt7921_dev_reset(dev); + ret = mt792x_dev_reset(dev); mutex_unlock(&dev->mt76.mutex); if (!ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index ed02fa48841c..9bfa79893b10 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -482,9 +482,9 @@ static int mt7921_load_firmware(struct mt792x_dev *dev) if (mt76_is_sdio(&dev->mt76)) { /* activate again */ - ret = __mt7921_mcu_fw_pmctrl(dev); + ret = __mt792x_mcu_fw_pmctrl(dev); if (!ret) - ret = __mt7921_mcu_drv_pmctrl(dev); + ret = __mt792x_mcu_drv_pmctrl(dev); } ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL); @@ -953,7 +953,7 @@ int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev) if (!test_bit(MT76_STATE_PM, &mphy->state)) goto out; - err = __mt7921_mcu_drv_pmctrl(dev); + err = __mt792x_mcu_drv_pmctrl(dev); out: mutex_unlock(&pm->mutex); @@ -975,7 +975,7 @@ int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev) if (mt76_connac_skip_fw_pmctrl(mphy, pm)) goto out; - err = __mt7921_mcu_fw_pmctrl(dev); + err = __mt792x_mcu_fw_pmctrl(dev); out: mutex_unlock(&pm->mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index b797d8bab5e2..86b8c98e3f69 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -159,12 +159,6 @@ enum mt7921_eeprom_field { #define MT_EE_HW_TYPE_ENCAP BIT(0) -#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) -#define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev)) -#define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) -#define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) -#define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) - enum { TXPWR_USER, TXPWR_EEPROM, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index d11406c87df7..7e9bb1879f9c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -46,7 +46,7 @@ static void mt7921e_unregister_device(struct mt792x_dev *dev) cancel_work_sync(&dev->reset_work); mt76_connac2_tx_token_put(&dev->mt76); - __mt7921_mcu_drv_pmctrl(dev); + __mt792x_mcu_drv_pmctrl(dev); mt792x_dma_cleanup(dev); mt792x_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c index 3c2165095ddd..e838d93477c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c @@ -57,7 +57,7 @@ mt7921_tm_set(struct mt792x_dev *dev, struct mt7921_tm_cmd *req) pm->enable = false; cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - __mt7921_mcu_drv_pmctrl(dev); + __mt792x_mcu_drv_pmctrl(dev); phy->test.state = MT76_TM_STATE_ON; } diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 894fb0fe8cba..1c2829cd954d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -127,6 +127,12 @@ struct mt792x_irq_map { } rx; }; +#define mt792x_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) +#define mt792x_dev_reset(dev) ((dev)->hif_ops->reset(dev)) +#define mt792x_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) +#define __mt792x_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) +#define __mt792x_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) + struct mt792x_hif_ops { int (*init_reset)(struct mt792x_dev *dev); int (*reset)(struct mt792x_dev *dev); -- cgit From c21a7f9f406bba3f7ee8ce788ef48592c8c3ba8f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:16 +0800 Subject: wifi: mt76: mt7921: move shared runtime-pm code on mt792x-lib Moving hif_ops marcos in mt792x.h, we can move shared runtime-pm code between mt7925 and mt7921 in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 70 --------------------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 44 ------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 4 -- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 6 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 6 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 4 ++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 44 +++++++++++++ drivers/net/wireless/mediatek/mt76/mt792x_mac.c | 72 ++++++++++++++++++++++ 9 files changed, 128 insertions(+), 126 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 6b8e31110fdf..c47fb07fcb2e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -192,8 +192,8 @@ int mt7921_register_device(struct mt792x_dev *dev) dev->mt76.phy.priv = &dev->phy; dev->mt76.tx_worker.fn = mt792x_tx_worker; - INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work); - INIT_WORK(&dev->pm.wake_work, mt7921_pm_wake_work); + INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work); + INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work); spin_lock_init(&dev->pm.wake.lock); mutex_init(&dev->pm.mutex); init_waitqueue_head(&dev->pm.wait); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 25d853a75a23..21f937454229 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -699,76 +699,6 @@ void mt7921_mac_reset_work(struct work_struct *work) mt76_connac_power_save_sched(&dev->mt76.phy, pm); } -void mt7921_pm_wake_work(struct work_struct *work) -{ - struct mt792x_dev *dev; - struct mt76_phy *mphy; - - dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, - pm.wake_work); - mphy = dev->phy.mt76; - - if (!mt7921_mcu_drv_pmctrl(dev)) { - struct mt76_dev *mdev = &dev->mt76; - int i; - - if (mt76_is_sdio(mdev)) { - mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - mt76_worker_schedule(&mdev->sdio.txrx_worker); - } else { - local_bh_disable(); - mt76_for_each_q_rx(mdev, i) - napi_schedule(&mdev->napi[i]); - local_bh_enable(); - mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - mt76_connac_tx_cleanup(mdev); - } - if (test_bit(MT76_STATE_RUNNING, &mphy->state)) - ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, - MT792x_WATCHDOG_TIME); - } - - ieee80211_wake_queues(mphy->hw); - wake_up(&dev->pm.wait); -} - -void mt7921_pm_power_save_work(struct work_struct *work) -{ - struct mt792x_dev *dev; - unsigned long delta; - struct mt76_phy *mphy; - - dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, - pm.ps_work.work); - mphy = dev->phy.mt76; - - delta = dev->pm.idle_timeout; - if (test_bit(MT76_HW_SCANNING, &mphy->state) || - test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) || - dev->fw_assert) - goto out; - - if (mutex_is_locked(&dev->mt76.mutex)) - /* if mt76 mutex is held we should not put the device - * to sleep since we are currently accessing device - * register map. We need to wait for the next power_save - * trigger. - */ - goto out; - - if (time_is_after_jiffies(dev->pm.last_activity + delta)) { - delta = dev->pm.last_activity + delta - jiffies; - goto out; - } - - if (!mt7921_mcu_fw_pmctrl(dev)) { - cancel_delayed_work_sync(&mphy->mac_work); - return; - } -out: - queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta); -} - void mt7921_coredump_work(struct work_struct *work) { struct mt792x_dev *dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 9bfa79893b10..bd40ca489447 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -942,50 +942,6 @@ int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, return mt76_connac_mcu_sta_cmd(&dev->mphy, &info); } -int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err = 0; - - mutex_lock(&pm->mutex); - - if (!test_bit(MT76_STATE_PM, &mphy->state)) - goto out; - - err = __mt792x_mcu_drv_pmctrl(dev); -out: - mutex_unlock(&pm->mutex); - - if (err) - mt792x_reset(&dev->mt76); - - return err; -} -EXPORT_SYMBOL_GPL(mt7921_mcu_drv_pmctrl); - -int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err = 0; - - mutex_lock(&pm->mutex); - - if (mt76_connac_skip_fw_pmctrl(mphy, pm)) - goto out; - - err = __mt792x_mcu_fw_pmctrl(dev); -out: - mutex_unlock(&pm->mutex); - - if (err) - mt792x_reset(&dev->mt76); - - return err; -} -EXPORT_SYMBOL_GPL(mt7921_mcu_fw_pmctrl); - int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 86b8c98e3f69..4a3416a28711 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -297,10 +297,6 @@ int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, void mt7921_scan_work(struct work_struct *work); void mt7921_roc_work(struct work_struct *work); int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); -int mt7921_mcu_drv_pmctrl(struct mt792x_dev *dev); -int mt7921_mcu_fw_pmctrl(struct mt792x_dev *dev); -void mt7921_pm_wake_work(struct work_struct *work); -void mt7921_pm_power_save_work(struct work_struct *work); void mt7921_coredump_work(struct work_struct *work); int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr); int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 7e9bb1879f9c..7419076b77cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -337,7 +337,7 @@ static int mt7921_pci_suspend(struct device *device) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; @@ -372,7 +372,7 @@ static int mt7921_pci_suspend(struct device *device) synchronize_irq(pdev->irq); tasklet_kill(&mdev->irq_tasklet); - err = mt7921_mcu_fw_pmctrl(dev); + err = mt792x_mcu_fw_pmctrl(dev); if (err) goto restore_napi; @@ -406,7 +406,7 @@ static int mt7921_pci_resume(struct device *device) struct mt76_connac_pm *pm = &dev->pm; int i, err; - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto failed; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 84b388656941..dc1beb76df3e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -216,7 +216,7 @@ static int mt7921s_suspend(struct device *__dev) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; @@ -244,7 +244,7 @@ static int mt7921s_suspend(struct device *__dev) mt76_worker_disable(&mdev->sdio.txrx_worker); mt76_worker_disable(&mdev->sdio.net_worker); - err = mt7921_mcu_fw_pmctrl(dev); + err = mt792x_mcu_fw_pmctrl(dev); if (err) goto restore_txrx_worker; @@ -284,7 +284,7 @@ static int mt7921s_resume(struct device *__dev) clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto failed; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 1c2829cd954d..470017f6f982 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -215,6 +215,8 @@ static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev) #define mt792x_mutex_release(dev) \ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) +void mt792x_pm_wake_work(struct work_struct *work); +void mt792x_pm_power_save_work(struct work_struct *work); void mt792x_reset(struct mt76_dev *mdev); void mt792x_update_channel(struct mt76_phy *mphy); void mt792x_mac_reset_counters(struct mt792x_phy *phy); @@ -284,5 +286,7 @@ mt792x_get_mac80211_ops(struct device *dev, const struct ieee80211_ops *mac80211_ops, void *drv_data, u8 *fw_features); int mt792x_init_wcid(struct mt792x_dev *dev); +int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index a4aa9694de7f..234aac4e3742 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -692,5 +692,49 @@ int mt792x_init_wcid(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792x_init_wcid); +int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err = 0; + + mutex_lock(&pm->mutex); + + if (!test_bit(MT76_STATE_PM, &mphy->state)) + goto out; + + err = __mt792x_mcu_drv_pmctrl(dev); +out: + mutex_unlock(&pm->mutex); + + if (err) + mt792x_reset(&dev->mt76); + + return err; +} +EXPORT_SYMBOL_GPL(mt792x_mcu_drv_pmctrl); + +int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err = 0; + + mutex_lock(&pm->mutex); + + if (mt76_connac_skip_fw_pmctrl(mphy, pm)) + goto out; + + err = __mt792x_mcu_fw_pmctrl(dev); +out: + mutex_unlock(&pm->mutex); + + if (err) + mt792x_reset(&dev->mt76); + + return err; +} +EXPORT_SYMBOL_GPL(mt792x_mcu_fw_pmctrl); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c index 9603c4eedb2b..5d1f8229fdc1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -311,3 +311,75 @@ void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band) mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); } EXPORT_SYMBOL_GPL(mt792x_mac_init_band); + +void mt792x_pm_wake_work(struct work_struct *work) +{ + struct mt792x_dev *dev; + struct mt76_phy *mphy; + + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, + pm.wake_work); + mphy = dev->phy.mt76; + + if (!mt792x_mcu_drv_pmctrl(dev)) { + struct mt76_dev *mdev = &dev->mt76; + int i; + + if (mt76_is_sdio(mdev)) { + mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); + mt76_worker_schedule(&mdev->sdio.txrx_worker); + } else { + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) + napi_schedule(&mdev->napi[i]); + local_bh_enable(); + mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); + mt76_connac_tx_cleanup(mdev); + } + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT792x_WATCHDOG_TIME); + } + + ieee80211_wake_queues(mphy->hw); + wake_up(&dev->pm.wait); +} +EXPORT_SYMBOL_GPL(mt792x_pm_wake_work); + +void mt792x_pm_power_save_work(struct work_struct *work) +{ + struct mt792x_dev *dev; + unsigned long delta; + struct mt76_phy *mphy; + + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, + pm.ps_work.work); + mphy = dev->phy.mt76; + + delta = dev->pm.idle_timeout; + if (test_bit(MT76_HW_SCANNING, &mphy->state) || + test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) || + dev->fw_assert) + goto out; + + if (mutex_is_locked(&dev->mt76.mutex)) + /* if mt76 mutex is held we should not put the device + * to sleep since we are currently accessing device + * register map. We need to wait for the next power_save + * trigger. + */ + goto out; + + if (time_is_after_jiffies(dev->pm.last_activity + delta)) { + delta = dev->pm.last_activity + delta - jiffies; + goto out; + } + + if (!mt792x_mcu_fw_pmctrl(dev)) { + cancel_delayed_work_sync(&mphy->mac_work); + return; + } +out: + queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta); +} +EXPORT_SYMBOL_GPL(mt792x_pm_power_save_work); -- cgit From 1c0254967d94bf5826ae5ea5f84960172db955ff Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:17 +0800 Subject: wifi: mt76: mt7921: move runtime-pm pci code in mt792x-lib Move the following runtime-pm pci routines in mt792x-lib since they are shared between mt7921 and mt7925 chipsets: - __mt7921e_mcu_drv_pmctrl - mt7921e_mcu_drv_pmctrl - mt7921e_mcu_fw_pmctrl Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 7 --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 8 +-- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/pci_mcu.c | 65 --------------------- .../net/wireless/mediatek/mt76/mt7921/usb_mac.c | 4 +- drivers/net/wireless/mediatek/mt76/mt792x.h | 8 +++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 68 ++++++++++++++++++++++ 8 files changed, 85 insertions(+), 81 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index c47fb07fcb2e..3ff0205919c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -128,7 +128,7 @@ static int mt7921_init_hardware(struct mt792x_dev *dev) set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - for (i = 0; i < MT7921_MCU_INIT_RETRY_COUNT; i++) { + for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) { ret = __mt7921_init_hardware(dev); if (!ret) break; @@ -136,7 +136,7 @@ static int mt7921_init_hardware(struct mt792x_dev *dev) mt792x_init_reset(dev); } - if (i == MT7921_MCU_INIT_RETRY_COUNT) { + if (i == MT792x_MCU_INIT_RETRY_COUNT) { dev_err(dev->mt76.dev, "hardware init failed\n"); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 4a3416a28711..0c60a1559041 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -18,10 +18,6 @@ #define MT7921_RX_RING_SIZE 1536 #define MT7921_RX_MCU_RING_SIZE 512 -#define MT7921_DRV_OWN_RETRY_COUNT 10 -#define MT7921_MCU_INIT_RETRY_COUNT 10 -#define MT7921_WFSYS_INIT_RETRY_COUNT 2 - #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" @@ -312,9 +308,6 @@ int mt7921e_mcu_init(struct mt792x_dev *dev); int mt7921s_wfsys_reset(struct mt792x_dev *dev); int mt7921s_mac_reset(struct mt792x_dev *dev); int mt7921s_init_reset(struct mt792x_dev *dev); -int __mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev); -int mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev); -int mt7921e_mcu_fw_pmctrl(struct mt792x_dev *dev); int mt7921s_mcu_init(struct mt792x_dev *dev); int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 7419076b77cb..c3f22ce9f5c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -181,8 +181,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .init_reset = mt7921e_init_reset, .reset = mt7921e_mac_reset, .mcu_init = mt7921e_mcu_init, - .drv_own = mt7921e_mcu_drv_pmctrl, - .fw_own = mt7921e_mcu_fw_pmctrl, + .drv_own = mt792xe_mcu_drv_pmctrl, + .fw_own = mt792xe_mcu_fw_pmctrl, }; static const struct mt792x_irq_map irq_map = { .host_irq_enable = MT_WFDMA0_HOST_INT_ENA, @@ -268,11 +268,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev, bus_ops->rmw = mt7921_rmw; dev->mt76.bus = bus_ops; - ret = mt7921e_mcu_fw_pmctrl(dev); + ret = mt792xe_mcu_fw_pmctrl(dev); if (ret) goto err_free_dev; - ret = __mt7921e_mcu_drv_pmctrl(dev); + ret = __mt792xe_mcu_drv_pmctrl(dev); if (ret) goto err_free_dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index bd3f004d1a18..e7a995e7e70a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -57,7 +57,7 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) { int i, err; - mt7921e_mcu_drv_pmctrl(dev); + mt792xe_mcu_drv_pmctrl(dev); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c index 57bd02746f5f..4cf1f2f0f968 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c @@ -61,68 +61,3 @@ int mt7921e_mcu_init(struct mt792x_dev *dev) return err; } - -int __mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev) -{ - int i, err = 0; - - for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { - mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); - if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, - PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) - break; - } - - if (i == MT7921_DRV_OWN_RETRY_COUNT) { - dev_err(dev->mt76.dev, "driver own failed\n"); - err = -EIO; - } - - return err; -} - -int mt7921e_mcu_drv_pmctrl(struct mt792x_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err; - - err = __mt7921e_mcu_drv_pmctrl(dev); - if (err < 0) - goto out; - - mt792x_wpdma_reinit_cond(dev); - clear_bit(MT76_STATE_PM, &mphy->state); - - pm->stats.last_wake_event = jiffies; - pm->stats.doze_time += pm->stats.last_wake_event - - pm->stats.last_doze_event; -out: - return err; -} - -int mt7921e_mcu_fw_pmctrl(struct mt792x_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int i; - - for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { - mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN); - if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, - PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1)) - break; - } - - if (i == MT7921_DRV_OWN_RETRY_COUNT) { - dev_err(dev->mt76.dev, "firmware own failed\n"); - clear_bit(MT76_STATE_PM, &mphy->state); - return -EIO; - } - - pm->stats.last_doze_event = jiffies; - pm->stats.awake_time += pm->stats.last_doze_event - - pm->stats.last_wake_event; - - return 0; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c index f612873c704b..f7cb6c542af5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -166,7 +166,7 @@ int mt7921u_wfsys_reset(struct mt792x_dev *dev) mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); - for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) { + for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) { val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) break; @@ -174,7 +174,7 @@ int mt7921u_wfsys_reset(struct mt792x_dev *dev) msleep(100); } - if (i == MT7921_WFSYS_INIT_RETRY_COUNT) + if (i == MT792x_WFSYS_INIT_RETRY_COUNT) return -ETIMEDOUT; return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 470017f6f982..54ff9627530f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -26,6 +26,10 @@ #define MT792x_WATCHDOG_TIME (HZ / 4) +#define MT792x_DRV_OWN_RETRY_COUNT 10 +#define MT792x_MCU_INIT_RETRY_COUNT 10 +#define MT792x_WFSYS_INIT_RETRY_COUNT 2 + struct mt792x_vif; struct mt792x_sta; @@ -289,4 +293,8 @@ int mt792x_init_wcid(struct mt792x_dev *dev); int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); +int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev); + #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index 234aac4e3742..f7dfc2189cc8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -736,5 +736,73 @@ out: } EXPORT_SYMBOL_GPL(mt792x_mcu_fw_pmctrl); +int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + int i, err = 0; + + for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { + mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, + PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) + break; + } + + if (i == MT792x_DRV_OWN_RETRY_COUNT) { + dev_err(dev->mt76.dev, "driver own failed\n"); + err = -EIO; + } + + return err; +} +EXPORT_SYMBOL_GPL(__mt792xe_mcu_drv_pmctrl); + +int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err; + + err = __mt792xe_mcu_drv_pmctrl(dev); + if (err < 0) + goto out; + + mt792x_wpdma_reinit_cond(dev); + clear_bit(MT76_STATE_PM, &mphy->state); + + pm->stats.last_wake_event = jiffies; + pm->stats.doze_time += pm->stats.last_wake_event - + pm->stats.last_doze_event; +out: + return err; +} +EXPORT_SYMBOL_GPL(mt792xe_mcu_drv_pmctrl); + +int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int i; + + for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { + mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, + PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1)) + break; + } + + if (i == MT792x_DRV_OWN_RETRY_COUNT) { + dev_err(dev->mt76.dev, "firmware own failed\n"); + clear_bit(MT76_STATE_PM, &mphy->state); + return -EIO; + } + + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xe_mcu_fw_pmctrl); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); -- cgit From 29f5a494f7a22ab4661dc835c1d208e1a61793e7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:18 +0800 Subject: wifi: mt76: mt7921: move acpi_sar code in mt792x-lib module Move acpi_sar code in mt792x-lib module since it is shared between mt7921 and mt7925 driver. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 1 + drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 1 - .../net/wireless/mediatek/mt76/mt7921/acpi_sar.c | 341 -------------------- .../net/wireless/mediatek/mt76/mt7921/acpi_sar.h | 105 ------- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 11 +- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 24 -- drivers/net/wireless/mediatek/mt76/mt792x.h | 23 ++ .../net/wireless/mediatek/mt76/mt792x_acpi_sar.c | 350 +++++++++++++++++++++ .../net/wireless/mediatek/mt76/mt792x_acpi_sar.h | 105 +++++++ 11 files changed, 485 insertions(+), 480 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index d6231948dd6e..f8a1928d62b2 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -33,6 +33,7 @@ mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \ mt792x_debugfs.o mt792x_dma.o +mt792x-lib-$(CONFIG_ACPI) += mt792x_acpi_sar.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index fd82dff76dae..f380ec4b6de1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_MT7921U) += mt7921u.o mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o -mt7921-common-$(CONFIG_ACPI) += acpi_sar.o mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o mt7921u-y := usb.o usb_mac.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c deleted file mode 100644 index 057767ab45ff..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ /dev/null @@ -1,341 +0,0 @@ -// SPDX-License-Identifier: ISC -/* Copyright (C) 2022 MediaTek Inc. */ - -#include -#include "mt7921.h" - -static int -mt7921_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) -{ - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *sar_root, *sar_unit; - struct mt76_dev *mdev = &dev->mt76; - acpi_handle root, handle; - acpi_status status; - u32 i = 0; - int ret; - - root = ACPI_HANDLE(mdev->dev); - if (!root) - return -EOPNOTSUPP; - - status = acpi_get_handle(root, method, &handle); - if (ACPI_FAILURE(status)) - return -EIO; - - status = acpi_evaluate_object(handle, NULL, NULL, &buf); - if (ACPI_FAILURE(status)) - return -EIO; - - sar_root = buf.pointer; - if (sar_root->type != ACPI_TYPE_PACKAGE || - sar_root->package.count < 4 || - sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) { - dev_err(mdev->dev, "sar cnt = %d\n", - sar_root->package.count); - ret = -EINVAL; - goto free; - } - - if (!*tbl) { - *tbl = devm_kzalloc(mdev->dev, sar_root->package.count, - GFP_KERNEL); - if (!*tbl) { - ret = -ENOMEM; - goto free; - } - } - if (len) - *len = sar_root->package.count; - - for (i = 0; i < sar_root->package.count; i++) { - sar_unit = &sar_root->package.elements[i]; - - if (sar_unit->type != ACPI_TYPE_INTEGER) - break; - *(*tbl + i) = (u8)sar_unit->integer.value; - } - ret = (i == sar_root->package.count) ? 0 : -EINVAL; - -free: - kfree(sar_root); - - return ret; -} - -/* MTCL : Country List Table for 6G band */ -static int -mt7921_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) -{ - *version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0) - ? 1 : 2; - return 0; -} - -/* MTDS : Dynamic SAR Power Table */ -static int -mt7921_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version) -{ - int len, ret, sarlen, prelen, tblcnt; - bool enable; - - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len); - if (ret) - return ret; - - /* Table content validation */ - switch (version) { - case 1: - enable = ((struct mt7921_asar_dyn *)*table)->enable; - sarlen = sizeof(struct mt7921_asar_dyn_limit); - prelen = sizeof(struct mt7921_asar_dyn); - break; - case 2: - enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable; - sarlen = sizeof(struct mt7921_asar_dyn_limit_v2); - prelen = sizeof(struct mt7921_asar_dyn_v2); - break; - default: - return -EINVAL; - } - - tblcnt = (len - prelen) / sarlen; - if (!enable || - tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN) - ret = -EINVAL; - - return ret; -} - -/* MTGS : Geo SAR Power Table */ -static int -mt7921_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version) -{ - int len, ret = 0, sarlen, prelen, tblcnt; - - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len); - if (ret) - return ret; - - /* Table content validation */ - switch (version) { - case 1: - sarlen = sizeof(struct mt7921_asar_geo_limit); - prelen = sizeof(struct mt7921_asar_geo); - break; - case 2: - sarlen = sizeof(struct mt7921_asar_geo_limit_v2); - prelen = sizeof(struct mt7921_asar_geo_v2); - break; - default: - return -EINVAL; - } - - tblcnt = (len - prelen) / sarlen; - if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO) - ret = -EINVAL; - - return ret; -} - -/* MTFG : Flag Table */ -static int -mt7921_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table) -{ - int len, ret; - - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len); - if (ret) - return ret; - - if (len < MT7921_ASAR_MIN_FG) - ret = -EINVAL; - - return ret; -} - -int mt7921_init_acpi_sar(struct mt792x_dev *dev) -{ - struct mt7921_acpi_sar *asar; - int ret; - - asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL); - if (!asar) - return -ENOMEM; - - mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); - - /* MTDS is mandatory. Return error if table is invalid */ - ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); - if (ret) { - devm_kfree(dev->mt76.dev, asar->dyn); - devm_kfree(dev->mt76.dev, asar->countrylist); - devm_kfree(dev->mt76.dev, asar); - return ret; - } - - /* MTGS is optional */ - ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver); - if (ret) { - devm_kfree(dev->mt76.dev, asar->geo); - asar->geo = NULL; - } - - /* MTFG is optional */ - ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg); - if (ret) { - devm_kfree(dev->mt76.dev, asar->fg); - asar->fg = NULL; - } - dev->phy.acpisar = asar; - - return 0; -} - -static s8 -mt7921_asar_get_geo_pwr(struct mt792x_phy *phy, - enum nl80211_band band, s8 dyn_power) -{ - struct mt7921_acpi_sar *asar = phy->acpisar; - struct mt7921_asar_geo_band *band_pwr; - s8 geo_power; - u8 idx, max; - - if (!asar->geo) - return dyn_power; - - switch (phy->mt76->dev->region) { - case NL80211_DFS_FCC: - idx = 0; - break; - case NL80211_DFS_ETSI: - idx = 1; - break; - default: /* WW */ - idx = 2; - break; - } - - if (asar->ver == 1) { - band_pwr = &asar->geo->tbl[idx].band[0]; - max = ARRAY_SIZE(asar->geo->tbl[idx].band); - } else { - band_pwr = &asar->geo_v2->tbl[idx].band[0]; - max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band); - } - - switch (band) { - case NL80211_BAND_2GHZ: - idx = 0; - break; - case NL80211_BAND_5GHZ: - idx = 1; - break; - case NL80211_BAND_6GHZ: - idx = 2; - break; - default: - return dyn_power; - } - - if (idx >= max) - return dyn_power; - - geo_power = (band_pwr + idx)->pwr; - dyn_power += (band_pwr + idx)->offset; - - return min(geo_power, dyn_power); -} - -static s8 -mt7921_asar_range_pwr(struct mt792x_phy *phy, - const struct cfg80211_sar_freq_ranges *range, - u8 idx) -{ - const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; - struct mt7921_acpi_sar *asar = phy->acpisar; - u8 *limit, band, max; - - if (!capa) - return 127; - - if (asar->ver == 1) { - limit = &asar->dyn->tbl[0].frp[0]; - max = ARRAY_SIZE(asar->dyn->tbl[0].frp); - } else { - limit = &asar->dyn_v2->tbl[0].frp[0]; - max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp); - } - - if (idx >= max) - return 127; - - if (range->start_freq >= 5945) - band = NL80211_BAND_6GHZ; - else if (range->start_freq >= 5150) - band = NL80211_BAND_5GHZ; - else - band = NL80211_BAND_2GHZ; - - return mt7921_asar_get_geo_pwr(phy, band, limit[idx]); -} - -int mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) -{ - const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; - int i; - - if (!phy->acpisar) - return 0; - - /* When ACPI SAR enabled in HW, we should apply rules for .frp - * 1. w/o .sar_specs : set ACPI SAR power as the defatul value - * 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR) - */ - for (i = 0; i < capa->num_freq_ranges; i++) { - struct mt76_freq_range_power *frp = &phy->mt76->frp[i]; - - frp->range = set_default ? &capa->freq_ranges[i] : frp->range; - if (!frp->range) - continue; - - frp->power = min_t(s8, set_default ? 127 : frp->power, - mt7921_asar_range_pwr(phy, frp->range, i)); - } - - return 0; -} - -u8 mt7921_acpi_get_flags(struct mt792x_phy *phy) -{ - struct mt7921_acpi_sar *acpisar = phy->acpisar; - struct mt7921_asar_fg *fg; - struct { - u8 acpi_idx; - u8 chip_idx; - } map[] = { - {1, 1}, - {4, 2}, - }; - u8 flags = BIT(0); - int i, j; - - if (!acpisar) - return 0; - - fg = acpisar->fg; - if (!fg) - return flags; - - /* pickup necessary settings per device and - * translate the index of bitmap for chip command. - */ - for (i = 0; i < fg->nr_flag; i++) - for (j = 0; j < ARRAY_SIZE(map); j++) - if (fg->flag[i] == map[j].acpi_idx) { - flags |= BIT(map[j].chip_idx); - break; - } - - return flags; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h deleted file mode 100644 index 6f2c4a572572..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* Copyright (C) 2022 MediaTek Inc. */ - -#ifndef __MT7921_ACPI_SAR_H -#define __MT7921_ACPI_SAR_H - -#define MT7921_ASAR_MIN_DYN 1 -#define MT7921_ASAR_MAX_DYN 8 -#define MT7921_ASAR_MIN_GEO 3 -#define MT7921_ASAR_MAX_GEO 8 -#define MT7921_ASAR_MIN_FG 8 - -#define MT7921_ACPI_MTCL "MTCL" -#define MT7921_ACPI_MTDS "MTDS" -#define MT7921_ACPI_MTGS "MTGS" -#define MT7921_ACPI_MTFG "MTFG" - -struct mt7921_asar_dyn_limit { - u8 idx; - u8 frp[5]; -} __packed; - -struct mt7921_asar_dyn { - u8 names[4]; - u8 enable; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl); -} __packed; - -struct mt7921_asar_dyn_limit_v2 { - u8 idx; - u8 frp[11]; -} __packed; - -struct mt7921_asar_dyn_v2 { - u8 names[4]; - u8 enable; - u8 rsvd; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl); -} __packed; - -struct mt7921_asar_geo_band { - u8 pwr; - u8 offset; -} __packed; - -struct mt7921_asar_geo_limit { - u8 idx; - /* 0:2G, 1:5G */ - struct mt7921_asar_geo_band band[2]; -} __packed; - -struct mt7921_asar_geo { - u8 names[4]; - u8 version; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl); -} __packed; - -struct mt7921_asar_geo_limit_v2 { - u8 idx; - /* 0:2G, 1:5G, 2:6G */ - struct mt7921_asar_geo_band band[3]; -} __packed; - -struct mt7921_asar_geo_v2 { - u8 names[4]; - u8 version; - u8 rsvd; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl); -} __packed; - -struct mt7921_asar_cl { - u8 names[4]; - u8 version; - u8 mode_6g; - u8 cl6g[6]; -} __packed; - -struct mt7921_asar_fg { - u8 names[4]; - u8 version; - u8 rsvd; - u8 nr_flag; - u8 rsvd1; - u8 flag[]; -} __packed; - -struct mt7921_acpi_sar { - u8 ver; - union { - struct mt7921_asar_dyn *dyn; - struct mt7921_asar_dyn_v2 *dyn_v2; - }; - union { - struct mt7921_asar_geo *geo; - struct mt7921_asar_geo_v2 *geo_v2; - }; - struct mt7921_asar_cl *countrylist; - struct mt7921_asar_fg *fg; -}; - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 3ff0205919c2..7b8876bf8fc8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -230,7 +230,7 @@ int mt7921_register_device(struct mt792x_dev *dev) if (!mt76_is_mmio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - mt7921_init_acpi_sar(dev); + mt792x_init_acpi_sar(dev); ret = mt792x_init_wcid(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 73f29fed216f..0844d28b3223 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1153,19 +1153,16 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { struct mt76_phy *mphy = hw->priv; - int err; if (sar) { - err = mt76_init_sar_power(hw, sar); + int err = mt76_init_sar_power(hw, sar); + if (err) return err; } + mt792x_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); - mt7921_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); - - err = mt76_connac_mcu_set_rate_txpower(mphy); - - return err; + return mt76_connac_mcu_set_rate_txpower(mphy); } static int mt7921_set_sar_specs(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index bd40ca489447..e9caf750bca5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1197,7 +1197,7 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, } __packed req = { .idx = idx, .env = env_cap, - .acpi_conf = mt7921_acpi_get_flags(&dev->phy), + .acpi_conf = mt792x_acpi_get_flags(&dev->phy), }; int ret, valid_cnt = 0; u8 i, *pos; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 0c60a1559041..3ba873ec6bc4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -6,7 +6,6 @@ #include "../mt792x.h" #include "regs.h" -#include "acpi_sar.h" #define MT7921_PM_TIMEOUT (HZ / 12) #define MT7921_HW_SCAN_TIMEOUT (HZ / 10) @@ -345,29 +344,6 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable); -#ifdef CONFIG_ACPI -int mt7921_init_acpi_sar(struct mt792x_dev *dev); -int mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); -u8 mt7921_acpi_get_flags(struct mt792x_phy *phy); -#else -static inline int -mt7921_init_acpi_sar(struct mt792x_dev *dev) -{ - return 0; -} - -static inline int -mt7921_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) -{ - return 0; -} - -static inline u8 -mt7921_acpi_get_flags(struct mt792x_phy *phy) -{ - return 0; -} -#endif int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 54ff9627530f..1ed688186fe7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -9,6 +9,7 @@ #include "mt76_connac_mcu.h" #include "mt792x_regs.h" +#include "mt792x_acpi_sar.h" #define MT792x_MAX_INTERFACES 4 #define MT792x_WTBL_SIZE 20 @@ -297,4 +298,26 @@ int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev); +#ifdef CONFIG_ACPI +int mt792x_init_acpi_sar(struct mt792x_dev *dev); +int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); +u8 mt792x_acpi_get_flags(struct mt792x_phy *phy); +#else +static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev) +{ + return 0; +} + +static inline int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, + bool set_default) +{ + return 0; +} + +static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) +{ + return 0; +} +#endif + #endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c new file mode 100644 index 000000000000..303c0f5c9c66 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include +#include "mt792x.h" + +static int +mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + struct mt76_dev *mdev = &dev->mt76; + union acpi_object *sar_root; + acpi_handle root, handle; + acpi_status status; + u32 i = 0; + int ret; + + root = ACPI_HANDLE(mdev->dev); + if (!root) + return -EOPNOTSUPP; + + status = acpi_get_handle(root, method, &handle); + if (ACPI_FAILURE(status)) + return -EIO; + + status = acpi_evaluate_object(handle, NULL, NULL, &buf); + if (ACPI_FAILURE(status)) + return -EIO; + + sar_root = buf.pointer; + if (sar_root->type != ACPI_TYPE_PACKAGE || + sar_root->package.count < 4 || + sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) { + dev_err(mdev->dev, "sar cnt = %d\n", + sar_root->package.count); + ret = -EINVAL; + goto free; + } + + if (!*tbl) { + *tbl = devm_kzalloc(mdev->dev, sar_root->package.count, + GFP_KERNEL); + if (!*tbl) { + ret = -ENOMEM; + goto free; + } + } + + if (len) + *len = sar_root->package.count; + + for (i = 0; i < sar_root->package.count; i++) { + union acpi_object *sar_unit = &sar_root->package.elements[i]; + + if (sar_unit->type != ACPI_TYPE_INTEGER) + break; + + *(*tbl + i) = (u8)sar_unit->integer.value; + } + + ret = i == sar_root->package.count ? 0 : -EINVAL; +free: + kfree(sar_root); + + return ret; +} + +/* MTCL : Country List Table for 6G band */ +static void +mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) +{ + if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0) + *version = 1; + else + *version = 2; +} + +/* MTDS : Dynamic SAR Power Table */ +static int +mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version) +{ + int len, ret, sarlen, prelen, tblcnt; + bool enable; + + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len); + if (ret) + return ret; + + /* Table content validation */ + switch (version) { + case 1: + enable = ((struct mt792x_asar_dyn *)*table)->enable; + sarlen = sizeof(struct mt792x_asar_dyn_limit); + prelen = sizeof(struct mt792x_asar_dyn); + break; + case 2: + enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable; + sarlen = sizeof(struct mt792x_asar_dyn_limit_v2); + prelen = sizeof(struct mt792x_asar_dyn_v2); + break; + default: + return -EINVAL; + } + + tblcnt = (len - prelen) / sarlen; + if (!enable || + tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN) + return -EINVAL; + + return 0; +} + +/* MTGS : Geo SAR Power Table */ +static int +mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version) +{ + int len, ret, sarlen, prelen, tblcnt; + + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len); + if (ret) + return ret; + + /* Table content validation */ + switch (version) { + case 1: + sarlen = sizeof(struct mt792x_asar_geo_limit); + prelen = sizeof(struct mt792x_asar_geo); + break; + case 2: + sarlen = sizeof(struct mt792x_asar_geo_limit_v2); + prelen = sizeof(struct mt792x_asar_geo_v2); + break; + default: + return -EINVAL; + } + + tblcnt = (len - prelen) / sarlen; + if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO) + return -EINVAL; + + return 0; +} + +/* MTFG : Flag Table */ +static int +mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table) +{ + int len, ret; + + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len); + if (ret) + return ret; + + if (len < MT792x_ASAR_MIN_FG) + return -EINVAL; + + return 0; +} + +int mt792x_init_acpi_sar(struct mt792x_dev *dev) +{ + struct mt792x_acpi_sar *asar; + int ret; + + asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL); + if (!asar) + return -ENOMEM; + + mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + + /* MTDS is mandatory. Return error if table is invalid */ + ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->dyn); + devm_kfree(dev->mt76.dev, asar->countrylist); + devm_kfree(dev->mt76.dev, asar); + + return ret; + } + + /* MTGS is optional */ + ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->geo); + asar->geo = NULL; + } + + /* MTFG is optional */ + ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg); + if (ret) { + devm_kfree(dev->mt76.dev, asar->fg); + asar->fg = NULL; + } + dev->phy.acpisar = asar; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar); + +static s8 +mt792x_asar_get_geo_pwr(struct mt792x_phy *phy, + enum nl80211_band band, s8 dyn_power) +{ + struct mt792x_acpi_sar *asar = phy->acpisar; + struct mt792x_asar_geo_band *band_pwr; + s8 geo_power; + u8 idx, max; + + if (!asar->geo) + return dyn_power; + + switch (phy->mt76->dev->region) { + case NL80211_DFS_FCC: + idx = 0; + break; + case NL80211_DFS_ETSI: + idx = 1; + break; + default: /* WW */ + idx = 2; + break; + } + + if (asar->ver == 1) { + band_pwr = &asar->geo->tbl[idx].band[0]; + max = ARRAY_SIZE(asar->geo->tbl[idx].band); + } else { + band_pwr = &asar->geo_v2->tbl[idx].band[0]; + max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band); + } + + switch (band) { + case NL80211_BAND_2GHZ: + idx = 0; + break; + case NL80211_BAND_5GHZ: + idx = 1; + break; + case NL80211_BAND_6GHZ: + idx = 2; + break; + default: + return dyn_power; + } + + if (idx >= max) + return dyn_power; + + geo_power = (band_pwr + idx)->pwr; + dyn_power += (band_pwr + idx)->offset; + + return min(geo_power, dyn_power); +} + +static s8 +mt792x_asar_range_pwr(struct mt792x_phy *phy, + const struct cfg80211_sar_freq_ranges *range, + u8 idx) +{ + const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; + struct mt792x_acpi_sar *asar = phy->acpisar; + u8 *limit, band, max; + + if (!capa) + return 127; + + if (asar->ver == 1) { + limit = &asar->dyn->tbl[0].frp[0]; + max = ARRAY_SIZE(asar->dyn->tbl[0].frp); + } else { + limit = &asar->dyn_v2->tbl[0].frp[0]; + max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp); + } + + if (idx >= max) + return 127; + + if (range->start_freq >= 5945) + band = NL80211_BAND_6GHZ; + else if (range->start_freq >= 5150) + band = NL80211_BAND_5GHZ; + else + band = NL80211_BAND_2GHZ; + + return mt792x_asar_get_geo_pwr(phy, band, limit[idx]); +} + +int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) +{ + const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; + int i; + + if (!phy->acpisar) + return 0; + + /* When ACPI SAR enabled in HW, we should apply rules for .frp + * 1. w/o .sar_specs : set ACPI SAR power as the defatul value + * 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR) + */ + for (i = 0; i < capa->num_freq_ranges; i++) { + struct mt76_freq_range_power *frp = &phy->mt76->frp[i]; + + frp->range = set_default ? &capa->freq_ranges[i] : frp->range; + if (!frp->range) + continue; + + frp->power = min_t(s8, set_default ? 127 : frp->power, + mt792x_asar_range_pwr(phy, frp->range, i)); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power); + +u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) +{ + struct mt792x_acpi_sar *acpisar = phy->acpisar; + struct mt792x_asar_fg *fg; + struct { + u8 acpi_idx; + u8 chip_idx; + } map[] = { + { 1, 1 }, + { 4, 2 }, + }; + u8 flags = BIT(0); + int i, j; + + if (!acpisar) + return 0; + + fg = acpisar->fg; + if (!fg) + return flags; + + /* pickup necessary settings per device and + * translate the index of bitmap for chip command. + */ + for (i = 0; i < fg->nr_flag; i++) { + for (j = 0; j < ARRAY_SIZE(map); j++) { + if (fg->flag[i] == map[j].acpi_idx) { + flags |= BIT(map[j].chip_idx); + break; + } + } + } + + return flags; +} +EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h new file mode 100644 index 000000000000..d6d332e863ba --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7921_ACPI_SAR_H +#define __MT7921_ACPI_SAR_H + +#define MT792x_ASAR_MIN_DYN 1 +#define MT792x_ASAR_MAX_DYN 8 +#define MT792x_ASAR_MIN_GEO 3 +#define MT792x_ASAR_MAX_GEO 8 +#define MT792x_ASAR_MIN_FG 8 + +#define MT792x_ACPI_MTCL "MTCL" +#define MT792x_ACPI_MTDS "MTDS" +#define MT792x_ACPI_MTGS "MTGS" +#define MT792x_ACPI_MTFG "MTFG" + +struct mt792x_asar_dyn_limit { + u8 idx; + u8 frp[5]; +} __packed; + +struct mt792x_asar_dyn { + u8 names[4]; + u8 enable; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit, tbl); +} __packed; + +struct mt792x_asar_dyn_limit_v2 { + u8 idx; + u8 frp[11]; +} __packed; + +struct mt792x_asar_dyn_v2 { + u8 names[4]; + u8 enable; + u8 rsvd; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit_v2, tbl); +} __packed; + +struct mt792x_asar_geo_band { + u8 pwr; + u8 offset; +} __packed; + +struct mt792x_asar_geo_limit { + u8 idx; + /* 0:2G, 1:5G */ + struct mt792x_asar_geo_band band[2]; +} __packed; + +struct mt792x_asar_geo { + u8 names[4]; + u8 version; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit, tbl); +} __packed; + +struct mt792x_asar_geo_limit_v2 { + u8 idx; + /* 0:2G, 1:5G, 2:6G */ + struct mt792x_asar_geo_band band[3]; +} __packed; + +struct mt792x_asar_geo_v2 { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl); +} __packed; + +struct mt792x_asar_cl { + u8 names[4]; + u8 version; + u8 mode_6g; + u8 cl6g[6]; +} __packed; + +struct mt792x_asar_fg { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_flag; + u8 rsvd1; + u8 flag[]; +} __packed; + +struct mt792x_acpi_sar { + u8 ver; + union { + struct mt792x_asar_dyn *dyn; + struct mt792x_asar_dyn_v2 *dyn_v2; + }; + union { + struct mt792x_asar_geo *geo; + struct mt792x_asar_geo_v2 *geo_v2; + }; + struct mt792x_asar_cl *countrylist; + struct mt792x_asar_fg *fg; +}; + +#endif -- cgit From d28e1a48952e60fe47bba5b79fdbafc65f6c892b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:19 +0800 Subject: wifi: mt76: mt792x: introduce mt792x-usb module Add usb shared code between mt7921 and mt7925 chipset to mt792x-usb module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Kconfig | 4 + drivers/net/wireless/mediatek/mt76/Makefile | 2 + drivers/net/wireless/mediatek/mt76/mt7921/Kconfig | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 8 - drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 162 +++++------- .../net/wireless/mediatek/mt76/mt7921/usb_mac.c | 255 ------------------ drivers/net/wireless/mediatek/mt76/mt792x.h | 13 + drivers/net/wireless/mediatek/mt76/mt792x_usb.c | 292 +++++++++++++++++++++ 9 files changed, 380 insertions(+), 360 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt792x_usb.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 1ddf195597a8..7eb1b0b63d11 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -33,6 +33,10 @@ config MT792x_LIB tristate select MT76_CONNAC_LIB +config MT792x_USB + tristate + select MT76_USB + source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index f8a1928d62b2..85c4799be954 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o obj-$(CONFIG_MT792x_LIB) += mt792x-lib.o +obj-$(CONFIG_MT792x_USB) += mt792x-usb.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ @@ -34,6 +35,7 @@ mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \ mt792x_debugfs.o mt792x_dma.o mt792x-lib-$(CONFIG_ACPI) += mt792x_acpi_sar.o +mt792x-usb-y := mt792x_usb.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig index b92630cdf88b..7ed51e057857 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig @@ -27,7 +27,7 @@ config MT7921S config MT7921U tristate "MediaTek MT7921U (USB) support" - select MT76_USB + select MT792x_USB select MT7921_COMMON depends on MAC80211 depends on USB diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index f380ec4b6de1..964eb55824cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -9,4 +9,4 @@ mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o -mt7921u-y := usb.o usb_mac.o +mt7921u-y := usb.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 3ba873ec6bc4..cb22be083242 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -332,14 +332,6 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); /* usb */ -#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) -#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) - -int mt7921u_mcu_power_on(struct mt792x_dev *dev); -int mt7921u_wfsys_reset(struct mt792x_dev *dev); -int mt7921u_dma_init(struct mt792x_dev *dev, bool resume); -int mt7921u_init_reset(struct mt792x_dev *dev); -int mt7921u_mac_reset(struct mt792x_dev *dev); int mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 0a31e7076324..c3981bc893ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -24,83 +24,6 @@ static const struct usb_device_id mt7921u_device_table[] = { { }, }; -static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - -static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr, - u32 mask, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return val; -} - -static void mt7921u_copy(struct mt76_dev *dev, u32 offset, - const void *data, int len) -{ - struct mt76_usb *usb = &dev->usb; - int ret, i = 0, batch_len; - const u8 *val = data; - - len = round_up(len, 4); - - mutex_lock(&usb->usb_ctrl_mtx); - while (i < len) { - batch_len = min_t(int, usb->data_len, len - i); - memcpy(usb->data, val + i, batch_len); - ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, - (offset + i) >> 16, offset + i, - usb->data, batch_len); - if (ret < 0) - break; - - i += batch_len; - } - mutex_unlock(&usb->usb_ctrl_mtx); -} - -int mt7921u_mcu_power_on(struct mt792x_dev *dev) -{ - int ret; - - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); - if (ret) - return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, - MT_TOP_MISC2_FW_PWR_ON, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - ret = -EIO; - } - - return ret; -} - static int mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) @@ -155,20 +78,69 @@ static int mt7921u_mcu_init(struct mt792x_dev *dev) return 0; } -static void mt7921u_stop(struct ieee80211_hw *hw) +static int mt7921u_mac_reset(struct mt792x_dev *dev) { - struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err; + + mt76_txq_schedule_all(&dev->mphy); + mt76_worker_disable(&dev->mt76.tx_worker); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); mt76u_stop_tx(&dev->mt76); - mt7921_stop(hw); + + mt792xu_wfsys_reset(dev); + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + err = mt76u_resume_rx(&dev->mt76); + if (err) + goto out; + + err = mt792xu_mcu_power_on(dev); + if (err) + goto out; + + err = mt792xu_dma_init(dev, false); + if (err) + goto out; + + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_run_firmware(dev); + if (err) + goto out; + + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7921_mac_init(dev); + if (err) + goto out; + + err = __mt7921_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; } -static void mt7921u_cleanup(struct mt792x_dev *dev) +static void mt7921u_stop(struct ieee80211_hw *hw) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - mt7921u_wfsys_reset(dev); - skb_queue_purge(&dev->mt76.mcu.res_q); - mt76u_queues_deinit(&dev->mt76); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt76u_stop_tx(&dev->mt76); + mt7921_stop(hw); } static int mt7921u_probe(struct usb_interface *usb_intf, @@ -193,15 +165,15 @@ static int mt7921u_probe(struct usb_interface *usb_intf, }; static const struct mt792x_hif_ops hif_ops = { .mcu_init = mt7921u_mcu_init, - .init_reset = mt7921u_init_reset, + .init_reset = mt792xu_init_reset, .reset = mt7921u_mac_reset, }; static struct mt76_bus_ops bus_ops = { - .rr = mt7921u_rr, - .wr = mt7921u_wr, - .rmw = mt7921u_rmw, + .rr = mt792xu_rr, + .wr = mt792xu_wr, + .rmw = mt792xu_rmw, .read_copy = mt76u_read_copy, - .write_copy = mt7921u_copy, + .write_copy = mt792xu_copy, .type = MT76_BUS_USB, }; struct usb_device *udev = interface_to_usbdev(usb_intf); @@ -240,12 +212,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf, dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) { - ret = mt7921u_wfsys_reset(dev); + ret = mt792xu_wfsys_reset(dev); if (ret) goto error; } - ret = mt7921u_mcu_power_on(dev); + ret = mt792xu_mcu_power_on(dev); if (ret) goto error; @@ -257,7 +229,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (ret) goto error; - ret = mt7921u_dma_init(dev, false); + ret = mt792xu_dma_init(dev, false); if (ret) goto error; @@ -291,7 +263,7 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf) return; mt76_unregister_device(&dev->mt76); - mt7921u_cleanup(dev); + mt792xu_cleanup(dev); usb_set_intfdata(usb_intf, NULL); usb_put_dev(interface_to_usbdev(usb_intf)); @@ -350,7 +322,7 @@ static int mt7921u_resume(struct usb_interface *intf) } if (reinit || mt792x_dma_need_reinit(dev)) { - err = mt7921u_dma_init(dev, true); + err = mt792xu_dma_init(dev, true); if (err) goto failed; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c deleted file mode 100644 index f7cb6c542af5..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: ISC -/* Copyright (C) 2022 MediaTek Inc. - * - * Author: Lorenzo Bianconi - */ - -#include -#include -#include - -#include "mt7921.h" -#include "mcu.h" -#include "../mt76_connac2_mac.h" - -static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, - USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE, - USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - -static void mt7921u_dma_prefetch(struct mt792x_dev *dev) -{ - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_BASE_PTR_MASK, 0x80); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_BASE_PTR_MASK, 0xc0); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_BASE_PTR_MASK, 0x100); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_BASE_PTR_MASK, 0x140); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_BASE_PTR_MASK, 0x180); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_BASE_PTR_MASK, 0x280); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_BASE_PTR_MASK, 0x2c0); -} - -static void mt7921u_wfdma_init(struct mt792x_dev *dev) -{ - mt7921u_dma_prefetch(dev); - - mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); - mt76_set(dev, MT_UWFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | - MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - /* disable dmashdl */ - mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - - mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); -} - -static int mt7921u_dma_rx_evt_ep4(struct mt792x_dev *dev) -{ - if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) - return -ETIMEDOUT; - - mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, MT_WFDMA_HOST_CONFIG, - MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); - mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - return 0; -} - -static void mt7921u_epctl_rst_opt(struct mt792x_dev *dev, bool reset) -{ - u32 val; - - /* usb endpoint reset opt - * bits[4,9]: out blk ep 4-9 - * bits[20,21]: in blk ep 4-5 - * bits[22]: in int ep 6 - */ - val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); - if (reset) - val |= GENMASK(9, 4) | GENMASK(22, 20); - else - val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); - mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); -} - -int mt7921u_dma_init(struct mt792x_dev *dev, bool resume) -{ - int err; - - mt7921u_wfdma_init(dev); - - mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); - - mt76_set(dev, MT_UDMA_WLCFG_0, - MT_WL_RX_EN | MT_WL_TX_EN | - MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); - mt76_clear(dev, MT_UDMA_WLCFG_0, - MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); - mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); - - if (resume) - return 0; - - err = mt7921u_dma_rx_evt_ep4(dev); - if (err) - return err; - - mt7921u_epctl_rst_opt(dev, false); - - return 0; -} - -int mt7921u_wfsys_reset(struct mt792x_dev *dev) -{ - u32 val; - int i; - - mt7921u_epctl_rst_opt(dev, false); - - val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); - val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; - mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); - - usleep_range(10, 20); - - val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); - val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; - mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); - - mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); - for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) { - val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); - if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) - break; - - msleep(100); - } - - if (i == MT792x_WFSYS_INIT_RETRY_COUNT) - return -ETIMEDOUT; - - return 0; -} - -int mt7921u_init_reset(struct mt792x_dev *dev) -{ - set_bit(MT76_RESET, &dev->mphy.state); - - wake_up(&dev->mt76.mcu.wait); - skb_queue_purge(&dev->mt76.mcu.res_q); - - mt76u_stop_rx(&dev->mt76); - mt76u_stop_tx(&dev->mt76); - - mt7921u_wfsys_reset(dev); - - clear_bit(MT76_RESET, &dev->mphy.state); - - return mt76u_resume_rx(&dev->mt76); -} - -int mt7921u_mac_reset(struct mt792x_dev *dev) -{ - int err; - - mt76_txq_schedule_all(&dev->mphy); - mt76_worker_disable(&dev->mt76.tx_worker); - - set_bit(MT76_RESET, &dev->mphy.state); - set_bit(MT76_MCU_RESET, &dev->mphy.state); - - wake_up(&dev->mt76.mcu.wait); - skb_queue_purge(&dev->mt76.mcu.res_q); - - mt76u_stop_rx(&dev->mt76); - mt76u_stop_tx(&dev->mt76); - - mt7921u_wfsys_reset(dev); - - clear_bit(MT76_MCU_RESET, &dev->mphy.state); - err = mt76u_resume_rx(&dev->mt76); - if (err) - goto out; - - err = mt7921u_mcu_power_on(dev); - if (err) - goto out; - - err = mt7921u_dma_init(dev, false); - if (err) - goto out; - - mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); - - err = mt7921_run_firmware(dev); - if (err) - goto out; - - mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); - - err = mt7921_mcu_set_eeprom(dev); - if (err) - goto out; - - err = mt7921_mac_init(dev); - if (err) - goto out; - - err = __mt7921_start(&dev->phy); -out: - clear_bit(MT76_RESET, &dev->mphy.state); - - mt76_worker_enable(&dev->mt76.tx_worker); - - return err; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 1ed688186fe7..b226a863e5de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -294,6 +294,19 @@ int mt792x_init_wcid(struct mt792x_dev *dev); int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); +/* usb */ +#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) +#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) +int mt792xu_dma_init(struct mt792x_dev *dev, bool resume); +int mt792xu_mcu_power_on(struct mt792x_dev *dev); +int mt792xu_wfsys_reset(struct mt792x_dev *dev); +int mt792xu_init_reset(struct mt792x_dev *dev); +u32 mt792xu_rr(struct mt76_dev *dev, u32 addr); +void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val); +u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val); +void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len); +void mt792xu_cleanup(struct mt792x_dev *dev); + int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c new file mode 100644 index 000000000000..97480c9c9974 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. + * + * Author: Lorenzo Bianconi + */ + +#include +#include +#include + +#include "mt792x.h" +#include "mt76_connac2_mac.h" + +u32 mt792xu_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} +EXPORT_SYMBOL_GPL(mt792xu_rr); + +void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} +EXPORT_SYMBOL_GPL(mt792xu_wr); + +u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} +EXPORT_SYMBOL_GPL(mt792xu_rmw); + +void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} +EXPORT_SYMBOL_GPL(mt792xu_copy); + +int mt792xu_mcu_power_on(struct mt792x_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, + MT_TOP_MISC2_FW_PWR_ON, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return ret; +} +EXPORT_SYMBOL_GPL(mt792xu_mcu_power_on); + +void mt792xu_cleanup(struct mt792x_dev *dev) +{ + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + mt792xu_wfsys_reset(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); + mt76u_queues_deinit(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792xu_cleanup); + +static u32 mt792xu_uhw_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, + USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt792xu_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE, + USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static void mt792xu_dma_prefetch(struct mt792x_dev *dev) +{ + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_BASE_PTR_MASK, 0x80); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_BASE_PTR_MASK, 0xc0); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_BASE_PTR_MASK, 0x100); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_BASE_PTR_MASK, 0x140); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_BASE_PTR_MASK, 0x180); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_BASE_PTR_MASK, 0x280); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_BASE_PTR_MASK, 0x2c0); +} + +static void mt792xu_wfdma_init(struct mt792x_dev *dev) +{ + mt792xu_dma_prefetch(dev); + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | + MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + /* disable dmashdl */ + mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + +static int mt792xu_dma_rx_evt_ep4(struct mt792x_dev *dev) +{ + if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) + return -ETIMEDOUT; + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + return 0; +} + +static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset) +{ + u32 val; + + /* usb endpoint reset opt + * bits[4,9]: out blk ep 4-9 + * bits[20,21]: in blk ep 4-5 + * bits[22]: in int ep 6 + */ + val = mt792xu_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); + if (reset) + val |= GENMASK(9, 4) | GENMASK(22, 20); + else + val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); + mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); +} + +int mt792xu_dma_init(struct mt792x_dev *dev, bool resume) +{ + int err; + + mt792xu_wfdma_init(dev); + + mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); + + mt76_set(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_EN | MT_WL_TX_EN | + MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); + mt76_clear(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); + mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); + + if (resume) + return 0; + + err = mt792xu_dma_rx_evt_ep4(dev); + if (err) + return err; + + mt792xu_epctl_rst_opt(dev, false); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xu_dma_init); + +int mt792xu_wfsys_reset(struct mt792x_dev *dev) +{ + u32 val; + int i; + + mt792xu_epctl_rst_opt(dev, false); + + val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + usleep_range(10, 20); + + val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); + for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) { + val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); + if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) + break; + + msleep(100); + } + + if (i == MT792x_WFSYS_INIT_RETRY_COUNT) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset); + +int mt792xu_init_reset(struct mt792x_dev *dev) +{ + set_bit(MT76_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt792xu_wfsys_reset(dev); + + clear_bit(MT76_RESET, &dev->mphy.state); + + return mt76u_resume_rx(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792xu_init_reset); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Lorenzo Bianconi "); -- cgit From 583204ae70f9f4d1cf8f2874a6c0706e5528eab1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:20 +0800 Subject: wifi: mt76: mt792x: move mt7921_load_firmware in mt792x-lib module mt7921_load_firmware routine is shared between mt7921 and mt7925 chipset so move it in mt792x-lib module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 63 +--------------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 6 --- drivers/net/wireless/mediatek/mt76/mt792x.h | 28 ++++++++++ drivers/net/wireless/mediatek/mt76/mt792x_core.c | 36 +++++++++++++ 4 files changed, 66 insertions(+), 67 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index e9caf750bca5..4b77d95af958 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -364,30 +364,6 @@ int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, enable, false); } -static char *mt7921_patch_name(struct mt792x_dev *dev) -{ - char *ret; - - if (is_mt7922(&dev->mt76)) - ret = MT7922_ROM_PATCH; - else - ret = MT7921_ROM_PATCH; - - return ret; -} - -static char *mt7921_ram_name(struct mt792x_dev *dev) -{ - char *ret; - - if (is_mt7922(&dev->mt76)) - ret = MT7922_FIRMWARE_WM; - else - ret = MT7921_FIRMWARE_WM; - - return ret; -} - static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name) { const struct mt76_connac2_fw_trailer *hdr; @@ -472,41 +448,6 @@ out: return ret; } -static int mt7921_load_firmware(struct mt792x_dev *dev) -{ - int ret; - - ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev)); - if (ret) - return ret; - - if (mt76_is_sdio(&dev->mt76)) { - /* activate again */ - ret = __mt792x_mcu_fw_pmctrl(dev); - if (!ret) - ret = __mt792x_mcu_drv_pmctrl(dev); - } - - ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL); - if (ret) - return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, - MT_TOP_MISC2_FW_N9_RDY, 1500)) { - dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); - - return -EIO; - } - -#ifdef CONFIG_PM - dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; -#endif /* CONFIG_PM */ - - dev_dbg(dev->mt76.dev, "Firmware init done\n"); - - return 0; -} - int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) { struct { @@ -524,7 +465,7 @@ int mt7921_run_firmware(struct mt792x_dev *dev) { int err; - err = mt7921_load_firmware(dev); + err = mt792x_load_firmware(dev); if (err) return err; @@ -533,7 +474,7 @@ int mt7921_run_firmware(struct mt792x_dev *dev) return err; set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); - err = mt7921_load_clc(dev, mt7921_ram_name(dev)); + err = mt7921_load_clc(dev, mt792x_ram_name(dev)); if (err) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index cb22be083242..e458ddb7d99a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -17,12 +17,6 @@ #define MT7921_RX_RING_SIZE 1536 #define MT7921_RX_MCU_RING_SIZE 512 -#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" -#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" - -#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin" -#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin" - #define MT7921_EEPROM_SIZE 3584 #define MT7921_TOKEN_SIZE 8192 diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index b226a863e5de..700cd0ccc5d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -31,6 +31,12 @@ #define MT792x_MCU_INIT_RETRY_COUNT 10 #define MT792x_WFSYS_INIT_RETRY_COUNT 2 +#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" +#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin" + +#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" +#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin" + struct mt792x_vif; struct mt792x_sta; @@ -294,6 +300,28 @@ int mt792x_init_wcid(struct mt792x_dev *dev); int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); +static inline char *mt792x_ram_name(struct mt792x_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7922: + return MT7922_FIRMWARE_WM; + default: + return MT7921_FIRMWARE_WM; + } +} + +static inline char *mt792x_patch_name(struct mt792x_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7922: + return MT7922_ROM_PATCH; + default: + return MT7921_ROM_PATCH; + } +} + +int mt792x_load_firmware(struct mt792x_dev *dev); + /* usb */ #define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) #define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index f7dfc2189cc8..46be7f996c7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -804,5 +804,41 @@ int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792xe_mcu_fw_pmctrl); +int mt792x_load_firmware(struct mt792x_dev *dev) +{ + int ret; + + ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev)); + if (ret) + return ret; + + if (mt76_is_sdio(&dev->mt76)) { + /* activate again */ + ret = __mt792x_mcu_fw_pmctrl(dev); + if (!ret) + ret = __mt792x_mcu_drv_pmctrl(dev); + } + + ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, + MT_TOP_MISC2_FW_N9_RDY, 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + + return -EIO; + } + +#ifdef CONFIG_PM + dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; +#endif /* CONFIG_PM */ + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_load_firmware); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); -- cgit From 81d4c943a168fc32eeb77e9b97ffd650db932ded Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:21 +0800 Subject: wifi: mt76: mt76_connac3: move lmac queue enumeration in mt76_connac3_mac.h This is a preliminary patch to introduce mt7925 chip support Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h | 14 ++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h index 6663a0b46541..68ca0844cbbf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h @@ -4,6 +4,20 @@ #ifndef __MT76_CONNAC3_MAC_H #define __MT76_CONNAC3_MAC_H +enum { + MT_CTX0, + MT_HIF0 = 0x0, + + MT_LMAC_AC00 = 0x0, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0, + MT_LMAC_BCN0, + MT_LMAC_PSMP0, +}; + #define MT_CT_PARSE_LEN 72 #define MT_CT_DMA_BUF_NUM 2 diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 726c222e8e1e..7354e5cf8e67 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -254,20 +254,6 @@ enum { __MT_WFDMA_MAX, }; -enum { - MT_CTX0, - MT_HIF0 = 0x0, - - MT_LMAC_AC00 = 0x0, - MT_LMAC_AC01, - MT_LMAC_AC02, - MT_LMAC_AC03, - MT_LMAC_ALTX0 = 0x10, - MT_LMAC_BMC0, - MT_LMAC_BCN0, - MT_LMAC_PSMP0, -}; - enum { MT_RX_SEL0, MT_RX_SEL1, -- cgit From 7d403f3a19c6687f51c5e7423e28ddfd00983477 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:22 +0800 Subject: wifi: mt76: mt792x: move MT7921_PM_TIMEOUT and MT7921_HW_SCAN_TIMEOUT in common code MT7921_PM_TIMEOUT is shared between mt7925 and mt7921 so move it in mt792x module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 --- drivers/net/wireless/mediatek/mt76/mt792x.h | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 7b8876bf8fc8..ff63f37f67d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -217,7 +217,7 @@ int mt7921_register_device(struct mt792x_dev *dev) timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0); init_waitqueue_head(&dev->phy.roc_wait); - dev->pm.idle_timeout = MT7921_PM_TIMEOUT; + dev->pm.idle_timeout = MT792x_PM_TIMEOUT; dev->pm.stats.last_wake_event = jiffies; dev->pm.stats.last_doze_event = jiffies; if (!mt76_is_usb(&dev->mt76)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 4b77d95af958..90c93970acab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -167,7 +167,7 @@ mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->mt76.lock); ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work, - MT7921_HW_SCAN_TIMEOUT); + MT792x_HW_SCAN_TIMEOUT); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index e458ddb7d99a..0f8b93a2be3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -7,9 +7,6 @@ #include "../mt792x.h" #include "regs.h" -#define MT7921_PM_TIMEOUT (HZ / 12) -#define MT7921_HW_SCAN_TIMEOUT (HZ / 10) - #define MT7921_TX_RING_SIZE 2048 #define MT7921_TX_MCU_RING_SIZE 256 #define MT7921_TX_FWDL_RING_SIZE 128 diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 700cd0ccc5d3..d80f80bc7656 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -11,6 +11,9 @@ #include "mt792x_regs.h" #include "mt792x_acpi_sar.h" +#define MT792x_PM_TIMEOUT (HZ / 12) +#define MT792x_HW_SCAN_TIMEOUT (HZ / 10) + #define MT792x_MAX_INTERFACES 4 #define MT792x_WTBL_SIZE 20 #define MT792x_WTBL_RESERVED (MT792x_WTBL_SIZE - 1) -- cgit From 2e7f7a2c871cd3b4a01c0a325f86f5b112f3b50f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:23 +0800 Subject: wifi: mt76: mt7921: move mt7921_dma_init in pci.c Move mt7921_dma_init routine in pci.c and make it static since it is run just in mt7921_pci_probe(). Get rid of dma.c. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 71 ---------------------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 66 ++++++++++++++++++++ 4 files changed, 67 insertions(+), 73 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/dma.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index 964eb55824cd..849be9e848e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -7,6 +7,6 @@ obj-$(CONFIG_MT7921U) += mt7921u.o mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o -mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o +mt7921e-y := pci.o pci_mac.o pci_mcu.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o mt7921u-y := usb.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c deleted file mode 100644 index fdc598e099f6..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: ISC -/* Copyright (C) 2020 MediaTek Inc. */ - -#include "mt7921.h" -#include "../dma.h" -#include "../mt76_connac2_mac.h" - -int mt7921_dma_init(struct mt792x_dev *dev) -{ - int ret; - - mt76_dma_attach(&dev->mt76); - - ret = mt792x_dma_disable(dev, true); - if (ret) - return ret; - - /* init tx queue */ - ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, - MT7921_TX_RING_SIZE, - MT_TX_RING_BASE, 0); - if (ret) - return ret; - - mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4); - - /* command to WM */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM, - MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE); - if (ret) - return ret; - - /* firmware download */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL, - MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); - if (ret) - return ret; - - /* event from WM before firmware download */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], - MT7921_RXQ_MCU_WM, - MT7921_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); - if (ret) - return ret; - - /* Change mcu queue after firmware download */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], - MT7921_RXQ_MCU_WM, - MT7921_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_WFDMA0(0x540)); - if (ret) - return ret; - - /* rx data */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], - MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); - if (ret) - return ret; - - ret = mt76_init_queues(dev, mt792x_poll_rx); - if (ret < 0) - return ret; - - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt792x_poll_tx); - napi_enable(&dev->mt76.tx_napi); - - return mt792x_dma_enable(dev); -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 0f8b93a2be3a..87dd06855f68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -182,7 +182,6 @@ u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); int __mt7921_start(struct mt792x_phy *phy); int mt7921_register_device(struct mt792x_dev *dev); void mt7921_unregister_device(struct mt792x_dev *dev); -int mt7921_dma_init(struct mt792x_dev *dev); int mt7921_run_firmware(struct mt792x_dev *dev); int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index c3f22ce9f5c4..3dda84a93717 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -9,6 +9,7 @@ #include "mt7921.h" #include "../mt76_connac2_mac.h" +#include "../dma.h" #include "mcu.h" static const struct pci_device_id mt7921_pci_device_table[] = { @@ -155,6 +156,71 @@ static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) return dev->bus_ops->rmw(mdev, addr, mask, val); } +static int mt7921_dma_init(struct mt792x_dev *dev) +{ + int ret; + + mt76_dma_attach(&dev->mt76); + + ret = mt792x_dma_disable(dev, true); + if (ret) + return ret; + + /* init tx queue */ + ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, + MT7921_TX_RING_SIZE, + MT_TX_RING_BASE, 0); + if (ret) + return ret; + + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4); + + /* command to WM */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM, + MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* firmware download */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL, + MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* event from WM before firmware download */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], + MT7921_RXQ_MCU_WM, + MT7921_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + if (ret) + return ret; + + /* Change mcu queue after firmware download */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], + MT7921_RXQ_MCU_WM, + MT7921_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_WFDMA0(0x540)); + if (ret) + return ret; + + /* rx data */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], + MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); + if (ret) + return ret; + + ret = mt76_init_queues(dev, mt792x_poll_rx); + if (ret < 0) + return ret; + + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt792x_poll_tx); + napi_enable(&dev->mt76.tx_napi); + + return mt792x_dma_enable(dev); +} + static int mt7921_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { -- cgit From fc80731ba06316da80be2993c91c315c9923dac0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 28 Jun 2023 15:07:24 +0800 Subject: wifi: mt76: mt7921: move mt7921u_disconnect mt792x-lib mt7921u_disconnect routine is shared between mt7921 and mt7925 so move it in mt792x-usb module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 19 +------------------ drivers/net/wireless/mediatek/mt76/mt792x.h | 2 +- drivers/net/wireless/mediatek/mt76/mt792x_usb.c | 21 +++++++++++++++++++-- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index c3981bc893ac..59cd3d98bf90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -254,23 +254,6 @@ error: return ret; } -static void mt7921u_disconnect(struct usb_interface *usb_intf) -{ - struct mt792x_dev *dev = usb_get_intfdata(usb_intf); - - cancel_work_sync(&dev->init_work); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return; - - mt76_unregister_device(&dev->mt76); - mt792xu_cleanup(dev); - - usb_set_intfdata(usb_intf, NULL); - usb_put_dev(interface_to_usbdev(usb_intf)); - - mt76_free_device(&dev->mt76); -} - #ifdef CONFIG_PM static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) { @@ -350,7 +333,7 @@ static struct usb_driver mt7921u_driver = { .name = KBUILD_MODNAME, .id_table = mt7921u_device_table, .probe = mt7921u_probe, - .disconnect = mt7921u_disconnect, + .disconnect = mt792xu_disconnect, #ifdef CONFIG_PM .suspend = mt7921u_suspend, .resume = mt7921u_resume, diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index d80f80bc7656..5d5ab8630041 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -336,7 +336,7 @@ u32 mt792xu_rr(struct mt76_dev *dev, u32 addr); void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val); u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val); void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len); -void mt792xu_cleanup(struct mt792x_dev *dev); +void mt792xu_disconnect(struct usb_interface *usb_intf); int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c index 97480c9c9974..20e7f9c7c88c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c @@ -91,14 +91,13 @@ int mt792xu_mcu_power_on(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792xu_mcu_power_on); -void mt792xu_cleanup(struct mt792x_dev *dev) +static void mt792xu_cleanup(struct mt792x_dev *dev) { clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt792xu_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); mt76u_queues_deinit(&dev->mt76); } -EXPORT_SYMBOL_GPL(mt792xu_cleanup); static u32 mt792xu_uhw_rr(struct mt76_dev *dev, u32 addr) { @@ -288,5 +287,23 @@ int mt792xu_init_reset(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792xu_init_reset); +void mt792xu_disconnect(struct usb_interface *usb_intf) +{ + struct mt792x_dev *dev = usb_get_intfdata(usb_intf); + + cancel_work_sync(&dev->init_work); + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return; + + mt76_unregister_device(&dev->mt76); + mt792xu_cleanup(dev); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792xu_disconnect); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi "); -- cgit From 74f12d511625e603fac8c0c2b6872e687e56dd61 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Sun, 23 Jul 2023 16:03:50 +0800 Subject: wifi: mt76: testmode: add nla_policy for MT76_TM_ATTR_TX_LENGTH It seems that the nla_policy in mt76_tm_policy is missed for attribute MT76_TM_ATTR_TX_LENGTH. This patch adds the correct description to make sure the u32 val = nla_get_u32(tb[MT76_TM_ATTR_TX_LENGTH]); in function mt76_testmode_cmd() is safe and will not result in out-of-attribute read. Fixes: f0efa8621550 ("mt76: add API for testmode support") Signed-off-by: Lin Ma Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/testmode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 0accc71a91c9..4644dace9bb3 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { [MT76_TM_ATTR_RESET] = { .type = NLA_FLAG }, [MT76_TM_ATTR_STATE] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 }, + [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 }, [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 }, -- cgit From 8b305ee2a91c3c4c89cb82ea940265b247eb0a13 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Tue, 25 Jul 2023 16:54:30 -0700 Subject: net: phy: smsc: add WoL support to LAN8740/LAN8742 PHYs Microchip LAN8740/LAN8742 PHYs support basic unicast, broadcast, and Magic Packet WoL. They have one pattern filter matching up to 128 bytes of frame data, which can be used to implement ARP or multicast WoL. ARP WoL matches any ARP frame with broadcast address. Multicast WoL matches any multicast frame. Signed-off-by: Tristram Ha Reviewed-by: Florian Fainelli Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/1690329270-2873-1-git-send-email-Tristram.Ha@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/Kconfig | 1 + drivers/net/phy/smsc.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 251 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 87b823858717..67aaeb75301f 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -350,6 +350,7 @@ config ROCKCHIP_PHY config SMSC_PHY tristate "SMSC PHYs" + select CRC16 help Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 692930750215..c88edb19d2e7 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include /* Vendor-specific PHY Definitions */ @@ -51,6 +53,7 @@ struct smsc_phy_priv { unsigned int edpd_enable:1; unsigned int edpd_mode_set_by_user:1; unsigned int edpd_max_wait_ms; + bool wol_arp; }; static int smsc_phy_ack_interrupt(struct phy_device *phydev) @@ -258,6 +261,243 @@ int lan87xx_read_status(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(lan87xx_read_status); +static int lan874x_phy_config_init(struct phy_device *phydev) +{ + u16 val; + int rc; + + /* Setup LED2/nINT/nPME pin to function as nPME. May need user option + * to use LED1/nINT/nPME. + */ + val = MII_LAN874X_PHY_PME2_SET; + + /* The bits MII_LAN874X_PHY_WOL_PFDA_FR, MII_LAN874X_PHY_WOL_WUFR, + * MII_LAN874X_PHY_WOL_MPR, and MII_LAN874X_PHY_WOL_BCAST_FR need to + * be cleared to de-assert PME signal after a WoL event happens, but + * using PME auto clear gets around that. + */ + val |= MII_LAN874X_PHY_PME_SELF_CLEAR; + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR, + val); + if (rc < 0) + return rc; + + /* set nPME self clear delay time */ + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_MCFGR, + MII_LAN874X_PHY_PME_SELF_CLEAR_DELAY); + if (rc < 0) + return rc; + + return smsc_phy_config_init(phydev); +} + +static void lan874x_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct smsc_phy_priv *priv = phydev->priv; + int rc; + + wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC | + WAKE_ARP | WAKE_MCAST); + wol->wolopts = 0; + + rc = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR); + if (rc < 0) + return; + + if (rc & MII_LAN874X_PHY_WOL_PFDAEN) + wol->wolopts |= WAKE_UCAST; + + if (rc & MII_LAN874X_PHY_WOL_BCSTEN) + wol->wolopts |= WAKE_BCAST; + + if (rc & MII_LAN874X_PHY_WOL_MPEN) + wol->wolopts |= WAKE_MAGIC; + + if (rc & MII_LAN874X_PHY_WOL_WUEN) { + if (priv->wol_arp) + wol->wolopts |= WAKE_ARP; + else + wol->wolopts |= WAKE_MCAST; + } +} + +static u16 smsc_crc16(const u8 *buffer, size_t len) +{ + return bitrev16(crc16(0xFFFF, buffer, len)); +} + +static int lan874x_chk_wol_pattern(const u8 pattern[], const u16 *mask, + u8 len, u8 *data, u8 *datalen) +{ + size_t i, j, k; + int ret = 0; + u16 bits; + + /* Pattern filtering can match up to 128 bytes of frame data. There + * are 8 registers to program the 16-bit masks, where each bit means + * the byte will be compared. The frame data will then go through a + * CRC16 calculation for hardware comparison. This helper function + * makes sure only relevant frame data are included in this + * calculation. It provides a warning when the masks and expected + * data size do not match. + */ + i = 0; + k = 0; + while (len > 0) { + bits = *mask; + for (j = 0; j < 16; j++, i++, len--) { + /* No more pattern. */ + if (!len) { + /* The rest of bitmap is not empty. */ + if (bits) + ret = i + 1; + break; + } + if (bits & 1) + data[k++] = pattern[i]; + bits >>= 1; + } + mask++; + } + *datalen = k; + return ret; +} + +static int lan874x_set_wol_pattern(struct phy_device *phydev, u16 val, + const u8 data[], u8 datalen, + const u16 *mask, u8 masklen) +{ + u16 crc, reg; + int rc; + + /* Starting pattern offset is set before calling this function. */ + val |= MII_LAN874X_PHY_WOL_FILTER_EN; + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, + MII_LAN874X_PHY_MMD_WOL_WUF_CFGA, val); + if (rc < 0) + return rc; + + crc = smsc_crc16(data, datalen); + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, + MII_LAN874X_PHY_MMD_WOL_WUF_CFGB, crc); + if (rc < 0) + return rc; + + masklen = (masklen + 15) & ~0xf; + reg = MII_LAN874X_PHY_MMD_WOL_WUF_MASK7; + while (masklen >= 16) { + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, reg, *mask); + if (rc < 0) + return rc; + reg--; + mask++; + masklen -= 16; + } + + /* Clear out the rest of mask registers. */ + while (reg != MII_LAN874X_PHY_MMD_WOL_WUF_MASK0) { + phy_write_mmd(phydev, MDIO_MMD_PCS, reg, 0); + reg--; + } + return rc; +} + +static int lan874x_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct net_device *ndev = phydev->attached_dev; + struct smsc_phy_priv *priv = phydev->priv; + u16 val, val_wucsr; + u8 data[128]; + u8 datalen; + int rc; + + /* lan874x has only one WoL filter pattern */ + if ((wol->wolopts & (WAKE_ARP | WAKE_MCAST)) == + (WAKE_ARP | WAKE_MCAST)) { + phydev_info(phydev, + "lan874x WoL supports one of ARP|MCAST at a time\n"); + return -EOPNOTSUPP; + } + + rc = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR); + if (rc < 0) + return rc; + + val_wucsr = rc; + + if (wol->wolopts & WAKE_UCAST) + val_wucsr |= MII_LAN874X_PHY_WOL_PFDAEN; + else + val_wucsr &= ~MII_LAN874X_PHY_WOL_PFDAEN; + + if (wol->wolopts & WAKE_BCAST) + val_wucsr |= MII_LAN874X_PHY_WOL_BCSTEN; + else + val_wucsr &= ~MII_LAN874X_PHY_WOL_BCSTEN; + + if (wol->wolopts & WAKE_MAGIC) + val_wucsr |= MII_LAN874X_PHY_WOL_MPEN; + else + val_wucsr &= ~MII_LAN874X_PHY_WOL_MPEN; + + /* Need to use pattern matching */ + if (wol->wolopts & (WAKE_ARP | WAKE_MCAST)) + val_wucsr |= MII_LAN874X_PHY_WOL_WUEN; + else + val_wucsr &= ~MII_LAN874X_PHY_WOL_WUEN; + + if (wol->wolopts & WAKE_ARP) { + const u8 pattern[2] = { 0x08, 0x06 }; + const u16 mask[1] = { 0x0003 }; + + rc = lan874x_chk_wol_pattern(pattern, mask, 2, data, + &datalen); + if (rc) + phydev_dbg(phydev, "pattern not valid at %d\n", rc); + + /* Need to match broadcast destination address and provided + * data pattern at offset 12. + */ + val = 12 | MII_LAN874X_PHY_WOL_FILTER_BCSTEN; + rc = lan874x_set_wol_pattern(phydev, val, data, datalen, mask, + 2); + if (rc < 0) + return rc; + priv->wol_arp = true; + } + + if (wol->wolopts & WAKE_MCAST) { + /* Need to match multicast destination address. */ + val = MII_LAN874X_PHY_WOL_FILTER_MCASTTEN; + rc = lan874x_set_wol_pattern(phydev, val, data, 0, NULL, 0); + if (rc < 0) + return rc; + priv->wol_arp = false; + } + + if (wol->wolopts & (WAKE_MAGIC | WAKE_UCAST)) { + const u8 *mac = (const u8 *)ndev->dev_addr; + int i, reg; + + reg = MII_LAN874X_PHY_MMD_WOL_RX_ADDRC; + for (i = 0; i < 6; i += 2, reg--) { + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, reg, + ((mac[i + 1] << 8) | mac[i])); + if (rc < 0) + return rc; + } + } + + rc = phy_write_mmd(phydev, MDIO_MMD_PCS, MII_LAN874X_PHY_MMD_WOL_WUCSR, + val_wucsr); + if (rc < 0) + return rc; + + return 0; +} + static int smsc_get_sset_count(struct phy_device *phydev) { return ARRAY_SIZE(smsc_hw_stats); @@ -533,7 +773,7 @@ static struct phy_driver smsc_phy_driver[] = { /* basic functions */ .read_status = lan87xx_read_status, - .config_init = smsc_phy_config_init, + .config_init = lan874x_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ @@ -548,6 +788,10 @@ static struct phy_driver smsc_phy_driver[] = { .get_tunable = smsc_phy_get_tunable, .set_tunable = smsc_phy_set_tunable, + /* WoL */ + .set_wol = lan874x_set_wol, + .get_wol = lan874x_get_wol, + .suspend = genphy_suspend, .resume = genphy_resume, }, { @@ -566,7 +810,7 @@ static struct phy_driver smsc_phy_driver[] = { /* basic functions */ .read_status = lan87xx_read_status, - .config_init = smsc_phy_config_init, + .config_init = lan874x_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ @@ -581,6 +825,10 @@ static struct phy_driver smsc_phy_driver[] = { .get_tunable = smsc_phy_get_tunable, .set_tunable = smsc_phy_set_tunable, + /* WoL */ + .set_wol = lan874x_set_wol, + .get_wol = lan874x_get_wol, + .suspend = genphy_suspend, .resume = genphy_resume, } }; -- cgit From 73365fe44aa52fcd3e634e502937eb029abd0ee0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 25 Jul 2023 17:46:37 +0200 Subject: bcmasp: BCMASP should depend on ARCH_BRCMSTB The Broadcom ASP 2.0 Ethernet controller is only present on Broadcom STB SoCs. Hence add a dependency on ARCH_BRCMSTB, to prevent asking the user about this driver when configuring a kernel without Broadcom ARM-based set-top box chipset support. Fixes: 490cb412007de593 ("net: bcmasp: Add support for ASP2.0 Ethernet controller") Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Acked-by: Florian Fainelli Acked-by: Justin Chen Link: https://lore.kernel.org/r/1e8b998aa8dcc6e38323e295ee2430b48245cc79.1690299794.git.geert+renesas@glider.be Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index d4166141145d..75ca3ddda1f5 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -257,6 +257,7 @@ config BNXT_HWMON config BCMASP tristate "Broadcom ASP 2.0 Ethernet support" + depends on ARCH_BRCMSTB || COMPILE_TEST default ARCH_BRCMSTB depends on OF select MII -- cgit From 68bf5100fadffbba297f9142bf005767e571d726 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Tue, 25 Jul 2023 14:04:01 +0200 Subject: mlxsw: reg: Move 'mpsc' definition in 'mlxsw_reg_infos' The array 'mlxsw_reg_infos' is ordered by registers' IDs. The ID of MPSC register is 0x9080, so it should be after MCDA (register ID 0x9063) and not after MTUTC (register ID 0x9055). Note that the register's fields are defined in the correct place in the file, only the definition in 'mlxsw_reg_infos' is wrong. This issue was found while adding new register which supposed to be before mpsc. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/c5e270cd5769f301fe81235622215143506e1b48.1690281940.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index df63f3923372..a209f98dafa2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -12974,10 +12974,10 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mcion), MLXSW_REG(mtpps), MLXSW_REG(mtutc), - MLXSW_REG(mpsc), MLXSW_REG(mcqi), MLXSW_REG(mcc), MLXSW_REG(mcda), + MLXSW_REG(mpsc), MLXSW_REG(mgpc), MLXSW_REG(mprs), MLXSW_REG(mogcr), -- cgit From 7447eda4065e377e09d6ef9ecc8bf3219548d0ed Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Tue, 25 Jul 2023 14:04:02 +0200 Subject: mlxsw: reg: Add Management Capabilities Mask Register MCAM register reports the device supported management features. Querying this register exposes if features are supported with the current firmware version in the current ASIC. Then, the driver can separate between different implementations dynamically. MCAM register supports querying whether the MCIA register supports 128 bytes payloads or only 48 bytes. Add support for the register as preparation for allowing larger MCIA transactions. Note that the access to the bits in the field 'mng_feature_cap_mask' is not same to other mask fields in other registers. In most of the cases bit #0 is the first one in the last dword, in MCAM register, bits #0-#31 are in the first dword and so on. Declare the mask field using bits arrays per dword to simplify the access. Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/1427a3f57ba93db1c5dd4f982bfb31dd5c82356e.1690281940.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index a209f98dafa2..d2391707dc04 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -10581,6 +10581,79 @@ static inline void mlxsw_reg_mcda_pack(char *payload, u32 update_handle, mlxsw_reg_mcda_data_set(payload, i, *(u32 *) &data[i * 4]); } +/* MCAM - Management Capabilities Mask Register + * -------------------------------------------- + * Reports the device supported management features. + */ +#define MLXSW_REG_MCAM_ID 0x907F +#define MLXSW_REG_MCAM_LEN 0x48 + +MLXSW_REG_DEFINE(mcam, MLXSW_REG_MCAM_ID, MLXSW_REG_MCAM_LEN); + +enum mlxsw_reg_mcam_feature_group { + /* Enhanced features. */ + MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES, +}; + +/* reg_mcam_feature_group + * Feature list mask index. + * Access: Index + */ +MLXSW_ITEM32(reg, mcam, feature_group, 0x00, 16, 8); + +enum mlxsw_reg_mcam_mng_feature_cap_mask_bits { + /* If set, MCIA supports 128 bytes payloads. Otherwise, 48 bytes. */ + MLXSW_REG_MCAM_MCIA_128B = 34, +}; + +#define MLXSW_REG_BYTES_PER_DWORD 0x4 + +/* reg_mcam_mng_feature_cap_mask + * Supported port's enhanced features. + * Based on feature_group index. + * When bit is set, the feature is supported in the device. + * Access: RO + */ +#define MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(_dw_num, _offset) \ + MLXSW_ITEM_BIT_ARRAY(reg, mcam, mng_feature_cap_mask_dw##_dw_num, \ + _offset, MLXSW_REG_BYTES_PER_DWORD, 1) + +/* The access to the bits in the field 'mng_feature_cap_mask' is not same to + * other mask fields in other registers. In most of the cases bit #0 is the + * first one in the last dword. In MCAM register, the first dword contains bits + * #0-#31 and so on, so the access to the bits is simpler using bit array per + * dword. Declare each dword of 'mng_feature_cap_mask' field separately. + */ +MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(0, 0x28); +MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(1, 0x2C); +MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(2, 0x30); +MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(3, 0x34); + +static inline void +mlxsw_reg_mcam_pack(char *payload, enum mlxsw_reg_mcam_feature_group feat_group) +{ + MLXSW_REG_ZERO(mcam, payload); + mlxsw_reg_mcam_feature_group_set(payload, feat_group); +} + +static inline void +mlxsw_reg_mcam_unpack(char *payload, + enum mlxsw_reg_mcam_mng_feature_cap_mask_bits bit, + bool *p_mng_feature_cap_val) +{ + int offset = bit % (MLXSW_REG_BYTES_PER_DWORD * BITS_PER_BYTE); + int dword = bit / (MLXSW_REG_BYTES_PER_DWORD * BITS_PER_BYTE); + u8 (*getters[])(const char *, u16) = { + mlxsw_reg_mcam_mng_feature_cap_mask_dw0_get, + mlxsw_reg_mcam_mng_feature_cap_mask_dw1_get, + mlxsw_reg_mcam_mng_feature_cap_mask_dw2_get, + mlxsw_reg_mcam_mng_feature_cap_mask_dw3_get, + }; + + if (!WARN_ON_ONCE(dword >= ARRAY_SIZE(getters))) + *p_mng_feature_cap_val = getters[dword](payload, offset); +} + /* MPSC - Monitoring Packet Sampling Configuration Register * -------------------------------------------------------- * MPSC Register is used to configure the Packet Sampling mechanism. @@ -12977,6 +13050,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mcqi), MLXSW_REG(mcc), MLXSW_REG(mcda), + MLXSW_REG(mcam), MLXSW_REG(mpsc), MLXSW_REG(mgpc), MLXSW_REG(mprs), -- cgit From 3930dcc5e404079d8aabe577f61742b7e9590811 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 25 Jul 2023 14:04:03 +0200 Subject: mlxsw: reg: Remove unused function argument The 'lock' argument is always set to the default value of '0'. Remove it from the arguments list. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/fb5dd22830622ceeda1c2d6431c27fccd0687aca.1690281940.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 10 +++++----- drivers/net/ethernet/mellanox/mlxsw/reg.h | 12 +----------- 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 0107cbc32fc7..679f7488ba10 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -111,7 +111,7 @@ mlxsw_env_validate_cable_ident(struct mlxsw_core *core, u8 slot_index, int id, if (err) return err; - mlxsw_reg_mcia_pack(mcia_pl, slot_index, id, 0, + mlxsw_reg_mcia_pack(mcia_pl, slot_index, id, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1, MLXSW_REG_MCIA_I2C_ADDR_LOW); err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); @@ -188,7 +188,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index, } } - mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page, offset, size, + mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page, offset, size, i2c_addr); err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); @@ -266,12 +266,12 @@ mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, u8 slot_index, page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; else page = MLXSW_REG_MCIA_TH_PAGE_NUM; - mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page, + mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page, MLXSW_REG_MCIA_TH_PAGE_OFF + off, MLXSW_REG_MCIA_TH_ITEM_SIZE, MLXSW_REG_MCIA_I2C_ADDR_LOW); } else { - mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, + mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, MLXSW_REG_MCIA_PAGE0_LO, off, MLXSW_REG_MCIA_TH_ITEM_SIZE, MLXSW_REG_MCIA_I2C_ADDR_HIGH); @@ -491,7 +491,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, size = min_t(u8, page->length - bytes_read, MLXSW_REG_MCIA_EEPROM_SIZE); - mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page->page, + mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page->page, device_addr + bytes_read, size, page->i2c_address); mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index d2391707dc04..3b297797ced4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -9644,14 +9644,6 @@ static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind, MLXSW_REG_DEFINE(mcia, MLXSW_REG_MCIA_ID, MLXSW_REG_MCIA_LEN); -/* reg_mcia_l - * Lock bit. Setting this bit will lock the access to the specific - * cable. Used for updating a full page in a cable EPROM. Any access - * other then subsequence writes will fail while the port is locked. - * Access: RW - */ -MLXSW_ITEM32(reg, mcia, l, 0x00, 31, 1); - /* reg_mcia_module * Module number. * Access: Index @@ -9764,14 +9756,12 @@ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH + 1) static inline void mlxsw_reg_mcia_pack(char *payload, u8 slot_index, u8 module, - u8 lock, u8 page_number, - u16 device_addr, u8 size, + u8 page_number, u16 device_addr, u8 size, u8 i2c_device_addr) { MLXSW_REG_ZERO(mcia, payload); mlxsw_reg_mcia_slot_set(payload, slot_index); mlxsw_reg_mcia_module_set(payload, module); - mlxsw_reg_mcia_l_set(payload, lock); mlxsw_reg_mcia_page_number_set(payload, page_number); mlxsw_reg_mcia_device_address_set(payload, device_addr); mlxsw_reg_mcia_size_set(payload, size); -- cgit From c8dbf67883db98a1987eefd4872cf997c64ce7e7 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 25 Jul 2023 14:04:04 +0200 Subject: mlxsw: reg: Increase Management Cable Info Access Register length The layout of the register always supported 128 bytes payloads, but the driver defined the register with a shorter length because it uses a maximum payload size of 48 bytes. Increase the register's length in preparation for using 128 bytes payloads. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/ba5c0f631e2cfd61bd21218d0cbfe03fbfe521f9.1690281940.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 3b297797ced4..7a0023ae9586 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -9640,7 +9640,7 @@ static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind, */ #define MLXSW_REG_MCIA_ID 0x9014 -#define MLXSW_REG_MCIA_LEN 0x40 +#define MLXSW_REG_MCIA_LEN 0x94 MLXSW_REG_DEFINE(mcia, MLXSW_REG_MCIA_ID, MLXSW_REG_MCIA_LEN); -- cgit From 1f4aea1f72da039d830862bc690dbd2d355dc992 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 25 Jul 2023 14:04:05 +0200 Subject: mlxsw: core_env: Read transceiver module EEPROM in 128 bytes chunks Old firmware versions could only read up to 48 bytes from a transceiver module's EEPROM in one go. Newer versions can read up to 128 bytes, resulting in fewer transactions. Query support for the new capability during driver initialization and if supported, read up to 128 bytes in one go. This is going to be especially useful for upcoming transceiver module firmware flashing support. Before: # perf stat -e devlink:devlink_hwmsg -- ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50 [...] Performance counter stats for 'ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50': 3 devlink:devlink_hwmsg After: # perf stat -e devlink:devlink_hwmsg -- ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50 [...] Performance counter stats for 'ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50': 1 devlink:devlink_hwmsg Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/99d1618e8cd5acefb2f795dfde1a5b41caa07dcb.1690281940.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 35 +++++++++++++++++++++----- drivers/net/ethernet/mellanox/mlxsw/reg.h | 3 +-- 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 679f7488ba10..d637c0348fa1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -32,6 +32,7 @@ struct mlxsw_env { const struct mlxsw_bus_info *bus_info; u8 max_module_count; /* Maximum number of modules per-slot. */ u8 num_of_slots; /* Including the main board. */ + u8 max_eeprom_len; /* Maximum module EEPROM transaction length. */ struct mutex line_cards_lock; /* Protects line cards. */ struct mlxsw_env_line_card *line_cards[]; }; @@ -146,6 +147,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index, int module, u16 offset, u16 size, void *data, bool qsfp, unsigned int *p_read_size) { + struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); char mcia_pl[MLXSW_REG_MCIA_LEN]; char *eeprom_tmp; u16 i2c_addr; @@ -153,11 +155,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index, int status; int err; - /* MCIA register accepts buffer size <= 48. Page of size 128 should be - * read by chunks of size 48, 48, 32. Align the size of the last chunk - * to avoid reading after the end of the page. - */ - size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); + size = min_t(u16, size, mlxsw_env->max_eeprom_len); if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) @@ -489,7 +487,7 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 size; size = min_t(u8, page->length - bytes_read, - MLXSW_REG_MCIA_EEPROM_SIZE); + mlxsw_env->max_eeprom_len); mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page->page, device_addr + bytes_read, size, @@ -1359,6 +1357,26 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = { .got_inactive = mlxsw_env_got_inactive, }; +static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env) +{ + char mcam_pl[MLXSW_REG_MCAM_LEN]; + bool mcia_128b_supported; + int err; + + mlxsw_reg_mcam_pack(mcam_pl, + MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES); + err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl); + if (err) + return err; + + mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B, + &mcia_128b_supported); + + mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48; + + return 0; +} + int mlxsw_env_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *bus_info, struct mlxsw_env **p_env) @@ -1427,10 +1445,15 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, if (err) goto err_type_set; + err = mlxsw_env_max_module_eeprom_len_query(env); + if (err) + goto err_eeprom_len_query; + env->line_cards[0]->active = true; return 0; +err_eeprom_len_query: err_type_set: mlxsw_env_module_event_disable(env, 0); err_mlxsw_env_module_event_enable: diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 7a0023ae9586..4b90ae44b476 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -9708,7 +9708,6 @@ MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16); #define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH 256 #define MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH 128 -#define MLXSW_REG_MCIA_EEPROM_SIZE 48 #define MLXSW_REG_MCIA_I2C_ADDR_LOW 0x50 #define MLXSW_REG_MCIA_I2C_ADDR_HIGH 0x51 #define MLXSW_REG_MCIA_PAGE0_LO_OFF 0xa0 @@ -9745,7 +9744,7 @@ enum mlxsw_reg_mcia_eeprom_module_info { * Bytes to read/write. * Access: RW */ -MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); +MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, 128); /* This is used to access the optional upper pages (1-3) in the QSFP+ * memory map. Page 1 is available on offset 256 through 383, page 2 - -- cgit From f44a90104ee5aceaf39b5a10787ab34c46c987ba Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 24 Jul 2023 15:18:58 -0600 Subject: net: dsa: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Vladimir Oltean Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230724211859.805481-1-robh@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mdio.c | 1 + drivers/net/dsa/b53/b53_mmap.c | 1 + drivers/net/dsa/hirschmann/hellcreek.c | 1 - drivers/net/dsa/hirschmann/hellcreek_ptp.c | 1 + drivers/net/dsa/lan9303-core.c | 1 + drivers/net/dsa/microchip/ksz8863_smi.c | 3 +++ drivers/net/dsa/microchip/ksz_common.c | 2 +- drivers/net/dsa/mt7530-mmio.c | 3 ++- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/dsa/ocelot/seville_vsc9953.c | 3 ++- drivers/net/dsa/qca/qca8k-leds.c | 1 + drivers/net/dsa/realtek/realtek-mdio.c | 2 +- drivers/net/dsa/realtek/realtek-smi.c | 1 - drivers/net/dsa/sja1105/sja1105_main.c | 1 - drivers/net/dsa/vitesse-vsc73xx-core.c | 1 - drivers/net/dsa/xrs700x/xrs700x.c | 2 +- 17 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/b53/b53_mdio.c b/drivers/net/dsa/b53/b53_mdio.c index 8b422b298cd5..4d55d8d18376 100644 --- a/drivers/net/dsa/b53/b53_mdio.c +++ b/drivers/net/dsa/b53/b53_mdio.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index 5db1ed26f03a..5e39641ea887 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index af50001ccdd4..720f4e4ed0b0 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/dsa/hirschmann/hellcreek_ptp.c b/drivers/net/dsa/hirschmann/hellcreek_ptp.c index 3e44ccb7db84..5249a1c2a80b 100644 --- a/drivers/net/dsa/hirschmann/hellcreek_ptp.c +++ b/drivers/net/dsa/hirschmann/hellcreek_ptp.c @@ -9,6 +9,7 @@ * Kurt Kanzenbach */ +#include #include #include "hellcreek.h" #include "hellcreek_ptp.h" diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index b0da1e4de63c..ee67adeb2cdb 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index fd6e2e69a42a..5711a59e2ac9 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -5,6 +5,9 @@ * Copyright (C) 2019 Pengutronix, Michael Grzeschik */ +#include +#include + #include "ksz8.h" #include "ksz_common.h" diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 1de2251a42dc..2414c1f8bc2d 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/dsa/mt7530-mmio.c b/drivers/net/dsa/mt7530-mmio.c index 1a3d4b692f34..0a6a2fe34e64 100644 --- a/drivers/net/dsa/mt7530-mmio.c +++ b/drivers/net/dsa/mt7530-mmio.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only +#include #include -#include +#include #include #include #include diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 11a2e3d38484..bce9c9e43752 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 1c113957fcf4..dce3548dcd05 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "felix.h" diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 15003b2af264..8f912bda120b 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -2,13 +2,14 @@ /* Distributed Switch Architecture VSC9953 driver * Copyright (C) 2020, Maxim Kochetkov */ +#include #include #include #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c index 1261e0bb21ef..e8c16e76e34b 100644 --- a/drivers/net/dsa/qca/qca8k-leds.c +++ b/drivers/net/dsa/qca/qca8k-leds.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c index 5a8fe707ca25..4310e7793e58 100644 --- a/drivers/net/dsa/realtek/realtek-mdio.c +++ b/drivers/net/dsa/realtek/realtek-mdio.c @@ -20,7 +20,7 @@ */ #include -#include +#include #include #include diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c index 1b447d96b9c4..c2bd8bb6c9c2 100644 --- a/drivers/net/dsa/realtek/realtek-smi.c +++ b/drivers/net/dsa/realtek/realtek-smi.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 52dd52d6c43d..331bb1c6676a 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c index ef1a4a7c47b2..4f09e7438f3b 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-core.c +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c index fa622639d640..753fef757f11 100644 --- a/drivers/net/dsa/xrs700x/xrs700x.c +++ b/drivers/net/dsa/xrs700x/xrs700x.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include "xrs700x.h" -- cgit From ac3cb6de32b62f08d76109e98e174ce0ebf3c022 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 24 Jul 2023 15:19:05 -0600 Subject: net: phy/pcs: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230724211905.805665-1-robh@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/pcs/pcs-rzn1-miic.c | 1 + drivers/net/phy/marvell-88x2222.c | 1 - drivers/net/phy/mediatek-ge-soc.c | 2 -- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c index 323bec5e57f8..e5d642c67a2c 100644 --- a/drivers/net/pcs/pcs-rzn1-miic.c +++ b/drivers/net/pcs/pcs-rzn1-miic.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c index f83cae64585d..e3aa30dad2e6 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c index 95369171a7ba..da512fab0eb0 100644 --- a/drivers/net/phy/mediatek-ge-soc.c +++ b/drivers/net/phy/mediatek-ge-soc.c @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include -- cgit From a008e2a84e6b2b598af6fadf6c8f756d4fe639ca Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:52:02 +0100 Subject: net: ethernet: mtk_eth_soc: add version in mtk_soc_data Introduce version field in mtk_soc_data data structure in order to make mtk_eth driver easier to maintain for chipset configuration codebase. Get rid of MTK_NETSYS_V2 bit in chip capabilities. This is a preliminary patch to introduce support for MT7988 SoC. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/e52fae302ca135436e5cdd26d38d87be2da63055.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 55 ++++++++++++++----------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 36 ++++++++++------ drivers/net/ethernet/mediatek/mtk_ppe.c | 18 ++++---- drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- drivers/net/ethernet/mediatek/mtk_wed.c | 4 +- 5 files changed, 66 insertions(+), 49 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 7490d48000c2..206cffb0e5ac 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -593,7 +593,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | MTK_QTX_SCH_LEAKY_BUCKET_SIZE; - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v1(eth)) val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; if (IS_ENABLED(CONFIG_SOC_MT7621)) { @@ -970,7 +970,7 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd, rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); } @@ -1028,7 +1028,7 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); txd->txd4 = 0; - if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { txd->txd5 = 0; txd->txd6 = 0; txd->txd7 = 0; @@ -1219,7 +1219,7 @@ static void mtk_tx_set_dma_desc(struct net_device *dev, void *txd, struct mtk_mac *mac = netdev_priv(dev); struct mtk_eth *eth = mac->hw; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) mtk_tx_set_dma_desc_v2(dev, txd, info); else mtk_tx_set_dma_desc_v1(dev, txd, info); @@ -1526,7 +1526,7 @@ static void mtk_update_rx_cpu_idx(struct mtk_eth *eth) static bool mtk_page_pool_enabled(struct mtk_eth *eth) { - return MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2); + return eth->soc->version == 2; } static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, @@ -1868,7 +1868,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, break; /* find out which mac the packet come from. values start at 1 */ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) @@ -1964,7 +1964,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, skb->dev = netdev; bytes += skb->len; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; if (hash != MTK_RXD5_FOE_ENTRY) @@ -1989,8 +1989,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, /* When using VLAN untagging in combination with DSA, the * hardware treats the MTK special tag as a VLAN and untags it. */ - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && - (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { + if (mtk_is_netsys_v1(eth) && (trxd.rxd2 & RX_DMA_VTAG) && + netdev_uses_dsa(netdev)) { unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); if (port < ARRAY_SIZE(eth->dsa_meta) && @@ -2300,7 +2300,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth) txd->txd2 = next_ptr; txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; txd->txd4 = 0; - if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { txd->txd5 = 0; txd->txd6 = 0; txd->txd7 = 0; @@ -2353,14 +2353,14 @@ static int mtk_tx_alloc(struct mtk_eth *eth) FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | MTK_QTX_SCH_LEAKY_BUCKET_SIZE; - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v1(eth)) val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); ofs += MTK_QTX_OFFSET; } val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); } else { mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); @@ -2489,7 +2489,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) rxd->rxd3 = 0; rxd->rxd4 = 0; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { rxd->rxd5 = 0; rxd->rxd6 = 0; rxd->rxd7 = 0; @@ -3037,7 +3037,7 @@ static int mtk_start_dma(struct mtk_eth *eth) MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) val |= MTK_MUTLI_CNT | MTK_RESV_BUF | MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; @@ -3183,7 +3183,7 @@ static int mtk_open(struct net_device *dev) phylink_start(mac->phylink); netif_tx_start_all_queues(dev); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return 0; if (mtk_uses_dsa(dev) && !eth->prog) { @@ -3449,7 +3449,7 @@ static void mtk_hw_reset(struct mtk_eth *eth) { u32 val; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); val = RSTCTRL_PPE0_V2; } else { @@ -3461,7 +3461,7 @@ static void mtk_hw_reset(struct mtk_eth *eth) ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff); } @@ -3487,7 +3487,7 @@ static void mtk_hw_warm_reset(struct mtk_eth *eth) return; } - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; else rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; @@ -3657,7 +3657,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) else mtk_hw_reset(eth); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { /* Set FE to PDMAv2 if necessary */ val = mtk_r32(eth, MTK_FE_GLO_MISC); mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); @@ -3694,7 +3694,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) */ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v1(eth)) { val = mtk_r32(eth, MTK_CDMP_IG_CTRL); mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); @@ -3716,7 +3716,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { /* PSE should not drop port8 and port9 packets from WDMA Tx */ mtk_w32(eth, 0x00000300, PSE_DROP_CFG); @@ -4521,7 +4521,7 @@ static int mtk_probe(struct platform_device *pdev) } } - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { err = -EINVAL; @@ -4629,9 +4629,8 @@ static int mtk_probe(struct platform_device *pdev) } if (eth->soc->offload_version) { - u32 num_ppe; + u32 num_ppe = mtk_is_netsys_v2_or_greater(eth) ? 2 : 1; - num_ppe = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); for (i = 0; i < num_ppe; i++) { u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; @@ -4723,6 +4722,7 @@ static const struct mtk_soc_data mt2701_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, + .version = 1, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), @@ -4739,6 +4739,7 @@ static const struct mtk_soc_data mt7621_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7621_CLKS_BITMAP, .required_pctl = false, + .version = 1, .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -4759,6 +4760,7 @@ static const struct mtk_soc_data mt7622_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7622_CLKS_BITMAP, .required_pctl = false, + .version = 1, .offload_version = 2, .hash_offset = 2, .has_accounting = true, @@ -4779,6 +4781,7 @@ static const struct mtk_soc_data mt7623_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, + .version = 1, .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -4801,6 +4804,7 @@ static const struct mtk_soc_data mt7629_data = { .required_clks = MT7629_CLKS_BITMAP, .required_pctl = false, .has_accounting = true, + .version = 1, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), @@ -4818,6 +4822,7 @@ static const struct mtk_soc_data mt7981_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7981_CLKS_BITMAP, .required_pctl = false, + .version = 2, .offload_version = 2, .hash_offset = 4, .has_accounting = true, @@ -4839,6 +4844,7 @@ static const struct mtk_soc_data mt7986_data = { .hw_features = MTK_HW_FEATURES, .required_clks = MT7986_CLKS_BITMAP, .required_pctl = false, + .version = 2, .offload_version = 2, .hash_offset = 4, .has_accounting = true, @@ -4859,6 +4865,7 @@ static const struct mtk_soc_data rt5350_data = { .hw_features = MTK_HW_FEATURES_MT7628, .required_clks = MT7628_CLKS_BITMAP, .required_pctl = false, + .version = 1, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 28adda0c90c0..8ca368973e92 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -820,7 +820,6 @@ enum mkt_eth_capabilities { MTK_SHARED_INT_BIT, MTK_TRGMII_MT7621_CLK_BIT, MTK_QDMA_BIT, - MTK_NETSYS_V2_BIT, MTK_SOC_MT7628_BIT, MTK_RSTCTRL_PPE1_BIT, MTK_U3_COPHY_V2_BIT, @@ -855,7 +854,6 @@ enum mkt_eth_capabilities { #define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) #define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) #define MTK_QDMA BIT(MTK_QDMA_BIT) -#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) #define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) #define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) #define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) @@ -934,11 +932,11 @@ enum mkt_eth_capabilities { #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ - MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) + MTK_RSTCTRL_PPE1) #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) + MTK_RSTCTRL_PPE1) struct mtk_tx_dma_desc_info { dma_addr_t addr; @@ -1009,6 +1007,7 @@ struct mtk_reg_map { * @required_pctl A bool value to show whether the SoC requires * the extra setup for those pins used by GMAC. * @hash_offset Flow table hash offset. + * @version SoC version. * @foe_entry_size Foe table entry size. * @has_accounting Bool indicating support for accounting of * offloaded flows. @@ -1027,6 +1026,7 @@ struct mtk_soc_data { bool required_pctl; u8 offload_version; u8 hash_offset; + u8 version; u16 foe_entry_size; netdev_features_t hw_features; bool has_accounting; @@ -1183,6 +1183,16 @@ struct mtk_mac { /* the struct describing the SoC. these are declared in the soc_xyz.c files */ extern const struct of_device_id of_mtk_match[]; +static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) +{ + return eth->soc->version == 1; +} + +static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) +{ + return eth->soc->version > 1; +} + static inline struct mtk_foe_entry * mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) { @@ -1193,7 +1203,7 @@ mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB1_BIND_TIMESTAMP_V2; return MTK_FOE_IB1_BIND_TIMESTAMP; @@ -1201,7 +1211,7 @@ static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth) static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB1_BIND_PPPOE_V2; return MTK_FOE_IB1_BIND_PPPOE; @@ -1209,7 +1219,7 @@ static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth) static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB1_BIND_VLAN_TAG_V2; return MTK_FOE_IB1_BIND_VLAN_TAG; @@ -1217,7 +1227,7 @@ static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth) static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB1_BIND_VLAN_LAYER_V2; return MTK_FOE_IB1_BIND_VLAN_LAYER; @@ -1225,7 +1235,7 @@ static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth) static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, val); @@ -1233,7 +1243,7 @@ static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val) static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, val); @@ -1241,7 +1251,7 @@ static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val) static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB1_PACKET_TYPE_V2; return MTK_FOE_IB1_PACKET_TYPE; @@ -1249,7 +1259,7 @@ static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth) static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE_V2, val); return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, val); @@ -1257,7 +1267,7 @@ static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val) static inline u32 mtk_get_ib2_multicast_mask(struct mtk_eth *eth) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) return MTK_FOE_IB2_MULTICAST_V2; return MTK_FOE_IB2_MULTICAST; diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index 9129821f3ab8..2f0e682449ef 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -208,7 +208,7 @@ int mtk_foe_entry_prepare(struct mtk_eth *eth, struct mtk_foe_entry *entry, memset(entry, 0, sizeof(*entry)); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE_V2, type) | FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | @@ -272,7 +272,7 @@ int mtk_foe_entry_set_pse_port(struct mtk_eth *eth, u32 *ib2 = mtk_foe_entry_ib2(eth, entry); u32 val = *ib2; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { val &= ~MTK_FOE_IB2_DEST_PORT_V2; val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, port); } else { @@ -423,7 +423,7 @@ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | MTK_FOE_IB2_WDMA_WINFO_V2; @@ -447,7 +447,7 @@ int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, { u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { *ib2 &= ~MTK_FOE_IB2_QID_V2; *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; @@ -603,7 +603,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, struct mtk_foe_entry *hwe; u32 val; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP_V2, timestamp); @@ -619,7 +619,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, hwe->ib1 = entry->ib1; if (ppe->accounting) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) val = MTK_FOE_IB2_MIB_CNT_V2; else val = MTK_FOE_IB2_MIB_CNT; @@ -979,7 +979,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, MTK_PPE_ENTRIES_SHIFT); - if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(ppe->eth)) val |= MTK_PPE_TB_CFG_INFO_SEL; ppe_w32(ppe, MTK_PPE_TB_CFG, val); @@ -995,7 +995,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) MTK_PPE_FLOW_CFG_IP4_NAPT | MTK_PPE_FLOW_CFG_IP4_DSLITE | MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; - if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(ppe->eth)) val |= MTK_PPE_MD_TOAP_BYP_CRSN0 | MTK_PPE_MD_TOAP_BYP_CRSN1 | MTK_PPE_MD_TOAP_BYP_CRSN2 | @@ -1037,7 +1037,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); - if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(ppe->eth)) { ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); } diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c index 02eebff02d45..a70a5417c173 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -193,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, info.bss, info.wcid); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + if (mtk_is_netsys_v2_or_greater(eth)) { switch (info.wdma_idx) { case 0: pse_port = 8; diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c index 985cff910f30..5f062ecb402c 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -1091,7 +1091,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev) } else { struct mtk_eth *eth = dev->hw->eth; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + if (mtk_is_netsys_v2_or_greater(eth)) wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX_V2); else @@ -1907,7 +1907,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, hw->wdma = wdma; hw->index = index; hw->irq = irq; - hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; + hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; if (hw->version == 1) { hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, -- cgit From 6ca265571b9e04ecc805e51c30e2949c9714dcaa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:52:27 +0100 Subject: net: ethernet: mtk_eth_soc: increase MAX_DEVS to 3 This is a preliminary patch to add MT7988 SoC support since it runs 3 macs instead of 2. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/3563e5fab367e7d79a7f1296fabaa5c20f202d7a.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 8ca368973e92..9623b909387a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -1043,8 +1043,8 @@ struct mtk_soc_data { #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) -/* currently no SoC has more than 2 macs */ -#define MTK_MAX_DEVS 2 +/* currently no SoC has more than 3 macs */ +#define MTK_MAX_DEVS 3 /* struct mtk_eth - This is the main datasructure for holding the state * of the driver -- cgit From e05fd6274ee657cbf1689aba23ee900727cd4b8c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:52:44 +0100 Subject: net: ethernet: mtk_eth_soc: rely on MTK_MAX_DEVS and remove MTK_MAC_COUNT Get rid of MTK_MAC_COUNT since it is a duplicated of MTK_MAX_DEVS. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/1856f4266f2fc80677807b1bad867659e7b00c65.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++++++++++------------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - 2 files changed, 27 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 206cffb0e5ac..67109a38df31 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -896,7 +896,7 @@ static void mtk_stats_update(struct mtk_eth *eth) { int i; - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->mac[i] || !eth->mac[i]->hw_stats) continue; if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { @@ -1401,7 +1401,7 @@ static int mtk_queue_stopped(struct mtk_eth *eth) { int i; - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->netdev[i]) continue; if (netif_queue_stopped(eth->netdev[i])) @@ -1415,7 +1415,7 @@ static void mtk_wake_queue(struct mtk_eth *eth) { int i; - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->netdev[i]) continue; netif_tx_wake_all_queues(eth->netdev[i]); @@ -1874,7 +1874,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; - if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || + if (unlikely(mac < 0 || mac >= MTK_MAX_DEVS || !eth->netdev[mac])) goto release_desc; @@ -2911,7 +2911,7 @@ static void mtk_dma_free(struct mtk_eth *eth) const struct mtk_soc_data *soc = eth->soc; int i; - for (i = 0; i < MTK_MAC_COUNT; i++) + for (i = 0; i < MTK_MAX_DEVS; i++) if (eth->netdev[i]) netdev_reset_queue(eth->netdev[i]); if (eth->scratch_ring) { @@ -3065,8 +3065,13 @@ static void mtk_gdm_config(struct mtk_eth *eth, u32 config) if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) return; - for (i = 0; i < MTK_MAC_COUNT; i++) { - u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); + for (i = 0; i < MTK_MAX_DEVS; i++) { + u32 val; + + if (!eth->netdev[i]) + continue; + + val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); /* default setup the forward port to send frame to PDMA */ val &= ~0xffff; @@ -3076,7 +3081,7 @@ static void mtk_gdm_config(struct mtk_eth *eth, u32 config) val |= config; - if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) + if (netdev_uses_dsa(eth->netdev[i])) val |= MTK_GDMA_SPECIAL_TAG; mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); @@ -3678,15 +3683,15 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) * up with the more appropriate value when mtk_mac_config call is being * invoked. */ - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { struct net_device *dev = eth->netdev[i]; - mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); - if (dev) { - struct mtk_mac *mac = netdev_priv(dev); + if (!dev) + continue; - mtk_set_mcr_max_rx(mac, dev->mtu + MTK_RX_ETH_HLEN); - } + mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); + mtk_set_mcr_max_rx(netdev_priv(dev), + dev->mtu + MTK_RX_ETH_HLEN); } /* Indicates CDM to parse the MTK special tag from CPU @@ -3866,7 +3871,7 @@ static void mtk_pending_work(struct work_struct *work) mtk_prepare_for_reset(eth); /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->netdev[i] || !netif_running(eth->netdev[i])) continue; @@ -3882,8 +3887,8 @@ static void mtk_pending_work(struct work_struct *work) mtk_hw_init(eth, true); /* restart DMA and enable IRQs */ - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!test_bit(i, &restart)) + for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i] || !test_bit(i, &restart)) continue; if (mtk_open(eth->netdev[i])) { @@ -3910,7 +3915,7 @@ static int mtk_free_dev(struct mtk_eth *eth) { int i; - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->netdev[i]) continue; free_netdev(eth->netdev[i]); @@ -3929,7 +3934,7 @@ static int mtk_unreg_dev(struct mtk_eth *eth) { int i; - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { struct mtk_mac *mac; if (!eth->netdev[i]) continue; @@ -4231,7 +4236,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) } id = be32_to_cpup(_id); - if (id >= MTK_MAC_COUNT) { + if (id >= MTK_MAX_DEVS) { dev_err(eth->dev, "%d is not a valid mac id\n", id); return -EINVAL; } @@ -4391,7 +4396,7 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) rtnl_lock(); - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { dev = eth->netdev[i]; if (!dev || !(dev->flags & IFF_UP)) @@ -4697,7 +4702,7 @@ static int mtk_remove(struct platform_device *pdev) int i; /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { + for (i = 0; i < MTK_MAX_DEVS; i++) { if (!eth->netdev[i]) continue; mtk_stop(eth->netdev[i]); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 9623b909387a..4dc5611f859b 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -33,7 +33,6 @@ #define MTK_TX_DMA_BUF_LEN_V2 0xffff #define MTK_QDMA_RING_SIZE 2048 #define MTK_DMA_SIZE 512 -#define MTK_MAC_COUNT 2 #define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) #define MTK_DMA_DUMMY_DESC 0xffffffff -- cgit From 1953f134a1a8b4732f6e1b15d0407959bf60209d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:52:59 +0100 Subject: net: ethernet: mtk_eth_soc: add NETSYS_V3 version support Introduce NETSYS_V3 chipset version support. This is a preliminary patch to introduce support for MT7988 SoC. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/0db2260910755d76fa48e303b9f9bdf4e5a82340.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 105 ++++++++++++++++++++-------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 ++++++++++--- 2 files changed, 116 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 67109a38df31..1344e2fc6d6f 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -876,17 +876,32 @@ void mtk_stats_update_mac(struct mtk_mac *mac) mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs); hw_stats->rx_flow_control_packets += mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs); - hw_stats->tx_skip += - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); - hw_stats->tx_collisions += - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); - hw_stats->tx_bytes += - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); - stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); - if (stats) - hw_stats->tx_bytes += (stats << 32); - hw_stats->tx_packets += - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); + + if (mtk_is_netsys_v3_or_greater(eth)) { + hw_stats->tx_skip += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x50 + offs); + hw_stats->tx_collisions += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x54 + offs); + hw_stats->tx_bytes += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x40 + offs); + stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x44 + offs); + if (stats) + hw_stats->tx_bytes += (stats << 32); + hw_stats->tx_packets += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x48 + offs); + } else { + hw_stats->tx_skip += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); + hw_stats->tx_collisions += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); + hw_stats->tx_bytes += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); + stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); + if (stats) + hw_stats->tx_bytes += (stats << 32); + hw_stats->tx_packets += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); + } } u64_stats_update_end(&hw_stats->syncp); @@ -1190,7 +1205,10 @@ static void mtk_tx_set_dma_desc_v2(struct net_device *dev, void *txd, data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); - data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ + if (mac->id == MTK_GMAC3_ID) + data = PSE_GDM3_PORT; + else + data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); WRITE_ONCE(desc->txd4, data); @@ -1201,6 +1219,8 @@ static void mtk_tx_set_dma_desc_v2(struct net_device *dev, void *txd, /* tx checksum offload */ if (info->csum) data |= TX_DMA_CHKSUM_V2; + if (mtk_is_netsys_v3_or_greater(eth) && netdev_uses_dsa(dev)) + data |= TX_DMA_SPTAG_V3; } WRITE_ONCE(desc->txd5, data); @@ -1266,8 +1286,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, mtk_tx_set_dma_desc(dev, itxd, &txd_info); itx_buf->flags |= MTK_TX_FLAGS_SINGLE0; - itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : - MTK_TX_FLAGS_FPORT1; + itx_buf->mac_id = mac->id; setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, k++); @@ -1315,8 +1334,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, memset(tx_buf, 0, sizeof(*tx_buf)); tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; tx_buf->flags |= MTK_TX_FLAGS_PAGE0; - tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : - MTK_TX_FLAGS_FPORT1; + tx_buf->mac_id = mac->id; setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, txd_info.size, k++); @@ -1618,7 +1636,7 @@ static int mtk_xdp_frame_map(struct mtk_eth *eth, struct net_device *dev, } mtk_tx_set_dma_desc(dev, txd, txd_info); - tx_buf->flags |= !mac->id ? MTK_TX_FLAGS_FPORT0 : MTK_TX_FLAGS_FPORT1; + tx_buf->mac_id = mac->id; tx_buf->type = dma_map ? MTK_TYPE_XDP_NDO : MTK_TYPE_XDP_TX; tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; @@ -1868,11 +1886,24 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, break; /* find out which mac the packet come from. values start at 1 */ - if (mtk_is_netsys_v2_or_greater(eth)) - mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; - else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && - !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) + if (mtk_is_netsys_v2_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { + case PSE_GDM1_PORT: + case PSE_GDM2_PORT: + mac = val - 1; + break; + case PSE_GDM3_PORT: + mac = MTK_GMAC3_ID; + break; + default: + break; + } + } else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && + !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) { mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; + } if (unlikely(mac < 0 || mac >= MTK_MAX_DEVS || !eth->netdev[mac])) @@ -2094,7 +2125,6 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, while ((cpu != dma) && budget) { u32 next_cpu = desc->txd2; - int mac = 0; desc = mtk_qdma_phys_to_virt(ring, desc->txd2); if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) @@ -2102,15 +2132,13 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, tx_buf = mtk_desc_to_tx_buf(ring, desc, eth->soc->txrx.txd_size); - if (tx_buf->flags & MTK_TX_FLAGS_FPORT1) - mac = 1; - if (!tx_buf->data) break; if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { if (tx_buf->type == MTK_TYPE_SKB) - mtk_poll_tx_done(eth, state, mac, tx_buf->data); + mtk_poll_tx_done(eth, state, tx_buf->mac_id, + tx_buf->data); budget--; } @@ -3721,7 +3749,24 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); - if (mtk_is_netsys_v2_or_greater(eth)) { + if (mtk_is_netsys_v3_or_greater(eth)) { + /* PSE should not drop port1, port8 and port9 packets */ + mtk_w32(eth, 0x00000302, PSE_DROP_CFG); + + /* GDM and CDM Threshold */ + mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES); + mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES); + + /* Disable GDM1 RX CRC stripping */ + mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, MTK_GDMA_FWD_CFG(0)); + + /* PSE GDM3 MIB counter has incorrect hw default values, + * so the driver ought to read clear the values beforehand + * in case ethtool retrieve wrong mib values. + */ + for (i = 0; i < 0x80; i += 0x4) + mtk_r32(eth, reg_map->gdm1_cnt + 0x100 + i); + } else if (!mtk_is_netsys_v1(eth)) { /* PSE should not drop port8 and port9 packets from WDMA Tx */ mtk_w32(eth, 0x00000300, PSE_DROP_CFG); @@ -4284,7 +4329,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) } spin_lock_init(&mac->hw_stats->stats_lock); u64_stats_init(&mac->hw_stats->syncp); - mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; + + if (mtk_is_netsys_v3_or_greater(eth)) + mac->hw_stats->reg_offset = id * 0x80; + else + mac->hw_stats->reg_offset = id * 0x40; /* phylink create */ err = of_get_phy_mode(np, &phy_mode); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 4dc5611f859b..3959bb39995f 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -122,6 +122,7 @@ #define MTK_GDMA_ICS_EN BIT(22) #define MTK_GDMA_TCS_EN BIT(21) #define MTK_GDMA_UCS_EN BIT(20) +#define MTK_GDMA_STRP_CRC BIT(16) #define MTK_GDMA_TO_PDMA 0x0 #define MTK_GDMA_DROP_ALL 0x7777 @@ -287,8 +288,6 @@ /* QDMA Interrupt grouping registers */ #define MTK_RLS_DONE_INT BIT(0) -#define MTK_STAT_OFFSET 0x40 - /* QDMA TX NUM */ #define QID_BITS_V2(x) (((x) & 0x3f) << 16) #define MTK_QDMA_GMAC2_QID 8 @@ -301,6 +300,8 @@ #define TX_DMA_CHKSUM_V2 (0x7 << 28) #define TX_DMA_TSO_V2 BIT(31) +#define TX_DMA_SPTAG_V3 BIT(27) + /* QDMA V2 descriptor txd4 */ #define TX_DMA_FPORT_SHIFT_V2 8 #define TX_DMA_FPORT_MASK_V2 0xf @@ -634,12 +635,6 @@ enum mtk_tx_flags { */ MTK_TX_FLAGS_SINGLE0 = 0x01, MTK_TX_FLAGS_PAGE0 = 0x02, - - /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted - * SKB out instead of looking up through hardware TX descriptor. - */ - MTK_TX_FLAGS_FPORT0 = 0x04, - MTK_TX_FLAGS_FPORT1 = 0x08, }; /* This enum allows us to identify how the clock is defined on the array of the @@ -725,6 +720,35 @@ enum mtk_dev_state { MTK_RESETTING }; +/* PSE Port Definition */ +enum mtk_pse_port { + PSE_ADMA_PORT = 0, + PSE_GDM1_PORT, + PSE_GDM2_PORT, + PSE_PPE0_PORT, + PSE_PPE1_PORT, + PSE_QDMA_TX_PORT, + PSE_QDMA_RX_PORT, + PSE_DROP_PORT, + PSE_WDMA0_PORT, + PSE_WDMA1_PORT, + PSE_TDMA_PORT, + PSE_NONE_PORT, + PSE_PPE2_PORT, + PSE_WDMA2_PORT, + PSE_EIP197_PORT, + PSE_GDM3_PORT, + PSE_PORT_MAX +}; + +/* GMAC Identifier */ +enum mtk_gmac_id { + MTK_GMAC1_ID = 0, + MTK_GMAC2_ID, + MTK_GMAC3_ID, + MTK_GMAC_ID_MAX +}; + enum mtk_tx_buf_type { MTK_TYPE_SKB, MTK_TYPE_XDP_TX, @@ -743,7 +767,8 @@ struct mtk_tx_buf { enum mtk_tx_buf_type type; void *data; - u32 flags; + u16 mac_id; + u16 flags; DEFINE_DMA_UNMAP_ADDR(dma_addr0); DEFINE_DMA_UNMAP_LEN(dma_len0); DEFINE_DMA_UNMAP_ADDR(dma_addr1); @@ -1192,6 +1217,11 @@ static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) return eth->soc->version > 1; } +static inline bool mtk_is_netsys_v3_or_greater(struct mtk_eth *eth) +{ + return eth->soc->version > 2; +} + static inline struct mtk_foe_entry * mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) { -- cgit From 51a4df60db5c2071782ba42a6803bb682e1d1f0a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:53:13 +0100 Subject: net: ethernet: mtk_eth_soc: convert caps in mtk_soc_data struct to u64 This is a preliminary patch to introduce support for MT7988 SoC. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/9499ac3670b2fc5b444404b84e8a4a169beabbf2.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 +++++------ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 56 ++++++++++++++-------------- 2 files changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_path.c b/drivers/net/ethernet/mediatek/mtk_eth_path.c index 317e447f4991..34ac492e047c 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -15,10 +15,10 @@ struct mtk_eth_muxc { const char *name; int cap_bit; - int (*set_path)(struct mtk_eth *eth, int path); + int (*set_path)(struct mtk_eth *eth, u64 path); }; -static const char *mtk_eth_path_name(int path) +static const char *mtk_eth_path_name(u64 path) { switch (path) { case MTK_ETH_PATH_GMAC1_RGMII: @@ -40,7 +40,7 @@ static const char *mtk_eth_path_name(int path) } } -static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path) +static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) { bool updated = true; u32 val, mask, set; @@ -71,7 +71,7 @@ static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path) return 0; } -static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path) +static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path) { unsigned int val = 0; bool updated = true; @@ -94,7 +94,7 @@ static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path) return 0; } -static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) +static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path) { unsigned int val = 0, mask = 0, reg = 0; bool updated = true; @@ -125,7 +125,7 @@ static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) return 0; } -static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path) +static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) { unsigned int val = 0; bool updated = true; @@ -163,7 +163,7 @@ static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path) return 0; } -static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path) +static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) { unsigned int val = 0; bool updated = true; @@ -218,7 +218,7 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] = { }, }; -static int mtk_eth_mux_setup(struct mtk_eth *eth, int path) +static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path) { int i, err = 0; @@ -249,7 +249,7 @@ out: int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) { - int path; + u64 path; path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : MTK_ETH_PATH_GMAC2_SGMII; @@ -260,7 +260,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) { - int path = 0; + u64 path = 0; if (mac_id == 1) path = MTK_ETH_PATH_GMAC2_GEPHY; @@ -274,7 +274,7 @@ int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) { - int path; + u64 path; path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII : MTK_ETH_PATH_GMAC2_RGMII; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 3959bb39995f..9fe6e44f5e32 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -866,41 +866,41 @@ enum mkt_eth_capabilities { }; /* Supported hardware group on SoCs */ -#define MTK_RGMII BIT(MTK_RGMII_BIT) -#define MTK_TRGMII BIT(MTK_TRGMII_BIT) -#define MTK_SGMII BIT(MTK_SGMII_BIT) -#define MTK_ESW BIT(MTK_ESW_BIT) -#define MTK_GEPHY BIT(MTK_GEPHY_BIT) -#define MTK_MUX BIT(MTK_MUX_BIT) -#define MTK_INFRA BIT(MTK_INFRA_BIT) -#define MTK_SHARED_SGMII BIT(MTK_SHARED_SGMII_BIT) -#define MTK_HWLRO BIT(MTK_HWLRO_BIT) -#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) -#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) -#define MTK_QDMA BIT(MTK_QDMA_BIT) -#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) -#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) -#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) +#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) +#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) +#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) +#define MTK_ESW BIT_ULL(MTK_ESW_BIT) +#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) +#define MTK_MUX BIT_ULL(MTK_MUX_BIT) +#define MTK_INFRA BIT_ULL(MTK_INFRA_BIT) +#define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT) +#define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT) +#define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT) +#define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT) +#define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) +#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) +#define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) +#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) + BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) #define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \ - BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) + BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ - BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) + BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \ - BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) + BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ - BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) + BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) /* Supported path present on SoCs */ -#define MTK_ETH_PATH_GMAC1_RGMII BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT) -#define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT) -#define MTK_ETH_PATH_GMAC1_SGMII BIT(MTK_ETH_PATH_GMAC1_SGMII_BIT) -#define MTK_ETH_PATH_GMAC2_RGMII BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT) -#define MTK_ETH_PATH_GMAC2_SGMII BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT) -#define MTK_ETH_PATH_GMAC2_GEPHY BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT) -#define MTK_ETH_PATH_GDM1_ESW BIT(MTK_ETH_PATH_GDM1_ESW_BIT) +#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) +#define MTK_ETH_PATH_GMAC1_TRGMII BIT_ULL(MTK_ETH_PATH_GMAC1_TRGMII_BIT) +#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) +#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) +#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) +#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) +#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) @@ -1045,7 +1045,7 @@ struct mtk_reg_map { struct mtk_soc_data { const struct mtk_reg_map *reg_map; u32 ana_rgc3; - u32 caps; + u64 caps; u32 required_clks; bool required_pctl; u8 offload_version; -- cgit From c75e416ccfd29257f39e88d0d4b3ced405d5bf01 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 25 Jul 2023 01:53:28 +0100 Subject: net: ethernet: mtk_eth_soc: convert clock bitmap to u64 The to-be-added MT7988 SoC adds many new clocks which need to be controlled by the Ethernet driver, which will result in their total number exceeding 32. Prepare by converting clock bitmaps into 64-bit types. Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/6960a39bb0078cf84d7642a9558e6a91c6cc9df3.1690246066.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 96 +++++++++++++++-------------- 1 file changed, 49 insertions(+), 47 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 9fe6e44f5e32..5902944ddb4f 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -666,54 +666,56 @@ enum mtk_clks_map { MTK_CLK_MAX }; -#define MT7623_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ - BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \ - BIT(MTK_CLK_TRGPLL)) -#define MT7622_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ - BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ - BIT(MTK_CLK_GP2) | \ - BIT(MTK_CLK_SGMII_TX_250M) | \ - BIT(MTK_CLK_SGMII_RX_250M) | \ - BIT(MTK_CLK_SGMII_CDR_REF) | \ - BIT(MTK_CLK_SGMII_CDR_FB) | \ - BIT(MTK_CLK_SGMII_CK) | \ - BIT(MTK_CLK_ETH2PLL)) +#define MT7623_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ + BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ + BIT_ULL(MTK_CLK_TRGPLL)) +#define MT7622_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ + BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ + BIT_ULL(MTK_CLK_GP2) | \ + BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII_CK) | \ + BIT_ULL(MTK_CLK_ETH2PLL)) #define MT7621_CLKS_BITMAP (0) #define MT7628_CLKS_BITMAP (0) -#define MT7629_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ - BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ - BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \ - BIT(MTK_CLK_SGMII_TX_250M) | \ - BIT(MTK_CLK_SGMII_RX_250M) | \ - BIT(MTK_CLK_SGMII_CDR_REF) | \ - BIT(MTK_CLK_SGMII_CDR_FB) | \ - BIT(MTK_CLK_SGMII2_TX_250M) | \ - BIT(MTK_CLK_SGMII2_RX_250M) | \ - BIT(MTK_CLK_SGMII2_CDR_REF) | \ - BIT(MTK_CLK_SGMII2_CDR_FB) | \ - BIT(MTK_CLK_SGMII_CK) | \ - BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP)) -#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ - BIT(MTK_CLK_WOCPU0) | \ - BIT(MTK_CLK_SGMII_TX_250M) | \ - BIT(MTK_CLK_SGMII_RX_250M) | \ - BIT(MTK_CLK_SGMII_CDR_REF) | \ - BIT(MTK_CLK_SGMII_CDR_FB) | \ - BIT(MTK_CLK_SGMII2_TX_250M) | \ - BIT(MTK_CLK_SGMII2_RX_250M) | \ - BIT(MTK_CLK_SGMII2_CDR_REF) | \ - BIT(MTK_CLK_SGMII2_CDR_FB) | \ - BIT(MTK_CLK_SGMII_CK)) -#define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ - BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \ - BIT(MTK_CLK_SGMII_TX_250M) | \ - BIT(MTK_CLK_SGMII_RX_250M) | \ - BIT(MTK_CLK_SGMII_CDR_REF) | \ - BIT(MTK_CLK_SGMII_CDR_FB) | \ - BIT(MTK_CLK_SGMII2_TX_250M) | \ - BIT(MTK_CLK_SGMII2_RX_250M) | \ - BIT(MTK_CLK_SGMII2_CDR_REF) | \ - BIT(MTK_CLK_SGMII2_CDR_FB)) +#define MT7629_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ + BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ + BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_FE) | \ + BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII_CK) | \ + BIT_ULL(MTK_CLK_ETH2PLL) | BIT_ULL(MTK_CLK_SGMIITOP)) +#define MT7981_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | \ + BIT_ULL(MTK_CLK_GP1) | \ + BIT_ULL(MTK_CLK_WOCPU0) | \ + BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII_CK)) +#define MT7986_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | \ + BIT_ULL(MTK_CLK_GP1) | \ + BIT_ULL(MTK_CLK_WOCPU1) | BIT_ULL(MTK_CLK_WOCPU0) | \ + BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ + BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ + BIT_ULL(MTK_CLK_SGMII2_CDR_FB)) enum mtk_dev_state { MTK_HW_INIT, @@ -1046,7 +1048,7 @@ struct mtk_soc_data { const struct mtk_reg_map *reg_map; u32 ana_rgc3; u64 caps; - u32 required_clks; + u64 required_clks; bool required_pctl; u8 offload_version; u8 hash_offset; -- cgit From 445eb6448ed3bf02a76f183e8499d11459281205 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 25 Jul 2023 01:57:42 +0100 Subject: net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC Introduce support for ethernet chip available in MT7988 SoC to mtk_eth_soc driver. As a first step support only the first GMAC which is hard-wired to the internal DSA switch having 4 built-in gigabit Ethernet PHYs. Signed-off-by: Lorenzo Bianconi Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/25c8377095b95d186872eeda7aa055da83e8f0ca.1690246605.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 201 ++++++++++++++++++++++++--- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 86 +++++++++++- 3 files changed, 273 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_path.c b/drivers/net/ethernet/mediatek/mtk_eth_path.c index 34ac492e047c..7c27a19c4d8f 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -43,7 +43,7 @@ static const char *mtk_eth_path_name(u64 path) static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) { bool updated = true; - u32 val, mask, set; + u32 mask, set, reg; switch (path) { case MTK_ETH_PATH_GMAC1_SGMII: @@ -59,11 +59,13 @@ static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) break; } - if (updated) { - val = mtk_r32(eth, MTK_MAC_MISC); - val = (val & mask) | set; - mtk_w32(eth, val, MTK_MAC_MISC); - } + if (mtk_is_netsys_v3_or_greater(eth)) + reg = MTK_MAC_MISC_V3; + else + reg = MTK_MAC_MISC; + + if (updated) + mtk_m32(eth, mask, set, reg); dev_dbg(eth->dev, "path %s in %s updated = %d\n", mtk_eth_path_name(path), __func__, updated); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 1344e2fc6d6f..30e3935e83f9 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -152,6 +152,54 @@ static const struct mtk_reg_map mt7986_reg_map = { .pse_oq_sta = 0x01a0, }; +static const struct mtk_reg_map mt7988_reg_map = { + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { + .rx_ptr = 0x6900, + .rx_cnt_cfg = 0x6904, + .pcrx_ptr = 0x6908, + .glo_cfg = 0x6a04, + .rst_idx = 0x6a08, + .delay_irq = 0x6a0c, + .irq_status = 0x6a20, + .irq_mask = 0x6a28, + .adma_rx_dbg0 = 0x6a38, + .int_grp = 0x6a50, + }, + .qdma = { + .qtx_cfg = 0x4400, + .qtx_sch = 0x4404, + .rx_ptr = 0x4500, + .rx_cnt_cfg = 0x4504, + .qcrx_ptr = 0x4508, + .glo_cfg = 0x4604, + .rst_idx = 0x4608, + .delay_irq = 0x460c, + .fc_th = 0x4610, + .int_grp = 0x4620, + .hred = 0x4644, + .ctx_ptr = 0x4700, + .dtx_ptr = 0x4704, + .crx_ptr = 0x4710, + .drx_ptr = 0x4714, + .fq_head = 0x4720, + .fq_tail = 0x4724, + .fq_count = 0x4728, + .fq_blen = 0x472c, + .tx_sch_rate = 0x4798, + }, + .gdm1_cnt = 0x1c00, + .gdma_to_ppe = 0x3333, + .ppe_base = 0x2000, + .wdma_base = { + [0] = 0x4800, + [1] = 0x4c00, + }, + .pse_iq_sta = 0x0180, + .pse_oq_sta = 0x01a0, +}; + /* strings used by ethtool */ static const struct mtk_ethtool_stats { char str[ETH_GSTRING_LEN]; @@ -179,10 +227,54 @@ static const struct mtk_ethtool_stats { }; static const char * const mtk_clks_source_name[] = { - "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll", - "sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", - "sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb", - "sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1" + "ethif", + "sgmiitop", + "esw", + "gp0", + "gp1", + "gp2", + "gp3", + "xgp1", + "xgp2", + "xgp3", + "crypto", + "fe", + "trgpll", + "sgmii_tx250m", + "sgmii_rx250m", + "sgmii_cdr_ref", + "sgmii_cdr_fb", + "sgmii2_tx250m", + "sgmii2_rx250m", + "sgmii2_cdr_ref", + "sgmii2_cdr_fb", + "sgmii_ck", + "eth2pll", + "wocpu0", + "wocpu1", + "netsys0", + "netsys1", + "ethwarp_wocpu2", + "ethwarp_wocpu1", + "ethwarp_wocpu0", + "top_usxgmii0_sel", + "top_usxgmii1_sel", + "top_sgm0_sel", + "top_sgm1_sel", + "top_xfi_phy0_xtal_sel", + "top_xfi_phy1_xtal_sel", + "top_eth_gmii_sel", + "top_eth_refck_50m_sel", + "top_eth_sys_200m_sel", + "top_eth_sys_sel", + "top_eth_xgmii_sel", + "top_eth_mii_sel", + "top_netsys_sel", + "top_netsys_500m_sel", + "top_netsys_pao_2x_sel", + "top_netsys_sync_250m_sel", + "top_netsys_ppefb_250m_sel", + "top_netsys_warp_sel", }; void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg) @@ -195,7 +287,7 @@ u32 mtk_r32(struct mtk_eth *eth, unsigned reg) return __raw_readl(eth->base + reg); } -static u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg) +u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg) { u32 val; @@ -400,6 +492,19 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); } +static void mtk_setup_bridge_switch(struct mtk_eth *eth) +{ + /* Force Port1 XGMAC Link Up */ + mtk_m32(eth, 0, MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID), + MTK_XGMAC_STS(MTK_GMAC1_ID)); + + /* Adjust GSW bridge IPG to 11 */ + mtk_m32(eth, GSWTX_IPG_MASK | GSWRX_IPG_MASK, + (GSW_IPG_11 << GSWTX_IPG_SHIFT) | + (GSW_IPG_11 << GSWRX_IPG_SHIFT), + MTK_GSW_CFG); +} + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { @@ -459,6 +564,8 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, goto init_err; } break; + case PHY_INTERFACE_MODE_INTERNAL: + break; default: goto err_phy; } @@ -528,6 +635,15 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, return; } + /* Setup gmac */ + if (mtk_is_netsys_v3_or_greater(eth) && + mac->interface == PHY_INTERFACE_MODE_INTERNAL) { + mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id)); + mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id)); + + mtk_setup_bridge_switch(eth); + } + return; err_phy: @@ -740,11 +856,15 @@ static int mtk_mdio_init(struct mtk_eth *eth) } divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); + /* Configure MDC Turbo Mode */ + if (mtk_is_netsys_v3_or_greater(eth)) + mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3); + /* Configure MDC Divider */ - val = mtk_r32(eth, MTK_PPSC); - val &= ~PPSC_MDC_CFG; - val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; - mtk_w32(eth, val, MTK_PPSC); + val = FIELD_PREP(PPSC_MDC_CFG, divider); + if (!mtk_is_netsys_v3_or_greater(eth)) + val |= PPSC_MDC_TURBO; + mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC); dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); @@ -1205,10 +1325,19 @@ static void mtk_tx_set_dma_desc_v2(struct net_device *dev, void *txd, data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); - if (mac->id == MTK_GMAC3_ID) - data = PSE_GDM3_PORT; - else - data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ + /* set forward port */ + switch (mac->id) { + case MTK_GMAC1_ID: + data = PSE_GDM1_PORT << TX_DMA_FPORT_SHIFT_V2; + break; + case MTK_GMAC2_ID: + data = PSE_GDM2_PORT << TX_DMA_FPORT_SHIFT_V2; + break; + case MTK_GMAC3_ID: + data = PSE_GDM3_PORT << TX_DMA_FPORT_SHIFT_V2; + break; + } + data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); WRITE_ONCE(desc->txd4, data); @@ -4387,6 +4516,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->phylink_config.supported_interfaces); } + if (mtk_is_netsys_v3_or_greater(mac->hw) && + MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW_BIT) && + id == MTK_GMAC1_ID) { + mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | + MAC_SYM_PAUSE | + MAC_10000FD; + phy_interface_zero(mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + mac->phylink_config.supported_interfaces); + } + phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); @@ -4913,6 +5053,24 @@ static const struct mtk_soc_data mt7986_data = { }, }; +static const struct mtk_soc_data mt7988_data = { + .reg_map = &mt7988_reg_map, + .ana_rgc3 = 0x128, + .caps = MT7988_CAPS, + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7988_CLKS_BITMAP, + .required_pctl = false, + .version = 3, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), + .rx_irq_done_mask = MTK_RX_DONE_INT_V2, + .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +}; + static const struct mtk_soc_data rt5350_data = { .reg_map = &mt7628_reg_map, .caps = MT7628_CAPS, @@ -4931,14 +5089,15 @@ static const struct mtk_soc_data rt5350_data = { }; const struct of_device_id of_mtk_match[] = { - { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, - { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, - { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, - { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, - { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data}, - { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data}, - { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data}, - { .compatible = "ralink,rt5350-eth", .data = &rt5350_data}, + { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data }, + { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, + { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data }, + { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data }, + { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data }, + { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data }, + { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data }, + { .compatible = "mediatek,mt7988-eth", .data = &mt7988_data }, + { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, {}, }; MODULE_DEVICE_TABLE(of, of_mtk_match); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 5902944ddb4f..80d17729e557 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -117,7 +117,8 @@ #define MTK_CDMP_EG_CTRL 0x404 /* GDM Exgress Control Register */ -#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) +#define MTK_GDMA_FWD_CFG(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x540 : 0x500 + (_x * 0x1000); }) #define MTK_GDMA_SPECIAL_TAG BIT(24) #define MTK_GDMA_ICS_EN BIT(22) #define MTK_GDMA_TCS_EN BIT(21) @@ -126,6 +127,11 @@ #define MTK_GDMA_TO_PDMA 0x0 #define MTK_GDMA_DROP_ALL 0x7777 +/* GDM Egress Control Register */ +#define MTK_GDMA_EG_CTRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x544 : 0x504 + (_x * 0x1000); }) +#define MTK_GDMA_XGDM_SEL BIT(31) + /* Unicast Filter MAC Address Register - Low */ #define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) @@ -389,7 +395,26 @@ #define PHY_IAC_TIMEOUT HZ #define MTK_MAC_MISC 0x1000c +#define MTK_MAC_MISC_V3 0x10010 #define MTK_MUX_TO_ESW BIT(0) +#define MISC_MDC_TURBO BIT(4) + +/* XMAC status registers */ +#define MTK_XGMAC_STS(x) (((x) == MTK_GMAC3_ID) ? 0x1001C : 0x1000C) +#define MTK_XGMAC_FORCE_LINK(x) (((x) == MTK_GMAC2_ID) ? BIT(31) : BIT(15)) +#define MTK_USXGMII_PCS_LINK BIT(8) +#define MTK_XGMAC_RX_FC BIT(5) +#define MTK_XGMAC_TX_FC BIT(4) +#define MTK_USXGMII_PCS_MODE GENMASK(3, 1) +#define MTK_XGMAC_LINK_STS BIT(0) + +/* GSW bridge registers */ +#define MTK_GSW_CFG (0x10080) +#define GSWTX_IPG_MASK GENMASK(19, 16) +#define GSWTX_IPG_SHIFT 16 +#define GSWRX_IPG_MASK GENMASK(3, 0) +#define GSWRX_IPG_SHIFT 0 +#define GSW_IPG_11 11 /* Mac control registers */ #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) @@ -647,6 +672,11 @@ enum mtk_clks_map { MTK_CLK_GP0, MTK_CLK_GP1, MTK_CLK_GP2, + MTK_CLK_GP3, + MTK_CLK_XGP1, + MTK_CLK_XGP2, + MTK_CLK_XGP3, + MTK_CLK_CRYPTO, MTK_CLK_FE, MTK_CLK_TRGPLL, MTK_CLK_SGMII_TX_250M, @@ -663,6 +693,27 @@ enum mtk_clks_map { MTK_CLK_WOCPU1, MTK_CLK_NETSYS0, MTK_CLK_NETSYS1, + MTK_CLK_ETHWARP_WOCPU2, + MTK_CLK_ETHWARP_WOCPU1, + MTK_CLK_ETHWARP_WOCPU0, + MTK_CLK_TOP_USXGMII_SBUS_0_SEL, + MTK_CLK_TOP_USXGMII_SBUS_1_SEL, + MTK_CLK_TOP_SGM_0_SEL, + MTK_CLK_TOP_SGM_1_SEL, + MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL, + MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL, + MTK_CLK_TOP_ETH_GMII_SEL, + MTK_CLK_TOP_ETH_REFCK_50M_SEL, + MTK_CLK_TOP_ETH_SYS_200M_SEL, + MTK_CLK_TOP_ETH_SYS_SEL, + MTK_CLK_TOP_ETH_XGMII_SEL, + MTK_CLK_TOP_ETH_MII_SEL, + MTK_CLK_TOP_NETSYS_SEL, + MTK_CLK_TOP_NETSYS_500M_SEL, + MTK_CLK_TOP_NETSYS_PAO_2X_SEL, + MTK_CLK_TOP_NETSYS_SYNC_250M_SEL, + MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL, + MTK_CLK_TOP_NETSYS_WARP_SEL, MTK_CLK_MAX }; @@ -716,6 +767,36 @@ enum mtk_clks_map { BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ BIT_ULL(MTK_CLK_SGMII2_CDR_FB)) +#define MT7988_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \ + BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ + BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \ + BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \ + BIT_ULL(MTK_CLK_CRYPTO) | \ + BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ + BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \ + BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \ + BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \ + BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \ + BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \ + BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \ + BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_NETSYS_WARP_SEL)) enum mtk_dev_state { MTK_HW_INIT, @@ -964,6 +1045,8 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1) +#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) + struct mtk_tx_dma_desc_info { dma_addr_t addr; u32 size; @@ -1309,6 +1392,7 @@ void mtk_stats_update_mac(struct mtk_mac *mac); void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); u32 mtk_r32(struct mtk_eth *eth, unsigned reg); +u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); -- cgit From bc758ade614576d1c1b167af0246ada8c916c804 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Jul 2023 08:39:47 +0300 Subject: net/mlx4: clean up a type issue These functions returns type bool, not pointers, so return false instead of NULL. Signed-off-by: Dan Carpenter Reviewed-by: Randy Dunlap Reviewed-by: Leon Romanovsky Reviewed-by: Tariq Toukan Link: https://lore.kernel.org/r/52d0814a-7287-4160-94b5-ac7939ac61c6@moroto.mountain Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index f1716a83a4d3..24d0c7c46878 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -294,7 +294,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, struct mlx4_promisc_qp *dqp, *tmp_dqp; if (port < 1 || port > dev->caps.num_ports) - return NULL; + return false; s_steer = &mlx4_priv(dev)->steer[port - 1]; @@ -375,7 +375,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, bool ret = false; if (port < 1 || port > dev->caps.num_ports) - return NULL; + return false; s_steer = &mlx4_priv(dev)->steer[port - 1]; -- cgit From 1ad8237e971630c66a1a6194491e0837b64d00e0 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 21 Jun 2023 12:36:55 +0300 Subject: wifi: wil6210: fix fortify warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y, I've noticed the following: In function ‘fortify_memcpy_chk’, inlined from ‘wil_rx_crypto_check_edma’ at drivers/net/wireless/ath/wil6210/txrx_edma.c:566:2: ./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 529 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where the compiler complains on: const u8 *pn; ... pn = (u8 *)&st->ext.pn_15_0; ... memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN); and: In function ‘fortify_memcpy_chk’, inlined from ‘wil_rx_crypto_check’ at drivers/net/wireless/ath/wil6210/txrx.c:684:2: ./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 529 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where the compiler complains on: const u8 *pn = (u8 *)&d->mac.pn_15_0; ... memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN); In both cases, the fortification logic interprets 'memcpy()' as 6-byte overread of 2-byte field 'pn_15_0' of 'struct wil_rx_status_extension' and 'pn_15_0' of 'struct vring_rx_mac', respectively. To silence these warnings, last two fields of the aforementioned structures are grouped using 'struct_group_attr(pn, __packed' quirk. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230621093711.80118-1-dmantipov@yandex.ru --- drivers/net/wireless/ath/wil6210/txrx.c | 2 +- drivers/net/wireless/ath/wil6210/txrx.h | 6 ++++-- drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +- drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 237cbd5c5060..f29ac6de7139 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid]; struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id]; - const u8 *pn = (u8 *)&d->mac.pn_15_0; + const u8 *pn = (u8 *)&d->mac.pn; if (!cc->key_set) { wil_err_ratelimited(wil, diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 1ae1bec1b97f..689f68d89a44 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -343,8 +343,10 @@ struct vring_rx_mac { u32 d0; u32 d1; u16 w4; - u16 pn_15_0; - u32 pn_47_16; + struct_group_attr(pn, __packed, + u16 pn_15_0; + u32 pn_47_16; + ); } __packed; /* Rx descriptor - DMA part diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 201c8c35e0c9..1ba1f21ebea2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil, s = &wil->sta[cid]; c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid]; cc = &c->key_id[key_id]; - pn = (u8 *)&st->ext.pn_15_0; + pn = (u8 *)&st->ext.pn; if (!cc->key_set) { wil_err_ratelimited(wil, diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h index c736f7413a35..ee90e225bb05 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.h +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h @@ -330,8 +330,10 @@ struct wil_rx_status_extension { u32 d0; u32 d1; __le16 seq_num; /* only lower 12 bits */ - u16 pn_15_0; - u32 pn_47_16; + struct_group_attr(pn, __packed, + u16 pn_15_0; + u32 pn_47_16; + ); } __packed; struct wil_rx_status_extended { -- cgit From f3fbda3396f39c9849ea31c19c9b188905b1691d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 20 Jun 2023 15:18:45 -0700 Subject: ice: Correctly initialize queue context values The ice_alloc_lan_q_ctx function allocates the queue context array for a given traffic class. This function uses devm_kcalloc which will zero-allocate the structure. Thus, prior to any queue being setup by ice_ena_vsi_txq, the q_ctx structure will have a q_handle of 0 and a q_teid of 0. These are potentially valid values. Modify the ice_alloc_lan_q_ctx function to initialize every member of the q_ctx array to have invalid values. Modify ice_dis_vsi_txq to ensure that it assigns q_teid to an invalid value when it assigns q_handle to the invalid value as well. This will allow other code to check whether the queue context is currently valid before operating on it. Reviewed-by: Simon Horman Reviewed-by: Daniel Machon Signed-off-by: Jacob Keller Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_common.c | 1 + drivers/net/ethernet/intel/ice/ice_sched.c | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index e16d4c83ed5f..8ff3d6d84797 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -4700,6 +4700,7 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues, break; ice_free_sched_node(pi, node); q_ctx->q_handle = ICE_INVAL_Q_HANDLE; + q_ctx->q_teid = ICE_INVAL_TEID; } mutex_unlock(&pi->sched_lock); kfree(qg_list); diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index b664d60fd037..79a8972873f1 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -569,18 +569,24 @@ ice_alloc_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 new_numqs) { struct ice_vsi_ctx *vsi_ctx; struct ice_q_ctx *q_ctx; + u16 idx; vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); if (!vsi_ctx) return -EINVAL; /* allocate LAN queue contexts */ if (!vsi_ctx->lan_q_ctx[tc]) { - vsi_ctx->lan_q_ctx[tc] = devm_kcalloc(ice_hw_to_dev(hw), - new_numqs, - sizeof(*q_ctx), - GFP_KERNEL); - if (!vsi_ctx->lan_q_ctx[tc]) + q_ctx = devm_kcalloc(ice_hw_to_dev(hw), new_numqs, + sizeof(*q_ctx), GFP_KERNEL); + if (!q_ctx) return -ENOMEM; + + for (idx = 0; idx < new_numqs; idx++) { + q_ctx[idx].q_handle = ICE_INVAL_Q_HANDLE; + q_ctx[idx].q_teid = ICE_INVAL_TEID; + } + + vsi_ctx->lan_q_ctx[tc] = q_ctx; vsi_ctx->num_lan_q_entries[tc] = new_numqs; return 0; } @@ -592,9 +598,16 @@ ice_alloc_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 new_numqs) sizeof(*q_ctx), GFP_KERNEL); if (!q_ctx) return -ENOMEM; + memcpy(q_ctx, vsi_ctx->lan_q_ctx[tc], prev_num * sizeof(*q_ctx)); devm_kfree(ice_hw_to_dev(hw), vsi_ctx->lan_q_ctx[tc]); + + for (idx = prev_num; idx < new_numqs; idx++) { + q_ctx[idx].q_handle = ICE_INVAL_Q_HANDLE; + q_ctx[idx].q_teid = ICE_INVAL_TEID; + } + vsi_ctx->lan_q_ctx[tc] = q_ctx; vsi_ctx->num_lan_q_entries[tc] = new_numqs; } -- cgit From bb52f42acef6ac317ee298d39909ce17bbaddb82 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:46 -0700 Subject: ice: Add driver support for firmware changes for LAG Add the defines, fields, and detection code for FW support of LAG for SRIOV. Also exposes some previously static functions to allow access in the lag code. Clean up code that is unused or not needed for LAG support. Also add an ordered workqueue for processing LAG events. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 5 +++ drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 3 ++ drivers/net/ethernet/intel/ice/ice_common.c | 8 ++++ drivers/net/ethernet/intel/ice/ice_lag.c | 53 +++++++++++++------------ drivers/net/ethernet/intel/ice/ice_lib.c | 2 +- drivers/net/ethernet/intel/ice/ice_lib.h | 1 + drivers/net/ethernet/intel/ice/ice_main.c | 22 ++++++++-- drivers/net/ethernet/intel/ice/ice_type.h | 2 + 8 files changed, 66 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 9109006336f0..5ac0ad12f9f1 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -200,6 +200,8 @@ enum ice_feature { ICE_F_PTP_EXTTS, ICE_F_SMA_CTRL, ICE_F_GNSS, + ICE_F_ROCE_LAG, + ICE_F_SRIOV_LAG, ICE_F_MAX }; @@ -569,6 +571,7 @@ struct ice_pf { struct mutex sw_mutex; /* lock for protecting VSI alloc flow */ struct mutex tc_mutex; /* lock to protect TC changes */ struct mutex adev_mutex; /* lock to protect aux device access */ + struct mutex lag_mutex; /* protect ice_lag struct in PF */ u32 msg_enable; struct ice_ptp ptp; struct gnss_serial *gnss_serial; @@ -639,6 +642,8 @@ struct ice_pf { struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES]; }; +extern struct workqueue_struct *ice_lag_wq; + struct ice_netdev_priv { struct ice_vsi *vsi; struct ice_repr *repr; diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 63d3e1dcbba5..1d4227b024d3 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -120,6 +120,9 @@ struct ice_aqc_list_caps_elem { #define ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE 0x0076 #define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT 0x0077 #define ICE_AQC_CAPS_NVM_MGMT 0x0080 +#define ICE_AQC_CAPS_FW_LAG_SUPPORT 0x0092 +#define ICE_AQC_BIT_ROCEV2_LAG 0x01 +#define ICE_AQC_BIT_SRIOV_LAG 0x02 u8 major_ver; u8 minor_ver; diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 8ff3d6d84797..3853ef22429f 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2241,6 +2241,14 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps, "%s: reset_restrict_support = %d\n", prefix, caps->reset_restrict_support); break; + case ICE_AQC_CAPS_FW_LAG_SUPPORT: + caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG); + ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n", + prefix, caps->roce_lag); + caps->sriov_lag = !!(number & ICE_AQC_BIT_SRIOV_LAG); + ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n", + prefix, caps->sriov_lag); + break; default: /* Not one of the recognized common capabilities */ found = false; diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 5a7753bda324..d018e68f5a6d 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -4,8 +4,12 @@ /* Link Aggregation code */ #include "ice.h" +#include "ice_lib.h" #include "ice_lag.h" +#define ICE_LAG_RES_SHARED BIT(14) +#define ICE_LAG_RES_VALID BIT(15) + /** * ice_lag_set_primary - set PF LAG state as Primary * @lag: LAG info struct @@ -225,6 +229,26 @@ static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) lag->role = ICE_LAG_NONE; } +/** + * ice_lag_init_feature_support_flag - Check for NVM support for LAG + * @pf: PF struct + */ +static void ice_lag_init_feature_support_flag(struct ice_pf *pf) +{ + struct ice_hw_common_caps *caps; + + caps = &pf->hw.dev_caps.common_cap; + if (caps->roce_lag) + ice_set_feature_support(pf, ICE_F_ROCE_LAG); + else + ice_clear_feature_support(pf, ICE_F_ROCE_LAG); + + if (caps->sriov_lag) + ice_set_feature_support(pf, ICE_F_SRIOV_LAG); + else + ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); +} + /** * ice_lag_changeupper_event - handle LAG changeupper event * @lag: LAG info struct @@ -264,26 +288,6 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) ice_display_lag_info(lag); } -/** - * ice_lag_changelower_event - handle LAG changelower event - * @lag: LAG info struct - * @ptr: opaque data pointer - * - * ptr to be cast to netdev_notifier_changelowerstate_info - */ -static void ice_lag_changelower_event(struct ice_lag *lag, void *ptr) -{ - struct net_device *netdev = netdev_notifier_info_to_dev(ptr); - - if (netdev != lag->netdev) - return; - - netdev_dbg(netdev, "bonding info\n"); - - if (!netif_is_lag_port(netdev)) - netdev_dbg(netdev, "CHANGELOWER rcvd, but netdev not in LAG. Bail\n"); -} - /** * ice_lag_event_handler - handle LAG events from netdev * @notif_blk: notifier block registered by this netdev @@ -310,9 +314,6 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, case NETDEV_CHANGEUPPER: ice_lag_changeupper_event(lag, ptr); break; - case NETDEV_CHANGELOWERSTATE: - ice_lag_changelower_event(lag, ptr); - break; case NETDEV_BONDING_INFO: ice_lag_info_event(lag, ptr); break; @@ -379,6 +380,8 @@ int ice_init_lag(struct ice_pf *pf) struct ice_vsi *vsi; int err; + ice_lag_init_feature_support_flag(pf); + pf->lag = kzalloc(sizeof(*lag), GFP_KERNEL); if (!pf->lag) return -ENOMEM; @@ -435,9 +438,7 @@ void ice_deinit_lag(struct ice_pf *pf) if (lag->pf) ice_unregister_lag_handler(lag); - dev_put(lag->upper_netdev); - - dev_put(lag->peer_netdev); + flush_workqueue(ice_lag_wq); kfree(lag); diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index a43c23c80565..077f2e91ae1a 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3970,7 +3970,7 @@ bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f) * @pf: pointer to the struct ice_pf instance * @f: feature enum to set */ -static void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f) +void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f) { if (f < 0 || f >= ICE_F_MAX) return; diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index 1628385a9672..dd53fe968ad8 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -163,6 +163,7 @@ int ice_vsi_del_vlan_zero(struct ice_vsi *vsi); bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi); u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi); bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f); +void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f); void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f); void ice_init_feature_support(struct ice_pf *pf); bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 9b36cce306b8..7f7728dadcbb 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -64,6 +64,7 @@ struct device *ice_hw_to_dev(struct ice_hw *hw) } static struct workqueue_struct *ice_wq; +struct workqueue_struct *ice_lag_wq; static const struct net_device_ops ice_netdev_safe_mode_ops; static const struct net_device_ops ice_netdev_ops; @@ -3795,6 +3796,7 @@ u16 ice_get_avail_rxq_count(struct ice_pf *pf) static void ice_deinit_pf(struct ice_pf *pf) { ice_service_task_stop(pf); + mutex_destroy(&pf->lag_mutex); mutex_destroy(&pf->adev_mutex); mutex_destroy(&pf->sw_mutex); mutex_destroy(&pf->tc_mutex); @@ -3875,6 +3877,7 @@ static int ice_init_pf(struct ice_pf *pf) mutex_init(&pf->sw_mutex); mutex_init(&pf->tc_mutex); mutex_init(&pf->adev_mutex); + mutex_init(&pf->lag_mutex); INIT_HLIST_HEAD(&pf->aq_wait_list); spin_lock_init(&pf->aq_wait_lock); @@ -5571,7 +5574,7 @@ static struct pci_driver ice_driver = { */ static int __init ice_module_init(void) { - int status; + int status = -ENOMEM; pr_info("%s\n", ice_driver_string); pr_info("%s\n", ice_copyright); @@ -5579,15 +5582,27 @@ static int __init ice_module_init(void) ice_wq = alloc_workqueue("%s", 0, 0, KBUILD_MODNAME); if (!ice_wq) { pr_err("Failed to create workqueue\n"); - return -ENOMEM; + return status; + } + + ice_lag_wq = alloc_ordered_workqueue("ice_lag_wq", 0); + if (!ice_lag_wq) { + pr_err("Failed to create LAG workqueue\n"); + goto err_dest_wq; } status = pci_register_driver(&ice_driver); if (status) { pr_err("failed to register PCI driver, err %d\n", status); - destroy_workqueue(ice_wq); + goto err_dest_lag_wq; } + return 0; + +err_dest_lag_wq: + destroy_workqueue(ice_lag_wq); +err_dest_wq: + destroy_workqueue(ice_wq); return status; } module_init(ice_module_init); @@ -5602,6 +5617,7 @@ static void __exit ice_module_exit(void) { pci_unregister_driver(&ice_driver); destroy_workqueue(ice_wq); + destroy_workqueue(ice_lag_wq); pr_info("module unloaded\n"); } module_exit(ice_module_exit); diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index df9171a1a34f..e82f38c2a940 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -277,6 +277,8 @@ struct ice_hw_common_caps { u8 dcb; u8 ieee_1588; u8 rdma; + u8 roce_lag; + u8 sriov_lag; bool nvm_update_pending_nvm; bool nvm_update_pending_orom; -- cgit From 23ccae5ce15f33001f34ed1b9e2ac312bb5e8615 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:47 -0700 Subject: ice: changes to the interface with the HW and FW for SRIOV_VF+LAG Add defines needed for interaction with the FW admin queue interface in relation to supporting LAG and SRIOV VFs interacting. Add code, or make non-static previously static functions, to access the new and changed admin queue calls for LAG. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 50 +++++++++++++++- drivers/net/ethernet/intel/ice/ice_common.c | 47 +++++++++++++++ drivers/net/ethernet/intel/ice/ice_common.h | 4 ++ drivers/net/ethernet/intel/ice/ice_sched.c | 14 ++--- drivers/net/ethernet/intel/ice/ice_sched.h | 21 +++++++ drivers/net/ethernet/intel/ice/ice_switch.c | 78 ++++++++++++++++++------- drivers/net/ethernet/intel/ice/ice_switch.h | 26 +++++++++ 7 files changed, 211 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 1d4227b024d3..c0ad34b42531 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -235,6 +235,8 @@ struct ice_aqc_set_port_params { #define ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA BIT(2) __le16 bad_frame_vsi; __le16 swid; +#define ICE_AQC_PORT_SWID_VALID BIT(15) +#define ICE_AQC_PORT_SWID_M 0xFF u8 reserved[10]; }; @@ -244,10 +246,12 @@ struct ice_aqc_set_port_params { * Allocate Resources command (indirect 0x0208) * Free Resources command (indirect 0x0209) * Get Allocated Resource Descriptors Command (indirect 0x020A) + * Share Resource command (indirect 0x020B) */ #define ICE_AQC_RES_TYPE_VSI_LIST_REP 0x03 #define ICE_AQC_RES_TYPE_VSI_LIST_PRUNE 0x04 #define ICE_AQC_RES_TYPE_RECIPE 0x05 +#define ICE_AQC_RES_TYPE_SWID 0x07 #define ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK 0x21 #define ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES 0x22 #define ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES 0x23 @@ -267,6 +271,7 @@ struct ice_aqc_set_port_params { /* Allocate Resources command (indirect 0x0208) * Free Resources command (indirect 0x0209) + * Share Resource command (indirect 0x020B) */ struct ice_aqc_alloc_free_res_cmd { __le16 num_entries; /* Number of Resource entries */ @@ -821,7 +826,11 @@ struct ice_aqc_txsched_move_grp_info_hdr { __le32 src_parent_teid; __le32 dest_parent_teid; __le16 num_elems; - __le16 reserved; + u8 mode; +#define ICE_AQC_MOVE_ELEM_MODE_SAME_PF 0x0 +#define ICE_AQC_MOVE_ELEM_MODE_GIVE_OWN 0x1 +#define ICE_AQC_MOVE_ELEM_MODE_KEEP_OWN 0x2 + u8 reserved; }; struct ice_aqc_move_elem { @@ -1926,6 +1935,42 @@ struct ice_aqc_dis_txq_item { __le16 q_id[]; } __packed; +/* Move/Reconfigure Tx queue (indirect 0x0C32) */ +struct ice_aqc_cfg_txqs { + u8 cmd_type; +#define ICE_AQC_Q_CFG_MOVE_NODE 0x1 +#define ICE_AQC_Q_CFG_TC_CHNG 0x2 +#define ICE_AQC_Q_CFG_MOVE_TC_CHNG 0x3 +#define ICE_AQC_Q_CFG_SUBSEQ_CALL BIT(2) +#define ICE_AQC_Q_CFG_FLUSH BIT(3) + u8 num_qs; + u8 port_num_chng; +#define ICE_AQC_Q_CFG_SRC_PRT_M 0x7 +#define ICE_AQC_Q_CFG_DST_PRT_S 3 +#define ICE_AQC_Q_CFG_DST_PRT_M (0x7 << ICE_AQC_Q_CFG_DST_PRT_S) + u8 time_out; +#define ICE_AQC_Q_CFG_TIMEOUT_S 2 +#define ICE_AQC_Q_CFG_TIMEOUT_M (0x1F << ICE_AQC_Q_CFG_TIMEOUT_S) + __le32 blocked_cgds; + __le32 addr_high; + __le32 addr_low; +}; + +/* Per Q struct for Move/Reconfigure Tx LAN Queues (indirect 0x0C32) */ +struct ice_aqc_cfg_txq_perq { + __le16 q_handle; + u8 tc; + u8 rsvd; + __le32 q_teid; +}; + +/* The buffer for Move/Reconfigure Tx LAN Queues (indirect 0x0C32) */ +struct ice_aqc_cfg_txqs_buf { + __le32 src_parent_teid; + __le32 dst_parent_teid; + struct ice_aqc_cfg_txq_perq queue_info[]; +}; + /* Add Tx RDMA Queue Set (indirect 0x0C33) */ struct ice_aqc_add_rdma_qset { u8 num_qset_grps; @@ -2184,6 +2229,7 @@ struct ice_aq_desc { struct ice_aqc_neigh_dev_req neigh_dev; struct ice_aqc_add_txqs add_txqs; struct ice_aqc_dis_txqs dis_txqs; + struct ice_aqc_cfg_txqs cfg_txqs; struct ice_aqc_add_rdma_qset add_rdma_qset; struct ice_aqc_add_get_update_free_vsi vsi_cmd; struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res; @@ -2266,6 +2312,7 @@ enum ice_adminq_opc { /* Alloc/Free/Get Resources */ ice_aqc_opc_alloc_res = 0x0208, ice_aqc_opc_free_res = 0x0209, + ice_aqc_opc_share_res = 0x020B, ice_aqc_opc_set_vlan_mode_parameters = 0x020C, ice_aqc_opc_get_vlan_mode_parameters = 0x020D, @@ -2359,6 +2406,7 @@ enum ice_adminq_opc { /* Tx queue handling commands/events */ ice_aqc_opc_add_txqs = 0x0C30, ice_aqc_opc_dis_txqs = 0x0C31, + ice_aqc_opc_cfg_txqs = 0x0C32, ice_aqc_opc_add_rdma_qset = 0x0C33, /* package commands */ diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 3853ef22429f..dade0a50299c 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -4229,6 +4229,53 @@ do_aq: return status; } +/** + * ice_aq_cfg_lan_txq + * @hw: pointer to the hardware structure + * @buf: buffer for command + * @buf_size: size of buffer in bytes + * @num_qs: number of queues being configured + * @oldport: origination lport + * @newport: destination lport + * @cd: pointer to command details structure or NULL + * + * Move/Configure LAN Tx queue (0x0C32) + * + * There is a better AQ command to use for moving nodes, so only coding + * this one for configuring the node. + */ +int +ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, + u16 buf_size, u16 num_qs, u8 oldport, u8 newport, + struct ice_sq_cd *cd) +{ + struct ice_aqc_cfg_txqs *cmd; + struct ice_aq_desc desc; + int status; + + cmd = &desc.params.cfg_txqs; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_txqs); + desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); + + if (!buf) + return -EINVAL; + + cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG; + cmd->num_qs = num_qs; + cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M); + cmd->port_num_chng |= (newport << ICE_AQC_Q_CFG_DST_PRT_S) & + ICE_AQC_Q_CFG_DST_PRT_M; + cmd->time_out = (5 << ICE_AQC_Q_CFG_TIMEOUT_S) & + ICE_AQC_Q_CFG_TIMEOUT_M; + cmd->blocked_cgds = 0; + + status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); + if (status) + ice_debug(hw, ICE_DBG_SCHED, "Failed to reconfigure nodes %d\n", + hw->adminq.sq_last_status); + return status; +} + /** * ice_aq_add_rdma_qsets * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 81961a7d6598..df12a9d8d28c 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -186,6 +186,10 @@ int ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle, u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size, struct ice_sq_cd *cd); +int +ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, + u16 buf_size, u16 num_qs, u8 oldport, u8 newport, + struct ice_sq_cd *cd); int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle); void ice_replay_post(struct ice_hw *hw); void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf); diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 79a8972873f1..f4677704b95e 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -447,7 +447,7 @@ ice_aq_cfg_sched_elems(struct ice_hw *hw, u16 elems_req, * * Move scheduling elements (0x0408) */ -static int +int ice_aq_move_sched_elems(struct ice_hw *hw, u16 grps_req, struct ice_aqc_move_elem *buf, u16 buf_size, u16 *grps_movd, struct ice_sq_cd *cd) @@ -526,7 +526,7 @@ ice_aq_query_sched_res(struct ice_hw *hw, u16 buf_size, * * This function suspends or resumes HW nodes */ -static int +int ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, bool suspend) { @@ -1057,7 +1057,7 @@ ice_sched_add_nodes_to_hw_layer(struct ice_port_info *pi, * * This function add nodes to a given layer. */ -static int +int ice_sched_add_nodes_to_layer(struct ice_port_info *pi, struct ice_sched_node *tc_node, struct ice_sched_node *parent, u8 layer, @@ -1132,7 +1132,7 @@ static u8 ice_sched_get_qgrp_layer(struct ice_hw *hw) * * This function returns the current VSI layer number */ -static u8 ice_sched_get_vsi_layer(struct ice_hw *hw) +u8 ice_sched_get_vsi_layer(struct ice_hw *hw) { /* Num Layers VSI layer * 9 6 @@ -1155,7 +1155,7 @@ static u8 ice_sched_get_vsi_layer(struct ice_hw *hw) * * This function returns the current aggregator layer number */ -static u8 ice_sched_get_agg_layer(struct ice_hw *hw) +u8 ice_sched_get_agg_layer(struct ice_hw *hw) { /* Num Layers aggregator layer * 9 4 @@ -1590,7 +1590,7 @@ ice_sched_get_vsi_node(struct ice_port_info *pi, struct ice_sched_node *tc_node, * This function retrieves an aggregator node for a given aggregator ID from * a given TC branch */ -static struct ice_sched_node * +struct ice_sched_node * ice_sched_get_agg_node(struct ice_port_info *pi, struct ice_sched_node *tc_node, u32 agg_id) { @@ -2152,7 +2152,7 @@ ice_get_agg_info(struct ice_hw *hw, u32 agg_id) * This function walks through the aggregator subtree to find a free parent * node */ -static struct ice_sched_node * +struct ice_sched_node * ice_sched_get_free_vsi_parent(struct ice_hw *hw, struct ice_sched_node *node, u16 *num_nodes) { diff --git a/drivers/net/ethernet/intel/ice/ice_sched.h b/drivers/net/ethernet/intel/ice/ice_sched.h index 9c100747445a..8bd26353d76a 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.h +++ b/drivers/net/ethernet/intel/ice/ice_sched.h @@ -146,8 +146,29 @@ ice_sched_set_node_bw_lmt_per_tc(struct ice_port_info *pi, u32 id, enum ice_agg_type agg_type, u8 tc, enum ice_rl_type rl_type, u32 bw); int ice_cfg_rl_burst_size(struct ice_hw *hw, u32 bytes); +int +ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, + bool suspend); +struct ice_sched_node * +ice_sched_get_agg_node(struct ice_port_info *pi, struct ice_sched_node *tc_node, + u32 agg_id); +u8 ice_sched_get_agg_layer(struct ice_hw *hw); +u8 ice_sched_get_vsi_layer(struct ice_hw *hw); +struct ice_sched_node * +ice_sched_get_free_vsi_parent(struct ice_hw *hw, struct ice_sched_node *node, + u16 *num_nodes); +int +ice_sched_add_nodes_to_layer(struct ice_port_info *pi, + struct ice_sched_node *tc_node, + struct ice_sched_node *parent, u8 layer, + u16 num_nodes, u32 *first_node_teid, + u16 *num_nodes_added); void ice_sched_replay_agg_vsi_preinit(struct ice_hw *hw); void ice_sched_replay_agg(struct ice_hw *hw); +int +ice_aq_move_sched_elems(struct ice_hw *hw, u16 grps_req, + struct ice_aqc_move_elem *buf, u16 buf_size, + u16 *grps_movd, struct ice_sq_cd *cd); int ice_replay_vsi_agg(struct ice_hw *hw, u16 vsi_handle); int ice_sched_replay_q_bw(struct ice_port_info *pi, struct ice_q_ctx *q_ctx); #endif /* _ICE_SCHED_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 813fef5fd748..8c332d24c7c5 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -20,10 +20,10 @@ * byte 0 = 0x2: to identify it as locally administered DA MAC * byte 6 = 0x2: to identify it as locally administered SA MAC * byte 12 = 0x81 & byte 13 = 0x00: - * In case of VLAN filter first two bytes defines ether type (0x8100) - * and remaining two bytes are placeholder for programming a given VLAN ID - * In case of Ether type filter it is treated as header without VLAN tag - * and byte 12 and 13 is used to program a given Ether type instead + * In case of VLAN filter first two bytes defines ether type (0x8100) + * and remaining two bytes are placeholder for programming a given VLAN ID + * In case of Ether type filter it is treated as header without VLAN tag + * and byte 12 and 13 is used to program a given Ether type instead */ #define DUMMY_ETH_HDR_LEN 16 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, @@ -1369,14 +1369,6 @@ static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = { ICE_PKT_PROFILE(tcp, 0), }; -#define ICE_SW_RULE_RX_TX_HDR_SIZE(s, l) struct_size((s), hdr_data, (l)) -#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s) \ - ICE_SW_RULE_RX_TX_HDR_SIZE((s), DUMMY_ETH_HDR_LEN) -#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s) \ - ICE_SW_RULE_RX_TX_HDR_SIZE((s), 0) -#define ICE_SW_RULE_LG_ACT_SIZE(s, n) struct_size((s), act, (n)) -#define ICE_SW_RULE_VSI_LIST_SIZE(s, n) struct_size((s), vsi, (n)) - /* this is a recipe to profile association bitmap */ static DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES], ICE_MAX_NUM_PROFILES); @@ -1841,8 +1833,13 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, lkup_type == ICE_SW_LKUP_DFLT) { sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP); } else if (lkup_type == ICE_SW_LKUP_VLAN) { - sw_buf->res_type = - cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); + if (opc == ice_aqc_opc_alloc_res) + sw_buf->res_type = + cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE | + ICE_AQC_RES_TYPE_FLAG_SHARED); + else + sw_buf->res_type = + cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); } else { status = -EINVAL; goto ice_aq_alloc_free_vsi_list_exit; @@ -1910,7 +1907,7 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, * * Add(0x0290) */ -static int +int ice_aq_add_recipe(struct ice_hw *hw, struct ice_aqc_recipe_data_elem *s_recipe_list, u16 num_recipes, struct ice_sq_cd *cd) @@ -1947,7 +1944,7 @@ ice_aq_add_recipe(struct ice_hw *hw, * The caller must supply enough space in s_recipe_list to hold all possible * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES. */ -static int +int ice_aq_get_recipe(struct ice_hw *hw, struct ice_aqc_recipe_data_elem *s_recipe_list, u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd) @@ -2040,7 +2037,7 @@ error_out: * @cd: pointer to command details structure or NULL * Recipe to profile association (0x0291) */ -static int +int ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, struct ice_sq_cd *cd) { @@ -2066,7 +2063,7 @@ ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, * @cd: pointer to command details structure or NULL * Associate profile ID with given recipe (0x0293) */ -static int +int ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, struct ice_sq_cd *cd) { @@ -2090,7 +2087,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, * @hw: pointer to the hardware structure * @rid: recipe ID returned as response to AQ call */ -static int ice_alloc_recipe(struct ice_hw *hw, u16 *rid) +int ice_alloc_recipe(struct ice_hw *hw, u16 *rid) { struct ice_aqc_alloc_free_res_elem *sw_buf; u16 buf_len; @@ -3122,7 +3119,7 @@ ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info) * handle element. This can be extended further to search VSI list with more * than 1 vsi_count. Returns pointer to VSI list entry if found. */ -static struct ice_vsi_list_map_info * +struct ice_vsi_list_map_info * ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, u16 *vsi_list_id) { @@ -3133,7 +3130,7 @@ ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, list_head = &sw->recp_list[recp_id].filt_rules; list_for_each_entry(list_itr, list_head, list_entry) { - if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) { + if (list_itr->vsi_list_info) { map_info = list_itr->vsi_list_info; if (test_bit(vsi_handle, map_info->vsi_map)) { *vsi_list_id = map_info->vsi_list_id; @@ -4544,6 +4541,45 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, .offs = {__VA_ARGS__}, \ } +/** + * ice_share_res - set a resource as shared or dedicated + * @hw: hw struct of original owner of resource + * @type: resource type + * @shared: is the resource being set to shared + * @res_id: resource id (descriptor) + */ +int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id) +{ + struct ice_aqc_alloc_free_res_elem *buf; + u16 buf_len; + int status; + + buf_len = struct_size(buf, elem, 1); + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf->num_elems = cpu_to_le16(1); + if (shared) + buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & + ICE_AQC_RES_TYPE_M) | + ICE_AQC_RES_TYPE_FLAG_SHARED); + else + buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & + ICE_AQC_RES_TYPE_M) & + ~ICE_AQC_RES_TYPE_FLAG_SHARED); + + buf->elem[0].e.sw_resp = cpu_to_le16(res_id); + status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, + ice_aqc_opc_share_res, NULL); + if (status) + ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n", + type, res_id, shared ? "SHARED" : "DEDICATED"); + + kfree(buf); + return status; +} + /* This is mapping table entry that maps every word within a given protocol * structure to the real byte offset as per the specification of that * protocol header. diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 10f5a0ae199e..51cd14952cd1 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -22,6 +22,14 @@ #define ICE_PROFID_IPV6_GTPU_TEID 46 #define ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER 70 +#define ICE_SW_RULE_VSI_LIST_SIZE(s, n) struct_size((s), vsi, (n)) +#define ICE_SW_RULE_RX_TX_HDR_SIZE(s, l) struct_size((s), hdr_data, (l)) +#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s) \ + ICE_SW_RULE_RX_TX_HDR_SIZE((s), DUMMY_ETH_HDR_LEN) +#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s) \ + ICE_SW_RULE_RX_TX_HDR_SIZE((s), 0) +#define ICE_SW_RULE_LG_ACT_SIZE(s, n) struct_size((s), act, (n)) + /* VSI context structure for add/get/update/free operations */ struct ice_vsi_ctx { u16 vsi_num; @@ -345,6 +353,7 @@ ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, int ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, u16 counter_id); +int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id); /* Switch/bridge related commands */ void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup); @@ -401,4 +410,21 @@ int ice_update_recipe_lkup_idx(struct ice_hw *hw, struct ice_update_recipe_lkup_idx_params *params); void ice_change_proto_id_to_dvm(void); +struct ice_vsi_list_map_info * +ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, + u16 *vsi_list_id); +int ice_alloc_recipe(struct ice_hw *hw, u16 *rid); +int ice_aq_get_recipe(struct ice_hw *hw, + struct ice_aqc_recipe_data_elem *s_recipe_list, + u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd); +int ice_aq_add_recipe(struct ice_hw *hw, + struct ice_aqc_recipe_data_elem *s_recipe_list, + u16 num_recipes, struct ice_sq_cd *cd); +int +ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, + struct ice_sq_cd *cd); +int +ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, + struct ice_sq_cd *cd); + #endif /* _ICE_SWITCH_H_ */ -- cgit From 41ccedf5ca8fcd9fc97f977887625c035d9b15df Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:48 -0700 Subject: ice: implement lag netdev event handler The event handler for LAG will create a work item to place on the ordered workqueue to be processed. Add in defines for training packets and new recipes to be used by the switching block of the HW for LAG packet steering. Update the ice_lag struct to reflect the new processing methodology. Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 124 +++++++++++++++++++++++++++---- drivers/net/ethernet/intel/ice/ice_lag.h | 30 +++++++- 2 files changed, 140 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index d018e68f5a6d..5725772cf8f4 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -56,11 +56,10 @@ static void ice_lag_set_backup(struct ice_lag *lag) */ static void ice_display_lag_info(struct ice_lag *lag) { - const char *name, *peer, *upper, *role, *bonded, *primary; + const char *name, *upper, *role, *bonded, *primary; struct device *dev = &lag->pf->pdev->dev; name = lag->netdev ? netdev_name(lag->netdev) : "unset"; - peer = lag->peer_netdev ? netdev_name(lag->peer_netdev) : "unset"; upper = lag->upper_netdev ? netdev_name(lag->upper_netdev) : "unset"; primary = lag->primary ? "TRUE" : "FALSE"; bonded = lag->bonded ? "BONDED" : "UNBONDED"; @@ -82,8 +81,8 @@ static void ice_display_lag_info(struct ice_lag *lag) role = "ERROR"; } - dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, primary:%s\n", name, - bonded, peer, upper, role, primary); + dev_dbg(dev, "%s %s, upper:%s, role:%s, primary:%s\n", name, bonded, + upper, role, primary); } /** @@ -198,7 +197,6 @@ ice_lag_unlink(struct ice_lag *lag, lag->upper_netdev = NULL; } - lag->peer_netdev = NULL; ice_set_rdma_cap(pf); lag->bonded = false; lag->role = ICE_LAG_NONE; @@ -288,6 +286,59 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) ice_display_lag_info(lag); } +/** + * ice_lag_process_event - process a task assigned to the lag_wq + * @work: pointer to work_struct + */ +static void ice_lag_process_event(struct work_struct *work) +{ + struct netdev_notifier_changeupper_info *info; + struct ice_lag_work *lag_work; + struct net_device *netdev; + struct list_head *tmp, *n; + struct ice_pf *pf; + + lag_work = container_of(work, struct ice_lag_work, lag_task); + pf = lag_work->lag->pf; + + mutex_lock(&pf->lag_mutex); + lag_work->lag->netdev_head = &lag_work->netdev_list.node; + + switch (lag_work->event) { + case NETDEV_CHANGEUPPER: + info = &lag_work->info.changeupper_info; + ice_lag_changeupper_event(lag_work->lag, info); + break; + case NETDEV_BONDING_INFO: + ice_lag_info_event(lag_work->lag, &lag_work->info.bonding_info); + break; + case NETDEV_UNREGISTER: + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { + netdev = lag_work->info.bonding_info.info.dev; + if ((netdev == lag_work->lag->netdev || + lag_work->lag->primary) && lag_work->lag->bonded) + ice_lag_unregister(lag_work->lag, netdev); + } + break; + default: + break; + } + + /* cleanup resources allocated for this work item */ + list_for_each_safe(tmp, n, &lag_work->netdev_list.node) { + struct ice_lag_netdev_list *entry; + + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + list_del(&entry->node); + kfree(entry); + } + lag_work->lag->netdev_head = NULL; + + mutex_unlock(&pf->lag_mutex); + + kfree(lag_work); +} + /** * ice_lag_event_handler - handle LAG events from netdev * @notif_blk: notifier block registered by this netdev @@ -299,31 +350,79 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, void *ptr) { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); + struct net_device *upper_netdev; + struct ice_lag_work *lag_work; struct ice_lag *lag; - lag = container_of(notif_blk, struct ice_lag, notif_block); + if (!netif_is_ice(netdev)) + return NOTIFY_DONE; + + if (event != NETDEV_CHANGEUPPER && event != NETDEV_BONDING_INFO && + event != NETDEV_UNREGISTER) + return NOTIFY_DONE; + if (!(netdev->priv_flags & IFF_BONDING)) + return NOTIFY_DONE; + + lag = container_of(notif_blk, struct ice_lag, notif_block); if (!lag->netdev) return NOTIFY_DONE; - /* Check that the netdev is in the working namespace */ if (!net_eq(dev_net(netdev), &init_net)) return NOTIFY_DONE; + /* This memory will be freed at the end of ice_lag_process_event */ + lag_work = kzalloc(sizeof(*lag_work), GFP_KERNEL); + if (!lag_work) + return -ENOMEM; + + lag_work->event_netdev = netdev; + lag_work->lag = lag; + lag_work->event = event; + if (event == NETDEV_CHANGEUPPER) { + struct netdev_notifier_changeupper_info *info; + + info = ptr; + upper_netdev = info->upper_dev; + } else { + upper_netdev = netdev_master_upper_dev_get(netdev); + } + + INIT_LIST_HEAD(&lag_work->netdev_list.node); + if (upper_netdev) { + struct ice_lag_netdev_list *nd_list; + struct net_device *tmp_nd; + + rcu_read_lock(); + for_each_netdev_in_bond_rcu(upper_netdev, tmp_nd) { + nd_list = kzalloc(sizeof(*nd_list), GFP_KERNEL); + if (!nd_list) + break; + + nd_list->netdev = tmp_nd; + list_add(&nd_list->node, &lag_work->netdev_list.node); + } + rcu_read_unlock(); + } + switch (event) { case NETDEV_CHANGEUPPER: - ice_lag_changeupper_event(lag, ptr); + lag_work->info.changeupper_info = + *((struct netdev_notifier_changeupper_info *)ptr); break; case NETDEV_BONDING_INFO: - ice_lag_info_event(lag, ptr); - break; - case NETDEV_UNREGISTER: - ice_lag_unregister(lag, netdev); + lag_work->info.bonding_info = + *((struct netdev_notifier_bonding_info *)ptr); break; default: + lag_work->info.notifier_info = + *((struct netdev_notifier_info *)ptr); break; } + INIT_WORK(&lag_work->lag_task, ice_lag_process_event); + queue_work(ice_lag_wq, &lag_work->lag_task); + return NOTIFY_DONE; } @@ -398,7 +497,6 @@ int ice_init_lag(struct ice_pf *pf) lag->netdev = vsi->netdev; lag->role = ICE_LAG_NONE; lag->bonded = false; - lag->peer_netdev = NULL; lag->upper_netdev = NULL; lag->notif_block.notifier_call = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h index 2c373676c42f..a4314a46c82c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.h +++ b/drivers/net/ethernet/intel/ice/ice_lag.h @@ -14,20 +14,48 @@ enum ice_lag_role { ICE_LAG_UNSET }; +#define ICE_LAG_INVALID_PORT 0xFF + struct ice_pf; +struct ice_vf; + +struct ice_lag_netdev_list { + struct list_head node; + struct net_device *netdev; +}; /* LAG info struct */ struct ice_lag { struct ice_pf *pf; /* backlink to PF struct */ struct net_device *netdev; /* this PF's netdev */ - struct net_device *peer_netdev; struct net_device *upper_netdev; /* upper bonding netdev */ + struct list_head *netdev_head; struct notifier_block notif_block; + s32 bond_mode; + u16 bond_swid; /* swid for primary interface */ + u8 active_port; /* lport value for the current active port */ u8 bonded:1; /* currently bonded */ u8 primary:1; /* this is primary */ + u16 pf_recipe; + u16 pf_rule_id; + u16 cp_rule_idx; u8 role; }; +/* LAG workqueue struct */ +struct ice_lag_work { + struct work_struct lag_task; + struct ice_lag_netdev_list netdev_list; + struct ice_lag *lag; + unsigned long event; + struct net_device *event_netdev; + union { + struct netdev_notifier_changeupper_info changeupper_info; + struct netdev_notifier_bonding_info bonding_info; + struct netdev_notifier_info notifier_info; + } info; +}; + int ice_init_lag(struct ice_pf *pf); void ice_deinit_lag(struct ice_pf *pf); #endif /* _ICE_LAG_H_ */ -- cgit From ec5a6c5f79ed7ff3e26418dce330d2a583e57fb0 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:49 -0700 Subject: ice: process events created by lag netdev event handler Add in the function framework for the processing of LAG events. Also add in helper function to perform common tasks. Add the basis of the process of linking a lower netdev to an upper netdev. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 559 ++++++++++++++++++++++---- drivers/net/ethernet/intel/ice/ice_lag.h | 1 + drivers/net/ethernet/intel/ice/ice_switch.c | 10 +- drivers/net/ethernet/intel/ice/ice_switch.h | 3 + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 2 + 5 files changed, 501 insertions(+), 74 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 5725772cf8f4..ac4deb5af118 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -10,6 +10,13 @@ #define ICE_LAG_RES_SHARED BIT(14) #define ICE_LAG_RES_VALID BIT(15) +#define ICE_RECIPE_LEN 64 +static const u8 ice_dflt_vsi_rcp[ICE_RECIPE_LEN] = { + 0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x85, 0, 0x01, 0, 0, 0, 0xff, 0xff, 0x08, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + /** * ice_lag_set_primary - set PF LAG state as Primary * @lag: LAG info struct @@ -50,6 +57,147 @@ static void ice_lag_set_backup(struct ice_lag *lag) lag->role = ICE_LAG_BACKUP; } +/** + * ice_netdev_to_lag - return pointer to associated lag struct from netdev + * @netdev: pointer to net_device struct to query + */ +static struct ice_lag *ice_netdev_to_lag(struct net_device *netdev) +{ + struct ice_netdev_priv *np; + struct ice_vsi *vsi; + + if (!netif_is_ice(netdev)) + return NULL; + + np = netdev_priv(netdev); + if (!np) + return NULL; + + vsi = np->vsi; + if (!vsi) + return NULL; + + return vsi->back->lag; +} + +/** + * ice_lag_find_primary - returns pointer to primary interfaces lag struct + * @lag: local interfaces lag struct + */ +static struct ice_lag *ice_lag_find_primary(struct ice_lag *lag) +{ + struct ice_lag *primary_lag = NULL; + struct list_head *tmp; + + list_for_each(tmp, lag->netdev_head) { + struct ice_lag_netdev_list *entry; + struct ice_lag *tmp_lag; + + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + tmp_lag = ice_netdev_to_lag(entry->netdev); + if (tmp_lag && tmp_lag->primary) { + primary_lag = tmp_lag; + break; + } + } + + return primary_lag; +} + +/** + * ice_lag_cfg_dflt_fltr - Add/Remove default VSI rule for LAG + * @lag: lag struct for local interface + * @add: boolean on whether we are adding filters + */ +static int +ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) +{ + struct ice_sw_rule_lkup_rx_tx *s_rule; + u16 s_rule_sz, vsi_num; + struct ice_hw *hw; + u32 act, opc; + u8 *eth_hdr; + int err; + + hw = &lag->pf->hw; + vsi_num = ice_get_hw_vsi_num(hw, 0); + + s_rule_sz = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule); + s_rule = kzalloc(s_rule_sz, GFP_KERNEL); + if (!s_rule) { + dev_err(ice_pf_to_dev(lag->pf), "error allocating rule for LAG default VSI\n"); + return -ENOMEM; + } + + if (add) { + eth_hdr = s_rule->hdr_data; + ice_fill_eth_hdr(eth_hdr); + + act = (vsi_num << ICE_SINGLE_ACT_VSI_ID_S) & + ICE_SINGLE_ACT_VSI_ID_M; + act |= ICE_SINGLE_ACT_VSI_FORWARDING | + ICE_SINGLE_ACT_VALID_BIT | ICE_SINGLE_ACT_LAN_ENABLE; + + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); + s_rule->recipe_id = cpu_to_le16(lag->pf_recipe); + s_rule->src = cpu_to_le16(hw->port_info->lport); + s_rule->act = cpu_to_le32(act); + s_rule->hdr_len = cpu_to_le16(DUMMY_ETH_HDR_LEN); + opc = ice_aqc_opc_add_sw_rules; + } else { + s_rule->index = cpu_to_le16(lag->pf_rule_id); + opc = ice_aqc_opc_remove_sw_rules; + } + + err = ice_aq_sw_rules(&lag->pf->hw, s_rule, s_rule_sz, 1, opc, NULL); + if (err) + goto dflt_fltr_free; + + if (add) + lag->pf_rule_id = le16_to_cpu(s_rule->index); + else + lag->pf_rule_id = 0; + +dflt_fltr_free: + kfree(s_rule); + return err; +} + +/** + * ice_lag_cfg_pf_fltrs - set filters up for new active port + * @lag: local interfaces lag struct + * @ptr: opaque data containing notifier event + */ +static void +ice_lag_cfg_pf_fltrs(struct ice_lag *lag, void *ptr) +{ + struct netdev_notifier_bonding_info *info; + struct netdev_bonding_info *bonding_info; + struct net_device *event_netdev; + struct device *dev; + + event_netdev = netdev_notifier_info_to_dev(ptr); + /* not for this netdev */ + if (event_netdev != lag->netdev) + return; + + info = (struct netdev_notifier_bonding_info *)ptr; + bonding_info = &info->bonding_info; + dev = ice_pf_to_dev(lag->pf); + + /* interface not active - remove old default VSI rule */ + if (bonding_info->slave.state && lag->pf_rule_id) { + if (ice_lag_cfg_dflt_fltr(lag, false)) + dev_err(dev, "Error removing old default VSI filter\n"); + return; + } + + /* interface becoming active - add new default VSI rule */ + if (!bonding_info->slave.state && !lag->pf_rule_id) + if (ice_lag_cfg_dflt_fltr(lag, true)) + dev_err(dev, "Error adding new default VSI filter\n"); +} + /** * ice_display_lag_info - print LAG info * @lag: LAG info struct @@ -85,6 +233,83 @@ static void ice_display_lag_info(struct ice_lag *lag) upper, role, primary); } +/** + * ice_lag_move_vf_node_tc - move scheduling nodes for one VF on one TC + * @lag: lag info struct + * @oldport: lport of previous nodes location + * @newport: lport of destination nodes location + * @vsi_num: array index of VSI in PF space + * @tc: traffic class to move + */ +static void +ice_lag_move_vf_node_tc(struct ice_lag *lag, u8 oldport, u8 newport, + u16 vsi_num, u8 tc) +{ +} + +/** + * ice_lag_move_single_vf_nodes - Move Tx scheduling nodes for single VF + * @lag: primary interface LAG struct + * @oldport: lport of previous interface + * @newport: lport of destination interface + * @vsi_num: SW index of VF's VSI + */ +static void +ice_lag_move_single_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport, + u16 vsi_num) +{ + u8 tc; + + ice_for_each_traffic_class(tc) + ice_lag_move_vf_node_tc(lag, oldport, newport, vsi_num, tc); +} + +/** + * ice_lag_move_new_vf_nodes - Move Tx scheduling nodes for a VF if required + * @vf: the VF to move Tx nodes for + * + * Called just after configuring new VF queues. Check whether the VF Tx + * scheduling nodes need to be updated to fail over to the active port. If so, + * move them now. + */ +void ice_lag_move_new_vf_nodes(struct ice_vf *vf) +{ +} + +/** + * ice_lag_move_vf_nodes - move Tx scheduling nodes for all VFs to new port + * @lag: lag info struct + * @oldport: lport of previous interface + * @newport: lport of destination interface + */ +static void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport) +{ + struct ice_pf *pf; + int i; + + if (!lag->primary) + return; + + pf = lag->pf; + ice_for_each_vsi(pf, i) + if (pf->vsi[i] && (pf->vsi[i]->type == ICE_VSI_VF || + pf->vsi[i]->type == ICE_VSI_SWITCHDEV_CTRL)) + ice_lag_move_single_vf_nodes(lag, oldport, newport, i); +} + +#define ICE_LAG_SRIOV_CP_RECIPE 10 +#define ICE_LAG_SRIOV_TRAIN_PKT_LEN 16 + +/** + * ice_lag_cfg_cp_fltr - configure filter for control packets + * @lag: local interface's lag struct + * @add: add or remove rule + */ +static void +ice_lag_cfg_cp_fltr(struct ice_lag *lag, bool add) +{ +} + /** * ice_lag_info_event - handle NETDEV_BONDING_INFO event * @lag: LAG info struct @@ -126,105 +351,168 @@ lag_out: ice_display_lag_info(lag); } +/** + * ice_lag_reclaim_vf_tc - move scheduling nodes back to primary interface + * @lag: primary interface lag struct + * @src_hw: HW struct current node location + * @vsi_num: VSI index in PF space + * @tc: traffic class to move + */ +static void +ice_lag_reclaim_vf_tc(struct ice_lag *lag, struct ice_hw *src_hw, u16 vsi_num, + u8 tc) +{ +} + +/** + * ice_lag_reclaim_vf_nodes - When interface leaving bond primary reclaims nodes + * @lag: primary interface lag struct + * @src_hw: HW struct for current node location + */ +static void +ice_lag_reclaim_vf_nodes(struct ice_lag *lag, struct ice_hw *src_hw) +{ + struct ice_pf *pf; + int i, tc; + + if (!lag->primary || !src_hw) + return; + + pf = lag->pf; + ice_for_each_vsi(pf, i) + if (pf->vsi[i] && (pf->vsi[i]->type == ICE_VSI_VF || + pf->vsi[i]->type == ICE_VSI_SWITCHDEV_CTRL)) + ice_for_each_traffic_class(tc) + ice_lag_reclaim_vf_tc(lag, src_hw, i, tc); +} + /** * ice_lag_link - handle LAG link event * @lag: LAG info struct - * @info: info from the netdev notifier */ -static void -ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info) +static void ice_lag_link(struct ice_lag *lag) { - struct net_device *netdev_tmp, *upper = info->upper_dev; struct ice_pf *pf = lag->pf; - int peers = 0; if (lag->bonded) dev_warn(ice_pf_to_dev(pf), "%s Already part of a bond\n", netdev_name(lag->netdev)); - rcu_read_lock(); - for_each_netdev_in_bond_rcu(upper, netdev_tmp) - peers++; - rcu_read_unlock(); - - if (lag->upper_netdev != upper) { - dev_hold(upper); - lag->upper_netdev = upper; - } - - ice_clear_rdma_cap(pf); - lag->bonded = true; lag->role = ICE_LAG_UNSET; - - /* if this is the first element in an LAG mark as primary */ - lag->primary = !!(peers == 1); } /** * ice_lag_unlink - handle unlink event * @lag: LAG info struct - * @info: info from netdev notification */ -static void -ice_lag_unlink(struct ice_lag *lag, - struct netdev_notifier_changeupper_info *info) +static void ice_lag_unlink(struct ice_lag *lag) { - struct net_device *netdev_tmp, *upper = info->upper_dev; + u8 pri_port, act_port, loc_port; struct ice_pf *pf = lag->pf; - bool found = false; if (!lag->bonded) { netdev_dbg(lag->netdev, "bonding unlink event on non-LAG netdev\n"); return; } - /* determine if we are in the new LAG config or not */ - rcu_read_lock(); - for_each_netdev_in_bond_rcu(upper, netdev_tmp) { - if (netdev_tmp == lag->netdev) { - found = true; - break; + if (lag->primary) { + act_port = lag->active_port; + pri_port = lag->pf->hw.port_info->lport; + if (act_port != pri_port && act_port != ICE_LAG_INVALID_PORT) + ice_lag_move_vf_nodes(lag, act_port, pri_port); + lag->primary = false; + lag->active_port = ICE_LAG_INVALID_PORT; + } else { + struct ice_lag *primary_lag; + + primary_lag = ice_lag_find_primary(lag); + if (primary_lag) { + act_port = primary_lag->active_port; + pri_port = primary_lag->pf->hw.port_info->lport; + loc_port = pf->hw.port_info->lport; + if (act_port == loc_port && + act_port != ICE_LAG_INVALID_PORT) { + ice_lag_reclaim_vf_nodes(primary_lag, + &lag->pf->hw); + primary_lag->active_port = ICE_LAG_INVALID_PORT; + } } } - rcu_read_unlock(); - - if (found) - return; - - if (lag->upper_netdev) { - dev_put(lag->upper_netdev); - lag->upper_netdev = NULL; - } - ice_set_rdma_cap(pf); lag->bonded = false; lag->role = ICE_LAG_NONE; + lag->upper_netdev = NULL; } /** - * ice_lag_unregister - handle netdev unregister events - * @lag: LAG info struct - * @netdev: netdev reporting the event + * ice_lag_link_unlink - helper function to call lag_link/unlink + * @lag: lag info struct + * @ptr: opaque pointer data */ -static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) +static void ice_lag_link_unlink(struct ice_lag *lag, void *ptr) { - struct ice_pf *pf = lag->pf; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info = ptr; - /* check to see if this event is for this netdev - * check that we are in an aggregate - */ - if (netdev != lag->netdev || !lag->bonded) + if (netdev != lag->netdev) return; - if (lag->upper_netdev) { - dev_put(lag->upper_netdev); - lag->upper_netdev = NULL; - ice_set_rdma_cap(pf); - } - /* perform some cleanup in case we come back */ - lag->bonded = false; - lag->role = ICE_LAG_NONE; + if (info->linking) + ice_lag_link(lag); + else + ice_lag_unlink(lag); +} + +/** + * ice_lag_set_swid - set the SWID on secondary interface + * @primary_swid: primary interface's SWID + * @local_lag: local interfaces LAG struct + * @link: Is this a linking activity + * + * If link is false, then primary_swid should be expected to not be valid + */ +static void +ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, + bool link) +{ +} + +/** + * ice_lag_primary_swid - set/clear the SHARED attrib of primary's SWID + * @lag: primary interfaces lag struct + * @link: is this a linking activity + * + * Implement setting primary SWID as shared using 0x020B + */ +static void ice_lag_primary_swid(struct ice_lag *lag, bool link) +{ + struct ice_hw *hw; + u16 swid; + + hw = &lag->pf->hw; + swid = hw->port_info->sw_id; + + if (ice_share_res(hw, ICE_AQC_RES_TYPE_SWID, link, swid)) + dev_warn(ice_pf_to_dev(lag->pf), "Failure to set primary interface shared status\n"); +} + +/** + * ice_lag_add_prune_list - Adds event_pf's VSI to primary's prune list + * @lag: lag info struct + * @event_pf: PF struct for VSI we are adding to primary's prune list + */ +static void ice_lag_add_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) +{ +} + +/** + * ice_lag_del_prune_list - Remove secondary's vsi from primary's prune list + * @lag: primary interface's ice_lag struct + * @event_pf: PF struct for unlinking interface + */ +static void ice_lag_del_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) +{ } /** @@ -257,6 +545,7 @@ static void ice_lag_init_feature_support_flag(struct ice_pf *pf) static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) { struct netdev_notifier_changeupper_info *info; + struct ice_lag *primary_lag; struct net_device *netdev; info = ptr; @@ -266,24 +555,107 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) if (netdev != lag->netdev) return; - if (!info->upper_dev) { - netdev_dbg(netdev, "changeupper rcvd, but no upper defined\n"); - return; + primary_lag = ice_lag_find_primary(lag); + if (info->linking) { + lag->upper_netdev = info->upper_dev; + /* If there is not already a primary interface in the LAG, + * then mark this one as primary. + */ + if (!primary_lag) { + lag->primary = true; + /* Configure primary's SWID to be shared */ + ice_lag_primary_swid(lag, true); + primary_lag = lag; + } else { + u16 swid; + + swid = primary_lag->pf->hw.port_info->sw_id; + ice_lag_set_swid(swid, lag, true); + ice_lag_add_prune_list(primary_lag, lag->pf); + } + /* add filter for primary control packets */ + ice_lag_cfg_cp_fltr(lag, true); + } else { + if (!primary_lag && lag->primary) + primary_lag = lag; + + if (primary_lag) { + if (!lag->primary) { + ice_lag_set_swid(0, lag, false); + } else { + ice_lag_primary_swid(lag, false); + ice_lag_del_prune_list(primary_lag, lag->pf); + } + ice_lag_cfg_cp_fltr(lag, false); + } } +} + +/** + * ice_lag_monitor_link - monitor interfaces entering/leaving the aggregate + * @lag: lag info struct + * @ptr: opaque data containing notifier event + * + * This function only operates after a primary has been set. + */ +static void ice_lag_monitor_link(struct ice_lag *lag, void *ptr) +{ +} + +/** + * ice_lag_monitor_active - main PF keep track of which port is active + * @lag: lag info struct + * @ptr: opaque data containing notifier event + * + * This function is for the primary PF to monitor changes in which port is + * active and handle changes for SRIOV VF functionality + */ +static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) +{ +} + +/** + * ice_lag_chk_comp - evaluate bonded interface for feature support + * @lag: lag info struct + * @ptr: opaque data for netdev event info + */ +static bool +ice_lag_chk_comp(struct ice_lag *lag, void *ptr) +{ + return true; +} + +/** + * ice_lag_unregister - handle netdev unregister events + * @lag: LAG info struct + * @event_netdev: netdev struct for target of notifier event + */ +static void +ice_lag_unregister(struct ice_lag *lag, struct net_device *event_netdev) +{ +} - netdev_dbg(netdev, "bonding %s\n", info->linking ? "LINK" : "UNLINK"); +/** + * ice_lag_monitor_rdma - set and clear rdma functionality + * @lag: pointer to lag struct + * @ptr: opaque data for netdev event info + */ +static void +ice_lag_monitor_rdma(struct ice_lag *lag, void *ptr) +{ + struct netdev_notifier_changeupper_info *info; + struct net_device *netdev; + + info = ptr; + netdev = netdev_notifier_info_to_dev(ptr); - if (!netif_is_lag_master(info->upper_dev)) { - netdev_dbg(netdev, "changeupper rcvd, but not primary. bail\n"); + if (netdev != lag->netdev) return; - } if (info->linking) - ice_lag_link(lag, info); + ice_clear_rdma_cap(lag->pf); else - ice_lag_unlink(lag, info); - - ice_display_lag_info(lag); + ice_set_rdma_cap(lag->pf); } /** @@ -307,16 +679,31 @@ static void ice_lag_process_event(struct work_struct *work) switch (lag_work->event) { case NETDEV_CHANGEUPPER: info = &lag_work->info.changeupper_info; - ice_lag_changeupper_event(lag_work->lag, info); + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { + ice_lag_monitor_link(lag_work->lag, info); + ice_lag_changeupper_event(lag_work->lag, info); + ice_lag_link_unlink(lag_work->lag, info); + } + ice_lag_monitor_rdma(lag_work->lag, info); break; case NETDEV_BONDING_INFO: + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { + if (!ice_lag_chk_comp(lag_work->lag, + &lag_work->info.bonding_info)) { + goto lag_cleanup; + } + ice_lag_monitor_active(lag_work->lag, + &lag_work->info.bonding_info); + ice_lag_cfg_pf_fltrs(lag_work->lag, + &lag_work->info.bonding_info); + } ice_lag_info_event(lag_work->lag, &lag_work->info.bonding_info); break; case NETDEV_UNREGISTER: if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { netdev = lag_work->info.bonding_info.info.dev; - if ((netdev == lag_work->lag->netdev || - lag_work->lag->primary) && lag_work->lag->bonded) + if (netdev == lag_work->lag->netdev && + lag_work->lag->bonded) ice_lag_unregister(lag_work->lag, netdev); } break; @@ -324,6 +711,7 @@ static void ice_lag_process_event(struct work_struct *work) break; } +lag_cleanup: /* cleanup resources allocated for this work item */ list_for_each_safe(tmp, n, &lag_work->netdev_list.node) { struct ice_lag_netdev_list *entry; @@ -465,6 +853,22 @@ static void ice_unregister_lag_handler(struct ice_lag *lag) } } +/** + * ice_create_lag_recipe + * @hw: pointer to HW struct + * @base_recipe: recipe to base the new recipe on + * @prio: priority for new recipe + * + * function returns 0 on error + */ +static u16 ice_create_lag_recipe(struct ice_hw *hw, const u8 *base_recipe, + u8 prio) +{ + u16 rid = 0; + + return rid; +} + /** * ice_init_lag - initialize support for LAG * @pf: PF struct @@ -506,6 +910,12 @@ int ice_init_lag(struct ice_pf *pf) goto lag_error; } + lag->pf_recipe = ice_create_lag_recipe(&pf->hw, ice_dflt_vsi_rcp, 1); + if (!lag->pf_recipe) { + err = -EINVAL; + goto lag_error; + } + ice_display_lag_info(lag); dev_dbg(dev, "INIT LAG complete\n"); @@ -538,6 +948,9 @@ void ice_deinit_lag(struct ice_pf *pf) flush_workqueue(ice_lag_wq); + ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, + &pf->lag->pf_recipe); + kfree(lag); pf->lag = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h index a4314a46c82c..df4af5184a75 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.h +++ b/drivers/net/ethernet/intel/ice/ice_lag.h @@ -56,6 +56,7 @@ struct ice_lag_work { } info; }; +void ice_lag_move_new_vf_nodes(struct ice_vf *vf); int ice_init_lag(struct ice_pf *pf); void ice_deinit_lag(struct ice_pf *pf); #endif /* _ICE_LAG_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 8c332d24c7c5..91bc92f5059b 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -25,7 +25,6 @@ * In case of Ether type filter it is treated as header without VLAN tag * and byte 12 and 13 is used to program a given Ether type instead */ -#define DUMMY_ETH_HDR_LEN 16 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0x81, 0, 0, 0}; @@ -2460,6 +2459,15 @@ static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) } } +/** + * ice_fill_eth_hdr - helper to copy dummy_eth_hdr into supplied buffer + * @eth_hdr: pointer to buffer to populate + */ +void ice_fill_eth_hdr(u8 *eth_hdr) +{ + memcpy(eth_hdr, dummy_eth_header, DUMMY_ETH_HDR_LEN); +} + /** * ice_fill_sw_rule - Helper function to fill switch rule structure * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 51cd14952cd1..250823ac173a 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -30,6 +30,8 @@ ICE_SW_RULE_RX_TX_HDR_SIZE((s), 0) #define ICE_SW_RULE_LG_ACT_SIZE(s, n) struct_size((s), act, (n)) +#define DUMMY_ETH_HDR_LEN 16 + /* VSI context structure for add/get/update/free operations */ struct ice_vsi_ctx { u16 vsi_num; @@ -402,6 +404,7 @@ u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle); int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle); void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw); +void ice_fill_eth_hdr(u8 *eth_hdr); int ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index efbc2968a7bf..625da88e7965 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -1724,6 +1724,8 @@ error_param: vf->vf_id, i); } + ice_lag_move_new_vf_nodes(vf); + /* send the response to the VF */ return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, VIRTCHNL_STATUS_ERR_PARAM, NULL, 0); -- cgit From 1e0f9881ef79af9629bbf3cc3b307498d2e015ac Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:50 -0700 Subject: ice: Flesh out implementation of support for SRIOV on bonded interface Add in the functions that will allow a VF created on the primary interface of a bond to "fail-over" to another PF interface in the bond and continue to Tx and Rx. Add in an ordered take-down path for the bonded interface. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 826 ++++++++++++++++++++++++++++++- 1 file changed, 816 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index ac4deb5af118..f054bf6181da 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -10,6 +10,11 @@ #define ICE_LAG_RES_SHARED BIT(14) #define ICE_LAG_RES_VALID BIT(15) +#define LACP_TRAIN_PKT_LEN 16 +static const u8 lacp_train_pkt[LACP_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x88, 0x09, 0, 0 }; + #define ICE_RECIPE_LEN 64 static const u8 ice_dflt_vsi_rcp[ICE_RECIPE_LEN] = { 0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -57,6 +62,39 @@ static void ice_lag_set_backup(struct ice_lag *lag) lag->role = ICE_LAG_BACKUP; } +/** + * netif_is_same_ice - determine if netdev is on the same ice NIC as local PF + * @pf: local PF struct + * @netdev: netdev we are evaluating + */ +static bool netif_is_same_ice(struct ice_pf *pf, struct net_device *netdev) +{ + struct ice_netdev_priv *np; + struct ice_pf *test_pf; + struct ice_vsi *vsi; + + if (!netif_is_ice(netdev)) + return false; + + np = netdev_priv(netdev); + if (!np) + return false; + + vsi = np->vsi; + if (!vsi) + return false; + + test_pf = vsi->back; + if (!test_pf) + return false; + + if (pf->pdev->bus != test_pf->pdev->bus || + pf->pdev->slot != test_pf->pdev->slot) + return false; + + return true; +} + /** * ice_netdev_to_lag - return pointer to associated lag struct from netdev * @netdev: pointer to net_device struct to query @@ -80,6 +118,38 @@ static struct ice_lag *ice_netdev_to_lag(struct net_device *netdev) return vsi->back->lag; } +/** + * ice_lag_find_hw_by_lport - return an hw struct from bond members lport + * @lag: lag struct + * @lport: lport value to search for + */ +static struct ice_hw * +ice_lag_find_hw_by_lport(struct ice_lag *lag, u8 lport) +{ + struct ice_lag_netdev_list *entry; + struct net_device *tmp_netdev; + struct ice_netdev_priv *np; + struct list_head *tmp; + struct ice_hw *hw; + + list_for_each(tmp, lag->netdev_head) { + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + tmp_netdev = entry->netdev; + if (!tmp_netdev || !netif_is_ice(tmp_netdev)) + continue; + + np = netdev_priv(tmp_netdev); + if (!np || !np->vsi) + continue; + + hw = &np->vsi->back->hw; + if (hw->port_info->lport == lport) + return hw; + } + + return NULL; +} + /** * ice_lag_find_primary - returns pointer to primary interfaces lag struct * @lag: local interfaces lag struct @@ -233,6 +303,123 @@ static void ice_display_lag_info(struct ice_lag *lag) upper, role, primary); } +/** + * ice_lag_qbuf_recfg - generate a buffer of queues for a reconfigure command + * @hw: HW struct that contains the queue contexts + * @qbuf: pointer to buffer to populate + * @vsi_num: index of the VSI in PF space + * @numq: number of queues to search for + * @tc: traffic class that contains the queues + * + * function returns the number of valid queues in buffer + */ +static u16 +ice_lag_qbuf_recfg(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *qbuf, + u16 vsi_num, u16 numq, u8 tc) +{ + struct ice_q_ctx *q_ctx; + u16 qid, count = 0; + struct ice_pf *pf; + int i; + + pf = hw->back; + for (i = 0; i < numq; i++) { + q_ctx = ice_get_lan_q_ctx(hw, vsi_num, tc, i); + if (!q_ctx) { + dev_dbg(ice_hw_to_dev(hw), "%s queue %d NO Q CONTEXT\n", + __func__, i); + continue; + } + if (q_ctx->q_teid == ICE_INVAL_TEID) { + dev_dbg(ice_hw_to_dev(hw), "%s queue %d INVAL TEID\n", + __func__, i); + continue; + } + if (q_ctx->q_handle == ICE_INVAL_Q_HANDLE) { + dev_dbg(ice_hw_to_dev(hw), "%s queue %d INVAL Q HANDLE\n", + __func__, i); + continue; + } + + qid = pf->vsi[vsi_num]->txq_map[q_ctx->q_handle]; + qbuf->queue_info[count].q_handle = cpu_to_le16(qid); + qbuf->queue_info[count].tc = tc; + qbuf->queue_info[count].q_teid = cpu_to_le32(q_ctx->q_teid); + count++; + } + + return count; +} + +/** + * ice_lag_get_sched_parent - locate or create a sched node parent + * @hw: HW struct for getting parent in + * @tc: traffic class on parent/node + */ +static struct ice_sched_node * +ice_lag_get_sched_parent(struct ice_hw *hw, u8 tc) +{ + struct ice_sched_node *tc_node, *aggnode, *parent = NULL; + u16 num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 }; + struct ice_port_info *pi = hw->port_info; + struct device *dev; + u8 aggl, vsil; + int n; + + dev = ice_hw_to_dev(hw); + + tc_node = ice_sched_get_tc_node(pi, tc); + if (!tc_node) { + dev_warn(dev, "Failure to find TC node for LAG move\n"); + return parent; + } + + aggnode = ice_sched_get_agg_node(pi, tc_node, ICE_DFLT_AGG_ID); + if (!aggnode) { + dev_warn(dev, "Failure to find aggregate node for LAG move\n"); + return parent; + } + + aggl = ice_sched_get_agg_layer(hw); + vsil = ice_sched_get_vsi_layer(hw); + + for (n = aggl + 1; n < vsil; n++) + num_nodes[n] = 1; + + for (n = 0; n < aggnode->num_children; n++) { + parent = ice_sched_get_free_vsi_parent(hw, aggnode->children[n], + num_nodes); + if (parent) + return parent; + } + + /* if free parent not found - add one */ + parent = aggnode; + for (n = aggl + 1; n < vsil; n++) { + u16 num_nodes_added; + u32 first_teid; + int err; + + err = ice_sched_add_nodes_to_layer(pi, tc_node, parent, n, + num_nodes[n], &first_teid, + &num_nodes_added); + if (err || num_nodes[n] != num_nodes_added) + return NULL; + + if (num_nodes_added) + parent = ice_sched_find_node_by_teid(tc_node, + first_teid); + else + parent = parent->children[0]; + if (!parent) { + dev_warn(dev, "Failure to add new parent for LAG move\n"); + return parent; + } + } + + return parent; +} + /** * ice_lag_move_vf_node_tc - move scheduling nodes for one VF on one TC * @lag: lag info struct @@ -245,6 +432,110 @@ static void ice_lag_move_vf_node_tc(struct ice_lag *lag, u8 oldport, u8 newport, u16 vsi_num, u8 tc) { + u16 numq, valq, buf_size, num_moved, qbuf_size; + struct device *dev = ice_pf_to_dev(lag->pf); + struct ice_aqc_cfg_txqs_buf *qbuf; + struct ice_aqc_move_elem *buf; + struct ice_sched_node *n_prt; + struct ice_hw *new_hw = NULL; + __le32 teid, parent_teid; + struct ice_vsi_ctx *ctx; + u32 tmp_teid; + + ctx = ice_get_vsi_ctx(&lag->pf->hw, vsi_num); + if (!ctx) { + dev_warn(dev, "Unable to locate VSI context for LAG failover\n"); + return; + } + + /* check to see if this VF is enabled on this TC */ + if (!ctx->sched.vsi_node[tc]) + return; + + /* locate HW struct for destination port */ + new_hw = ice_lag_find_hw_by_lport(lag, newport); + if (!new_hw) { + dev_warn(dev, "Unable to locate HW struct for LAG node destination\n"); + return; + } + + numq = ctx->num_lan_q_entries[tc]; + teid = ctx->sched.vsi_node[tc]->info.node_teid; + tmp_teid = le32_to_cpu(teid); + parent_teid = ctx->sched.vsi_node[tc]->info.parent_teid; + /* if no teid assigned or numq == 0, then this TC is not active */ + if (!tmp_teid || !numq) + return; + + /* suspend VSI subtree for Traffic Class "tc" on + * this VF's VSI + */ + if (ice_sched_suspend_resume_elems(&lag->pf->hw, 1, &tmp_teid, true)) + dev_dbg(dev, "Problem suspending traffic for LAG node move\n"); + + /* reconfigure all VF's queues on this Traffic Class + * to new port + */ + qbuf_size = struct_size(qbuf, queue_info, numq); + qbuf = kzalloc(qbuf_size, GFP_KERNEL); + if (!qbuf) { + dev_warn(dev, "Failure allocating memory for VF queue recfg buffer\n"); + goto resume_traffic; + } + + /* add the per queue info for the reconfigure command buffer */ + valq = ice_lag_qbuf_recfg(&lag->pf->hw, qbuf, vsi_num, numq, tc); + if (!valq) { + dev_dbg(dev, "No valid queues found for LAG failover\n"); + goto qbuf_none; + } + + if (ice_aq_cfg_lan_txq(&lag->pf->hw, qbuf, qbuf_size, valq, oldport, + newport, NULL)) { + dev_warn(dev, "Failure to configure queues for LAG failover\n"); + goto qbuf_err; + } + +qbuf_none: + kfree(qbuf); + + /* find new parent in destination port's tree for VF VSI node on this + * Traffic Class + */ + n_prt = ice_lag_get_sched_parent(new_hw, tc); + if (!n_prt) + goto resume_traffic; + + /* Move Vf's VSI node for this TC to newport's scheduler tree */ + buf_size = struct_size(buf, teid, 1); + buf = kzalloc(buf_size, GFP_KERNEL); + if (!buf) { + dev_warn(dev, "Failure to alloc memory for VF node failover\n"); + goto resume_traffic; + } + + buf->hdr.src_parent_teid = parent_teid; + buf->hdr.dest_parent_teid = n_prt->info.node_teid; + buf->hdr.num_elems = cpu_to_le16(1); + buf->hdr.mode = ICE_AQC_MOVE_ELEM_MODE_KEEP_OWN; + buf->teid[0] = teid; + + if (ice_aq_move_sched_elems(&lag->pf->hw, 1, buf, buf_size, &num_moved, + NULL)) + dev_warn(dev, "Failure to move VF nodes for failover\n"); + else + ice_sched_update_parent(n_prt, ctx->sched.vsi_node[tc]); + + kfree(buf); + goto resume_traffic; + +qbuf_err: + kfree(qbuf); + +resume_traffic: + /* restart traffic for VSI node */ + if (ice_sched_suspend_resume_elems(&lag->pf->hw, 1, &tmp_teid, false)) + dev_dbg(dev, "Problem restarting traffic for LAG node move\n"); } /** @@ -274,6 +565,66 @@ ice_lag_move_single_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport, */ void ice_lag_move_new_vf_nodes(struct ice_vf *vf) { + struct ice_lag_netdev_list ndlist; + struct list_head *tmp, *n; + u8 pri_port, act_port; + struct ice_lag *lag; + struct ice_vsi *vsi; + struct ice_pf *pf; + + vsi = ice_get_vf_vsi(vf); + + if (WARN_ON(!vsi)) + return; + + if (WARN_ON(vsi->type != ICE_VSI_VF)) + return; + + pf = vf->pf; + lag = pf->lag; + + mutex_lock(&pf->lag_mutex); + if (!lag->bonded) + goto new_vf_unlock; + + pri_port = pf->hw.port_info->lport; + act_port = lag->active_port; + + if (lag->upper_netdev) { + struct ice_lag_netdev_list *nl; + struct net_device *tmp_nd; + + INIT_LIST_HEAD(&ndlist.node); + rcu_read_lock(); + for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { + nl = kzalloc(sizeof(*nl), GFP_KERNEL); + if (!nl) + break; + + nl->netdev = tmp_nd; + list_add(&nl->node, &ndlist.node); + } + rcu_read_unlock(); + } + + lag->netdev_head = &ndlist.node; + + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) && + lag->bonded && lag->primary && pri_port != act_port && + !list_empty(lag->netdev_head)) + ice_lag_move_single_vf_nodes(lag, pri_port, act_port, vsi->idx); + + list_for_each_safe(tmp, n, &ndlist.node) { + struct ice_lag_netdev_list *entry; + + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + list_del(&entry->node); + kfree(entry); + } + lag->netdev_head = NULL; + +new_vf_unlock: + mutex_unlock(&pf->lag_mutex); } /** @@ -308,6 +659,50 @@ static void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport) static void ice_lag_cfg_cp_fltr(struct ice_lag *lag, bool add) { + struct ice_sw_rule_lkup_rx_tx *s_rule = NULL; + struct ice_vsi *vsi; + u16 buf_len, opc; + + vsi = lag->pf->vsi[0]; + + buf_len = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, + ICE_LAG_SRIOV_TRAIN_PKT_LEN); + s_rule = kzalloc(buf_len, GFP_KERNEL); + if (!s_rule) { + netdev_warn(lag->netdev, "-ENOMEM error configuring CP filter\n"); + return; + } + + if (add) { + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); + s_rule->recipe_id = cpu_to_le16(ICE_LAG_SRIOV_CP_RECIPE); + s_rule->src = cpu_to_le16(vsi->port_info->lport); + s_rule->act = cpu_to_le32(ICE_FWD_TO_VSI | + ICE_SINGLE_ACT_LAN_ENABLE | + ICE_SINGLE_ACT_VALID_BIT | + ((vsi->vsi_num << + ICE_SINGLE_ACT_VSI_ID_S) & + ICE_SINGLE_ACT_VSI_ID_M)); + s_rule->hdr_len = cpu_to_le16(ICE_LAG_SRIOV_TRAIN_PKT_LEN); + memcpy(s_rule->hdr_data, lacp_train_pkt, LACP_TRAIN_PKT_LEN); + opc = ice_aqc_opc_add_sw_rules; + } else { + opc = ice_aqc_opc_remove_sw_rules; + s_rule->index = cpu_to_le16(lag->cp_rule_idx); + } + if (ice_aq_sw_rules(&lag->pf->hw, s_rule, buf_len, 1, opc, NULL)) { + netdev_warn(lag->netdev, "Error %s CP rule for fail-over\n", + add ? "ADDING" : "REMOVING"); + goto cp_free; + } + + if (add) + lag->cp_rule_idx = le16_to_cpu(s_rule->index); + else + lag->cp_rule_idx = 0; + +cp_free: + kfree(s_rule); } /** @@ -362,6 +757,100 @@ static void ice_lag_reclaim_vf_tc(struct ice_lag *lag, struct ice_hw *src_hw, u16 vsi_num, u8 tc) { + u16 numq, valq, buf_size, num_moved, qbuf_size; + struct device *dev = ice_pf_to_dev(lag->pf); + struct ice_aqc_cfg_txqs_buf *qbuf; + struct ice_aqc_move_elem *buf; + struct ice_sched_node *n_prt; + __le32 teid, parent_teid; + struct ice_vsi_ctx *ctx; + struct ice_hw *hw; + u32 tmp_teid; + + hw = &lag->pf->hw; + ctx = ice_get_vsi_ctx(hw, vsi_num); + if (!ctx) { + dev_warn(dev, "Unable to locate VSI context for LAG reclaim\n"); + return; + } + + /* check to see if this VF is enabled on this TC */ + if (!ctx->sched.vsi_node[tc]) + return; + + numq = ctx->num_lan_q_entries[tc]; + teid = ctx->sched.vsi_node[tc]->info.node_teid; + tmp_teid = le32_to_cpu(teid); + parent_teid = ctx->sched.vsi_node[tc]->info.parent_teid; + + /* if !teid or !numq, then this TC is not active */ + if (!tmp_teid || !numq) + return; + + /* suspend traffic */ + if (ice_sched_suspend_resume_elems(hw, 1, &tmp_teid, true)) + dev_dbg(dev, "Problem suspending traffic for LAG node move\n"); + + /* reconfig queues for new port */ + qbuf_size = struct_size(qbuf, queue_info, numq); + qbuf = kzalloc(qbuf_size, GFP_KERNEL); + if (!qbuf) { + dev_warn(dev, "Failure allocating memory for VF queue recfg buffer\n"); + goto resume_reclaim; + } + + /* add the per queue info for the reconfigure command buffer */ + valq = ice_lag_qbuf_recfg(hw, qbuf, vsi_num, numq, tc); + if (!valq) { + dev_dbg(dev, "No valid queues found for LAG reclaim\n"); + goto reclaim_none; + } + + if (ice_aq_cfg_lan_txq(hw, qbuf, qbuf_size, numq, + src_hw->port_info->lport, hw->port_info->lport, + NULL)) { + dev_warn(dev, "Failure to configure queues for LAG failover\n"); + goto reclaim_qerr; + } + +reclaim_none: + kfree(qbuf); + + /* find parent in primary tree */ + n_prt = ice_lag_get_sched_parent(hw, tc); + if (!n_prt) + goto resume_reclaim; + + /* Move node to new parent */ + buf_size = struct_size(buf, teid, 1); + buf = kzalloc(buf_size, GFP_KERNEL); + if (!buf) { + dev_warn(dev, "Failure to alloc memory for VF node failover\n"); + goto resume_reclaim; + } + + buf->hdr.src_parent_teid = parent_teid; + buf->hdr.dest_parent_teid = n_prt->info.node_teid; + buf->hdr.num_elems = cpu_to_le16(1); + buf->hdr.mode = ICE_AQC_MOVE_ELEM_MODE_KEEP_OWN; + buf->teid[0] = teid; + + if (ice_aq_move_sched_elems(&lag->pf->hw, 1, buf, buf_size, &num_moved, + NULL)) + dev_warn(dev, "Failure to move VF nodes for LAG reclaim\n"); + else + ice_sched_update_parent(n_prt, ctx->sched.vsi_node[tc]); + + kfree(buf); + goto resume_reclaim; + +reclaim_qerr: + kfree(qbuf); + +resume_reclaim: + /* restart traffic */ + if (ice_sched_suspend_resume_elems(hw, 1, &tmp_teid, false)) + dev_warn(dev, "Problem restarting traffic for LAG node reclaim\n"); } /** @@ -476,6 +965,65 @@ static void ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, bool link) { + struct ice_aqc_alloc_free_res_elem *buf; + struct ice_aqc_set_port_params *cmd; + struct ice_aq_desc desc; + u16 buf_len, swid; + int status; + + buf_len = struct_size(buf, elem, 1); + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) { + dev_err(ice_pf_to_dev(local_lag->pf), "-ENOMEM error setting SWID\n"); + return; + } + + buf->num_elems = cpu_to_le16(1); + buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_SWID); + /* if unlinnking need to free the shared resource */ + if (!link && local_lag->bond_swid) { + buf->elem[0].e.sw_resp = cpu_to_le16(local_lag->bond_swid); + status = ice_aq_alloc_free_res(&local_lag->pf->hw, 1, buf, + buf_len, ice_aqc_opc_free_res, + NULL); + if (status) + dev_err(ice_pf_to_dev(local_lag->pf), "Error freeing SWID during LAG unlink\n"); + local_lag->bond_swid = 0; + } + + if (link) { + buf->res_type |= cpu_to_le16(ICE_LAG_RES_SHARED | + ICE_LAG_RES_VALID); + /* store the primary's SWID in case it leaves bond first */ + local_lag->bond_swid = primary_swid; + buf->elem[0].e.sw_resp = cpu_to_le16(local_lag->bond_swid); + } else { + buf->elem[0].e.sw_resp = + cpu_to_le16(local_lag->pf->hw.port_info->sw_id); + } + + status = ice_aq_alloc_free_res(&local_lag->pf->hw, 1, buf, buf_len, + ice_aqc_opc_alloc_res, NULL); + if (status) + dev_err(ice_pf_to_dev(local_lag->pf), "Error subscribing to SWID 0x%04X\n", + local_lag->bond_swid); + + kfree(buf); + + /* Configure port param SWID to correct value */ + if (link) + swid = primary_swid; + else + swid = local_lag->pf->hw.port_info->sw_id; + + cmd = &desc.params.set_port_params; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params); + + cmd->swid = cpu_to_le16(ICE_AQC_PORT_SWID_VALID | swid); + status = ice_aq_send_cmd(&local_lag->pf->hw, &desc, NULL, 0, NULL); + if (status) + dev_err(ice_pf_to_dev(local_lag->pf), "Error setting SWID in port params %d\n", + status); } /** @@ -504,6 +1052,38 @@ static void ice_lag_primary_swid(struct ice_lag *lag, bool link) */ static void ice_lag_add_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) { + u16 num_vsi, rule_buf_sz, vsi_list_id, event_vsi_num, prim_vsi_idx; + struct ice_sw_rule_vsi_list *s_rule = NULL; + struct device *dev; + + num_vsi = 1; + + dev = ice_pf_to_dev(lag->pf); + event_vsi_num = event_pf->vsi[0]->vsi_num; + prim_vsi_idx = lag->pf->vsi[0]->idx; + + if (!ice_find_vsi_list_entry(&lag->pf->hw, ICE_SW_LKUP_VLAN, + prim_vsi_idx, &vsi_list_id)) { + dev_warn(dev, "Could not locate prune list when setting up SRIOV LAG\n"); + return; + } + + rule_buf_sz = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi); + s_rule = kzalloc(rule_buf_sz, GFP_KERNEL); + if (!s_rule) { + dev_warn(dev, "Error allocating space for prune list when configuring SRIOV LAG\n"); + return; + } + + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_PRUNE_LIST_SET); + s_rule->index = cpu_to_le16(vsi_list_id); + s_rule->number_vsi = cpu_to_le16(num_vsi); + s_rule->vsi[0] = cpu_to_le16(event_vsi_num); + + if (ice_aq_sw_rules(&event_pf->hw, s_rule, rule_buf_sz, 1, + ice_aqc_opc_update_sw_rules, NULL)) + dev_warn(dev, "Error adding VSI prune list\n"); + kfree(s_rule); } /** @@ -513,6 +1093,39 @@ static void ice_lag_add_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) */ static void ice_lag_del_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) { + u16 num_vsi, vsi_num, vsi_idx, rule_buf_sz, vsi_list_id; + struct ice_sw_rule_vsi_list *s_rule = NULL; + struct device *dev; + + num_vsi = 1; + + dev = ice_pf_to_dev(lag->pf); + vsi_num = event_pf->vsi[0]->vsi_num; + vsi_idx = lag->pf->vsi[0]->idx; + + if (!ice_find_vsi_list_entry(&lag->pf->hw, ICE_SW_LKUP_VLAN, + vsi_idx, &vsi_list_id)) { + dev_warn(dev, "Could not locate prune list when unwinding SRIOV LAG\n"); + return; + } + + rule_buf_sz = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi); + s_rule = kzalloc(rule_buf_sz, GFP_KERNEL); + if (!s_rule) { + dev_warn(dev, "Error allocating prune list when unwinding SRIOV LAG\n"); + return; + } + + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR); + s_rule->index = cpu_to_le16(vsi_list_id); + s_rule->number_vsi = cpu_to_le16(num_vsi); + s_rule->vsi[0] = cpu_to_le16(vsi_num); + + if (ice_aq_sw_rules(&event_pf->hw, (struct ice_aqc_sw_rules *)s_rule, + rule_buf_sz, 1, ice_aqc_opc_update_sw_rules, NULL)) + dev_warn(dev, "Error clearing VSI prune list\n"); + + kfree(s_rule); } /** @@ -539,8 +1152,6 @@ static void ice_lag_init_feature_support_flag(struct ice_pf *pf) * ice_lag_changeupper_event - handle LAG changeupper event * @lag: LAG info struct * @ptr: opaque pointer data - * - * ptr is to be cast into netdev_notifier_changeupper_info */ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) { @@ -600,6 +1211,40 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) */ static void ice_lag_monitor_link(struct ice_lag *lag, void *ptr) { + struct netdev_notifier_changeupper_info *info; + struct ice_hw *prim_hw, *active_hw; + struct net_device *event_netdev; + struct ice_pf *pf; + u8 prim_port; + + if (!lag->primary) + return; + + event_netdev = netdev_notifier_info_to_dev(ptr); + if (!netif_is_same_ice(lag->pf, event_netdev)) + return; + + pf = lag->pf; + prim_hw = &pf->hw; + prim_port = prim_hw->port_info->lport; + + info = (struct netdev_notifier_changeupper_info *)ptr; + if (info->upper_dev != lag->upper_netdev) + return; + + if (!info->linking) { + /* Since there are only two interfaces allowed in SRIOV+LAG, if + * one port is leaving, then nodes need to be on primary + * interface. + */ + if (prim_port != lag->active_port && + lag->active_port != ICE_LAG_INVALID_PORT) { + active_hw = ice_lag_find_hw_by_lport(lag, + lag->active_port); + ice_lag_reclaim_vf_nodes(lag, active_hw); + lag->active_port = ICE_LAG_INVALID_PORT; + } + } } /** @@ -612,6 +1257,67 @@ static void ice_lag_monitor_link(struct ice_lag *lag, void *ptr) */ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) { + struct net_device *event_netdev, *event_upper; + struct netdev_notifier_bonding_info *info; + struct netdev_bonding_info *bonding_info; + struct ice_netdev_priv *event_np; + struct ice_pf *pf, *event_pf; + u8 prim_port, event_port; + + if (!lag->primary) + return; + + pf = lag->pf; + if (!pf) + return; + + event_netdev = netdev_notifier_info_to_dev(ptr); + rcu_read_lock(); + event_upper = netdev_master_upper_dev_get_rcu(event_netdev); + rcu_read_unlock(); + if (!netif_is_ice(event_netdev) || event_upper != lag->upper_netdev) + return; + + event_np = netdev_priv(event_netdev); + event_pf = event_np->vsi->back; + event_port = event_pf->hw.port_info->lport; + prim_port = pf->hw.port_info->lport; + + info = (struct netdev_notifier_bonding_info *)ptr; + bonding_info = &info->bonding_info; + + if (!bonding_info->slave.state) { + /* if no port is currently active, then nodes and filters exist + * on primary port, check if we need to move them + */ + if (lag->active_port == ICE_LAG_INVALID_PORT) { + if (event_port != prim_port) + ice_lag_move_vf_nodes(lag, prim_port, + event_port); + lag->active_port = event_port; + return; + } + + /* active port is already set and is current event port */ + if (lag->active_port == event_port) + return; + /* new active port */ + ice_lag_move_vf_nodes(lag, lag->active_port, event_port); + lag->active_port = event_port; + } else { + /* port not set as currently active (e.g. new active port + * has already claimed the nodes and filters + */ + if (lag->active_port != event_port) + return; + /* This is the case when neither port is active (both link down) + * Link down on the bond - set active port to invalid and move + * nodes and filters back to primary if not already there + */ + if (event_port != prim_port) + ice_lag_move_vf_nodes(lag, event_port, prim_port); + lag->active_port = ICE_LAG_INVALID_PORT; + } } /** @@ -622,6 +1328,68 @@ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) static bool ice_lag_chk_comp(struct ice_lag *lag, void *ptr) { + struct net_device *event_netdev, *event_upper; + struct netdev_notifier_bonding_info *info; + struct netdev_bonding_info *bonding_info; + struct list_head *tmp; + int count = 0; + + if (!lag->primary) + return true; + + event_netdev = netdev_notifier_info_to_dev(ptr); + rcu_read_lock(); + event_upper = netdev_master_upper_dev_get_rcu(event_netdev); + rcu_read_unlock(); + if (event_upper != lag->upper_netdev) + return true; + + info = (struct netdev_notifier_bonding_info *)ptr; + bonding_info = &info->bonding_info; + lag->bond_mode = bonding_info->master.bond_mode; + if (lag->bond_mode != BOND_MODE_ACTIVEBACKUP) { + netdev_info(lag->netdev, "Bond Mode not ACTIVE-BACKUP\n"); + return false; + } + + list_for_each(tmp, lag->netdev_head) { + struct ice_dcbx_cfg *dcb_cfg, *peer_dcb_cfg; + struct ice_lag_netdev_list *entry; + struct ice_netdev_priv *peer_np; + struct net_device *peer_netdev; + struct ice_vsi *vsi, *peer_vsi; + + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + peer_netdev = entry->netdev; + if (!netif_is_ice(peer_netdev)) { + netdev_info(lag->netdev, "Found non-ice netdev in LAG\n"); + return false; + } + + count++; + if (count > 2) { + netdev_info(lag->netdev, "Found more than two netdevs in LAG\n"); + return false; + } + + peer_np = netdev_priv(peer_netdev); + vsi = ice_get_main_vsi(lag->pf); + peer_vsi = peer_np->vsi; + if (lag->pf->pdev->bus != peer_vsi->back->pdev->bus || + lag->pf->pdev->slot != peer_vsi->back->pdev->slot) { + netdev_info(lag->netdev, "Found netdev on different device in LAG\n"); + return false; + } + + dcb_cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg; + peer_dcb_cfg = &peer_vsi->port_info->qos_cfg.local_dcbx_cfg; + if (memcmp(dcb_cfg, peer_dcb_cfg, + sizeof(struct ice_dcbx_cfg))) { + netdev_info(lag->netdev, "Found netdev with different DCB config in LAG\n"); + return false; + } + } + return true; } @@ -856,17 +1624,40 @@ static void ice_unregister_lag_handler(struct ice_lag *lag) /** * ice_create_lag_recipe * @hw: pointer to HW struct + * @rid: pointer to u16 to pass back recipe index * @base_recipe: recipe to base the new recipe on * @prio: priority for new recipe * * function returns 0 on error */ -static u16 ice_create_lag_recipe(struct ice_hw *hw, const u8 *base_recipe, - u8 prio) +static int ice_create_lag_recipe(struct ice_hw *hw, u16 *rid, + const u8 *base_recipe, u8 prio) { - u16 rid = 0; + struct ice_aqc_recipe_data_elem *new_rcp; + int err; + + err = ice_alloc_recipe(hw, rid); + if (err) + return err; + + new_rcp = kzalloc(ICE_RECIPE_LEN * ICE_MAX_NUM_RECIPES, GFP_KERNEL); + if (!new_rcp) + return -ENOMEM; + + memcpy(new_rcp, base_recipe, ICE_RECIPE_LEN); + new_rcp->content.act_ctrl_fwd_priority = prio; + new_rcp->content.rid = *rid | ICE_AQ_RECIPE_ID_IS_ROOT; + new_rcp->recipe_indx = *rid; + bitmap_zero((unsigned long *)new_rcp->recipe_bitmap, + ICE_MAX_NUM_RECIPES); + set_bit(*rid, (unsigned long *)new_rcp->recipe_bitmap); - return rid; + err = ice_aq_add_recipe(hw, new_rcp, 1, NULL); + if (err) + *rid = 0; + + kfree(new_rcp); + return err; } /** @@ -881,7 +1672,8 @@ int ice_init_lag(struct ice_pf *pf) struct device *dev = ice_pf_to_dev(pf); struct ice_lag *lag; struct ice_vsi *vsi; - int err; + u64 recipe_bits = 0; + int n, err; ice_lag_init_feature_support_flag(pf); @@ -900,6 +1692,7 @@ int ice_init_lag(struct ice_pf *pf) lag->pf = pf; lag->netdev = vsi->netdev; lag->role = ICE_LAG_NONE; + lag->active_port = ICE_LAG_INVALID_PORT; lag->bonded = false; lag->upper_netdev = NULL; lag->notif_block.notifier_call = NULL; @@ -910,10 +1703,23 @@ int ice_init_lag(struct ice_pf *pf) goto lag_error; } - lag->pf_recipe = ice_create_lag_recipe(&pf->hw, ice_dflt_vsi_rcp, 1); - if (!lag->pf_recipe) { - err = -EINVAL; + err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe, ice_dflt_vsi_rcp, + 1); + if (err) goto lag_error; + + /* associate recipes to profiles */ + for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { + err = ice_aq_get_recipe_to_profile(&pf->hw, n, + (u8 *)&recipe_bits, NULL); + if (err) + continue; + + if (recipe_bits & BIT(ICE_SW_LKUP_DFLT)) { + recipe_bits |= BIT(lag->pf_recipe); + ice_aq_map_recipe_to_profile(&pf->hw, n, + (u8 *)&recipe_bits, NULL); + } } ice_display_lag_info(lag); -- cgit From ba789fb45697e98a3fce9d0f26e41067a65a8a05 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:51 -0700 Subject: ice: support non-standard teardown of bond interface Code for supporting removal of the PF driver (NETDEV_UNREGISTER) events for both when the bond has the primary interface as active and when failed over to thew secondary interface. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 47 +++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index f054bf6181da..33aedbc506a0 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -1190,15 +1190,16 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) if (!primary_lag && lag->primary) primary_lag = lag; - if (primary_lag) { - if (!lag->primary) { - ice_lag_set_swid(0, lag, false); - } else { + if (!lag->primary) { + ice_lag_set_swid(0, lag, false); + } else { + if (primary_lag && lag->primary) { ice_lag_primary_swid(lag, false); ice_lag_del_prune_list(primary_lag, lag->pf); } - ice_lag_cfg_cp_fltr(lag, false); } + /* remove filter for control packets */ + ice_lag_cfg_cp_fltr(lag, false); } } @@ -1401,6 +1402,38 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) static void ice_lag_unregister(struct ice_lag *lag, struct net_device *event_netdev) { + struct ice_netdev_priv *np; + struct ice_pf *event_pf; + struct ice_lag *p_lag; + + p_lag = ice_lag_find_primary(lag); + np = netdev_priv(event_netdev); + event_pf = np->vsi->back; + + if (p_lag) { + if (p_lag->active_port != p_lag->pf->hw.port_info->lport && + p_lag->active_port != ICE_LAG_INVALID_PORT) { + struct ice_hw *active_hw; + + active_hw = ice_lag_find_hw_by_lport(lag, + p_lag->active_port); + if (active_hw) + ice_lag_reclaim_vf_nodes(p_lag, active_hw); + lag->active_port = ICE_LAG_INVALID_PORT; + } + } + + /* primary processing for primary */ + if (lag->primary && lag->netdev == event_netdev) + ice_lag_primary_swid(lag, false); + + /* primary processing for secondary */ + if (lag->primary && lag->netdev != event_netdev) + ice_lag_del_prune_list(lag, event_pf); + + /* secondary processing for secondary */ + if (!lag->primary && lag->netdev == event_netdev) + ice_lag_set_swid(0, lag, false); } /** @@ -1470,8 +1503,8 @@ static void ice_lag_process_event(struct work_struct *work) case NETDEV_UNREGISTER: if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { netdev = lag_work->info.bonding_info.info.dev; - if (netdev == lag_work->lag->netdev && - lag_work->lag->bonded) + if ((netdev == lag_work->lag->netdev || + lag_work->lag->primary) && lag_work->lag->bonded) ice_lag_unregister(lag_work->lag, netdev); } break; -- cgit From bf65da2eb279f27d6933e11a713a55fe49e71671 Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:52 -0700 Subject: ice: enforce interface eligibility and add messaging for SRIOV LAG Implement checks on what interfaces are eligible for supporting SRIOV VFs when a member of an aggregate interface. Implement unwind path for interfaces that become ineligible. checks for the SRIOV LAG feature bit wrap most of the functional code for manipulating resources that apply to this feature. Utilize this bit to track compliant aggregates. Also flag any new entries into the aggregate as not supporting SRIOV LAG for the time they are in the non-compliant aggregate. Once an aggregate has been flagged as non-compliant, only unpopulating the aggregate and re-populating it will return SRIOV LAG functionality. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 89 ++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 33aedbc506a0..fecc77279647 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -889,6 +889,7 @@ static void ice_lag_link(struct ice_lag *lag) lag->bonded = true; lag->role = ICE_LAG_UNSET; + netdev_info(lag->netdev, "Shared SR-IOV resources in bond are active\n"); } /** @@ -1333,6 +1334,7 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) struct netdev_notifier_bonding_info *info; struct netdev_bonding_info *bonding_info; struct list_head *tmp; + struct device *dev; int count = 0; if (!lag->primary) @@ -1345,11 +1347,21 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) if (event_upper != lag->upper_netdev) return true; + dev = ice_pf_to_dev(lag->pf); + + /* only supporting switchdev mode for SRIOV VF LAG. + * primary interface has to be in switchdev mode + */ + if (!ice_is_switchdev_running(lag->pf)) { + dev_info(dev, "Primary interface not in switchdev mode - VF LAG disabled\n"); + return false; + } + info = (struct netdev_notifier_bonding_info *)ptr; bonding_info = &info->bonding_info; lag->bond_mode = bonding_info->master.bond_mode; if (lag->bond_mode != BOND_MODE_ACTIVEBACKUP) { - netdev_info(lag->netdev, "Bond Mode not ACTIVE-BACKUP\n"); + dev_info(dev, "Bond Mode not ACTIVE-BACKUP - VF LAG disabled\n"); return false; } @@ -1359,17 +1371,19 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) struct ice_netdev_priv *peer_np; struct net_device *peer_netdev; struct ice_vsi *vsi, *peer_vsi; + struct ice_pf *peer_pf; entry = list_entry(tmp, struct ice_lag_netdev_list, node); peer_netdev = entry->netdev; if (!netif_is_ice(peer_netdev)) { - netdev_info(lag->netdev, "Found non-ice netdev in LAG\n"); + dev_info(dev, "Found %s non-ice netdev in LAG - VF LAG disabled\n", + netdev_name(peer_netdev)); return false; } count++; if (count > 2) { - netdev_info(lag->netdev, "Found more than two netdevs in LAG\n"); + dev_info(dev, "Found more than two netdevs in LAG - VF LAG disabled\n"); return false; } @@ -1378,7 +1392,8 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) peer_vsi = peer_np->vsi; if (lag->pf->pdev->bus != peer_vsi->back->pdev->bus || lag->pf->pdev->slot != peer_vsi->back->pdev->slot) { - netdev_info(lag->netdev, "Found netdev on different device in LAG\n"); + dev_info(dev, "Found %s on different device in LAG - VF LAG disabled\n", + netdev_name(peer_netdev)); return false; } @@ -1386,7 +1401,15 @@ ice_lag_chk_comp(struct ice_lag *lag, void *ptr) peer_dcb_cfg = &peer_vsi->port_info->qos_cfg.local_dcbx_cfg; if (memcmp(dcb_cfg, peer_dcb_cfg, sizeof(struct ice_dcbx_cfg))) { - netdev_info(lag->netdev, "Found netdev with different DCB config in LAG\n"); + dev_info(dev, "Found %s with different DCB in LAG - VF LAG disabled\n", + netdev_name(peer_netdev)); + return false; + } + + peer_pf = peer_vsi->back; + if (test_bit(ICE_FLAG_FW_LLDP_AGENT, peer_pf->flags)) { + dev_warn(dev, "Found %s with FW LLDP agent active - VF LAG disabled\n", + netdev_name(peer_netdev)); return false; } } @@ -1459,6 +1482,58 @@ ice_lag_monitor_rdma(struct ice_lag *lag, void *ptr) ice_set_rdma_cap(lag->pf); } +/** + * ice_lag_chk_disabled_bond - monitor interfaces entering/leaving disabled bond + * @lag: lag info struct + * @ptr: opaque data containing event + * + * as interfaces enter a bond - determine if the bond is currently + * SRIOV LAG compliant and flag if not. As interfaces leave the + * bond, reset their compliant status. + */ +static void ice_lag_chk_disabled_bond(struct ice_lag *lag, void *ptr) +{ + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info = ptr; + struct ice_lag *prim_lag; + + if (netdev != lag->netdev) + return; + + if (info->linking) { + prim_lag = ice_lag_find_primary(lag); + if (prim_lag && + !ice_is_feature_supported(prim_lag->pf, ICE_F_SRIOV_LAG)) { + ice_clear_feature_support(lag->pf, ICE_F_SRIOV_LAG); + netdev_info(netdev, "Interface added to non-compliant SRIOV LAG aggregate\n"); + } + } else { + ice_lag_init_feature_support_flag(lag->pf); + } +} + +/** + * ice_lag_disable_sriov_bond - set members of bond as not supporting SRIOV LAG + * @lag: primary interfaces lag struct + */ +static void ice_lag_disable_sriov_bond(struct ice_lag *lag) +{ + struct ice_lag_netdev_list *entry; + struct ice_netdev_priv *np; + struct net_device *netdev; + struct list_head *tmp; + struct ice_pf *pf; + + list_for_each(tmp, lag->netdev_head) { + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + netdev = entry->netdev; + np = netdev_priv(netdev); + pf = np->vsi->back; + + ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); + } +} + /** * ice_lag_process_event - process a task assigned to the lag_wq * @work: pointer to work_struct @@ -1480,6 +1555,7 @@ static void ice_lag_process_event(struct work_struct *work) switch (lag_work->event) { case NETDEV_CHANGEUPPER: info = &lag_work->info.changeupper_info; + ice_lag_chk_disabled_bond(lag_work->lag, info); if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { ice_lag_monitor_link(lag_work->lag, info); ice_lag_changeupper_event(lag_work->lag, info); @@ -1491,6 +1567,9 @@ static void ice_lag_process_event(struct work_struct *work) if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) { if (!ice_lag_chk_comp(lag_work->lag, &lag_work->info.bonding_info)) { + netdev = lag_work->info.bonding_info.info.dev; + ice_lag_disable_sriov_bond(lag_work->lag); + ice_lag_unregister(lag_work->lag, netdev); goto lag_cleanup; } ice_lag_monitor_active(lag_work->lag, -- cgit From ab2ed5d77ab9c438d1ca8ebb230cf8eb699c163f Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:53 -0700 Subject: ice: enforce no DCB config changing when in bond To support SRIOV LAG, the driver cannot allow changes to an interface's DCB configuration when in a bond. This would break the ability to modify interfaces Tx scheduling for fail-over interfaces. Block kernel generated DCB config events when in a bond. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c index 3eb01731e496..e1fbc6de452d 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c @@ -70,6 +70,11 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) return -EINVAL; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return -EINVAL; + } + new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; mutex_lock(&pf->tc_mutex); @@ -170,6 +175,11 @@ static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode) if (mode == pf->dcbx_cap) return ICE_DCB_NO_HW_CHG; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return ICE_DCB_NO_HW_CHG; + } + qos_cfg = &pf->hw.port_info->qos_cfg; /* DSCP configuration is not DCBx negotiated */ @@ -261,6 +271,11 @@ static int ice_dcbnl_setpfc(struct net_device *netdev, struct ieee_pfc *pfc) !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) return -EINVAL; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return -EINVAL; + } + mutex_lock(&pf->tc_mutex); new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; @@ -323,6 +338,11 @@ static void ice_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, u8 set) if (prio >= ICE_MAX_USER_PRIORITY) return; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return; + } + new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc; @@ -379,6 +399,11 @@ static u8 ice_dcbnl_setstate(struct net_device *netdev, u8 state) !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return ICE_DCB_NO_HW_CHG; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return ICE_DCB_NO_HW_CHG; + } + /* Nothing to do */ if (!!state == test_bit(ICE_FLAG_DCB_ENA, pf->flags)) return ICE_DCB_NO_HW_CHG; @@ -451,6 +476,11 @@ ice_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, if (tc >= ICE_MAX_TRAFFIC_CLASS) return; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return; + } + new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; /* prio_type, bwg_id and bw_pct per UP are not supported */ @@ -505,6 +535,11 @@ ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 bw_pct) if (pgid >= ICE_MAX_TRAFFIC_CLASS) return; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return; + } + new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; new_cfg->etscfg.tcbwtable[pgid] = bw_pct; @@ -725,6 +760,11 @@ static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app) return -EINVAL; } + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return -EINVAL; + } + max_tc = pf->hw.func_caps.common_cap.maxtc; if (app->priority >= max_tc) { netdev_err(netdev, "TC %d out of range, max TC %d\n", @@ -836,6 +876,11 @@ static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app) return -EINVAL; } + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return -EINVAL; + } + mutex_lock(&pf->tc_mutex); old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; @@ -937,6 +982,11 @@ static u8 ice_dcbnl_cee_set_all(struct net_device *netdev) !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return ICE_DCB_NO_HW_CHG; + if (pf->lag && pf->lag->bonded) { + netdev_err(netdev, "DCB changes not allowed when in a bond\n"); + return ICE_DCB_NO_HW_CHG; + } + new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; mutex_lock(&pf->tc_mutex); -- cgit From 3579aa86fb4046a378f7d68583cfb7f62e0feabd Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Tue, 20 Jun 2023 15:18:54 -0700 Subject: ice: update reset path for SRIOV LAG support Add code to rebuild the LAG resources when rebuilding the state of the interface after a reset. Also added in a function for building per-queue information into the buffer used to configure VF queues for LAG fail-over. This improves code reuse. Due to differences in timing per interface for recovering from a reset, add in the ability to retry on non-local dependencies where needed. Reviewed-by: Daniel Machon Signed-off-by: Dave Ertman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 231 +++++++++++++++++++++++++++++- drivers/net/ethernet/intel/ice/ice_lag.h | 3 + drivers/net/ethernet/intel/ice/ice_main.c | 14 +- 3 files changed, 244 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index fecc77279647..36b7044717e8 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -961,6 +961,7 @@ static void ice_lag_link_unlink(struct ice_lag *lag, void *ptr) * @link: Is this a linking activity * * If link is false, then primary_swid should be expected to not be valid + * This function should never be called in interrupt context. */ static void ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, @@ -970,7 +971,7 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, struct ice_aqc_set_port_params *cmd; struct ice_aq_desc desc; u16 buf_len, swid; - int status; + int status, i; buf_len = struct_size(buf, elem, 1); buf = kzalloc(buf_len, GFP_KERNEL); @@ -1021,7 +1022,20 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params); cmd->swid = cpu_to_le16(ICE_AQC_PORT_SWID_VALID | swid); - status = ice_aq_send_cmd(&local_lag->pf->hw, &desc, NULL, 0, NULL); + /* If this is happening in reset context, it is possible that the + * primary interface has not finished setting its SWID to SHARED + * yet. Allow retries to account for this timing issue between + * interfaces. + */ + for (i = 0; i < ICE_LAG_RESET_RETRIES; i++) { + status = ice_aq_send_cmd(&local_lag->pf->hw, &desc, NULL, 0, + NULL); + if (!status) + break; + + usleep_range(1000, 2000); + } + if (status) dev_err(ice_pf_to_dev(local_lag->pf), "Error setting SWID in port params %d\n", status); @@ -1029,7 +1043,7 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, /** * ice_lag_primary_swid - set/clear the SHARED attrib of primary's SWID - * @lag: primary interfaces lag struct + * @lag: primary interface's lag struct * @link: is this a linking activity * * Implement setting primary SWID as shared using 0x020B @@ -1772,6 +1786,135 @@ static int ice_create_lag_recipe(struct ice_hw *hw, u16 *rid, return err; } +/** + * ice_lag_move_vf_nodes_tc_sync - move a VF's nodes for a tc during reset + * @lag: primary interfaces lag struct + * @dest_hw: HW struct for destination's interface + * @vsi_num: VSI index in PF space + * @tc: traffic class to move + */ +static void +ice_lag_move_vf_nodes_tc_sync(struct ice_lag *lag, struct ice_hw *dest_hw, + u16 vsi_num, u8 tc) +{ + u16 numq, valq, buf_size, num_moved, qbuf_size; + struct device *dev = ice_pf_to_dev(lag->pf); + struct ice_aqc_cfg_txqs_buf *qbuf; + struct ice_aqc_move_elem *buf; + struct ice_sched_node *n_prt; + __le32 teid, parent_teid; + struct ice_vsi_ctx *ctx; + struct ice_hw *hw; + u32 tmp_teid; + + hw = &lag->pf->hw; + ctx = ice_get_vsi_ctx(hw, vsi_num); + if (!ctx) { + dev_warn(dev, "LAG rebuild failed after reset due to VSI Context failure\n"); + return; + } + + if (!ctx->sched.vsi_node[tc]) + return; + + numq = ctx->num_lan_q_entries[tc]; + teid = ctx->sched.vsi_node[tc]->info.node_teid; + tmp_teid = le32_to_cpu(teid); + parent_teid = ctx->sched.vsi_node[tc]->info.parent_teid; + + if (!tmp_teid || !numq) + return; + + if (ice_sched_suspend_resume_elems(hw, 1, &tmp_teid, true)) + dev_dbg(dev, "Problem suspending traffic during reset rebuild\n"); + + /* reconfig queues for new port */ + qbuf_size = struct_size(qbuf, queue_info, numq); + qbuf = kzalloc(qbuf_size, GFP_KERNEL); + if (!qbuf) { + dev_warn(dev, "Failure allocating VF queue recfg buffer for reset rebuild\n"); + goto resume_sync; + } + + /* add the per queue info for the reconfigure command buffer */ + valq = ice_lag_qbuf_recfg(hw, qbuf, vsi_num, numq, tc); + if (!valq) { + dev_warn(dev, "Failure to reconfig queues for LAG reset rebuild\n"); + goto sync_none; + } + + if (ice_aq_cfg_lan_txq(hw, qbuf, qbuf_size, numq, hw->port_info->lport, + dest_hw->port_info->lport, NULL)) { + dev_warn(dev, "Failure to configure queues for LAG reset rebuild\n"); + goto sync_qerr; + } + +sync_none: + kfree(qbuf); + + /* find parent in destination tree */ + n_prt = ice_lag_get_sched_parent(dest_hw, tc); + if (!n_prt) + goto resume_sync; + + /* Move node to new parent */ + buf_size = struct_size(buf, teid, 1); + buf = kzalloc(buf_size, GFP_KERNEL); + if (!buf) { + dev_warn(dev, "Failure to alloc for VF node move in reset rebuild\n"); + goto resume_sync; + } + + buf->hdr.src_parent_teid = parent_teid; + buf->hdr.dest_parent_teid = n_prt->info.node_teid; + buf->hdr.num_elems = cpu_to_le16(1); + buf->hdr.mode = ICE_AQC_MOVE_ELEM_MODE_KEEP_OWN; + buf->teid[0] = teid; + + if (ice_aq_move_sched_elems(&lag->pf->hw, 1, buf, buf_size, &num_moved, + NULL)) + dev_warn(dev, "Failure to move VF nodes for LAG reset rebuild\n"); + else + ice_sched_update_parent(n_prt, ctx->sched.vsi_node[tc]); + + kfree(buf); + goto resume_sync; + +sync_qerr: + kfree(qbuf); + +resume_sync: + if (ice_sched_suspend_resume_elems(hw, 1, &tmp_teid, false)) + dev_warn(dev, "Problem restarting traffic for LAG node reset rebuild\n"); +} + +/** + * ice_lag_move_vf_nodes_sync - move vf nodes to active interface + * @lag: primary interfaces lag struct + * @dest_hw: lport value for currently active port + * + * This function is used in a reset context, outside of event handling, + * to move the VF nodes to the secondary interface when that interface + * is the active interface during a reset rebuild + */ +static void +ice_lag_move_vf_nodes_sync(struct ice_lag *lag, struct ice_hw *dest_hw) +{ + struct ice_pf *pf; + int i, tc; + + if (!lag->primary || !dest_hw) + return; + + pf = lag->pf; + ice_for_each_vsi(pf, i) + if (pf->vsi[i] && (pf->vsi[i]->type == ICE_VSI_VF || + pf->vsi[i]->type == ICE_VSI_SWITCHDEV_CTRL)) + ice_for_each_traffic_class(tc) + ice_lag_move_vf_nodes_tc_sync(lag, dest_hw, i, + tc); +} + /** * ice_init_lag - initialize support for LAG * @pf: PF struct @@ -1873,3 +2016,85 @@ void ice_deinit_lag(struct ice_pf *pf) pf->lag = NULL; } + +/** + * ice_lag_rebuild - rebuild lag resources after reset + * @pf: pointer to local pf struct + * + * PF resets are promoted to CORER resets when interface in an aggregate. This + * means that we need to rebuild the PF resources for the interface. Since + * this will happen outside the normal event processing, need to acquire the lag + * lock. + * + * This function will also evaluate the VF resources if this is the primary + * interface. + */ +void ice_lag_rebuild(struct ice_pf *pf) +{ + struct ice_lag_netdev_list ndlist; + struct ice_lag *lag, *prim_lag; + struct list_head *tmp, *n; + u8 act_port, loc_port; + + if (!pf->lag || !pf->lag->bonded) + return; + + mutex_lock(&pf->lag_mutex); + + lag = pf->lag; + if (lag->primary) { + prim_lag = lag; + } else { + struct ice_lag_netdev_list *nl; + struct net_device *tmp_nd; + + INIT_LIST_HEAD(&ndlist.node); + rcu_read_lock(); + for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { + nl = kzalloc(sizeof(*nl), GFP_KERNEL); + if (!nl) + break; + + nl->netdev = tmp_nd; + list_add(&nl->node, &ndlist.node); + } + rcu_read_unlock(); + lag->netdev_head = &ndlist.node; + prim_lag = ice_lag_find_primary(lag); + } + + if (!prim_lag) { + dev_dbg(ice_pf_to_dev(pf), "No primary interface in aggregate, can't rebuild\n"); + goto lag_rebuild_out; + } + + act_port = prim_lag->active_port; + loc_port = lag->pf->hw.port_info->lport; + + /* configure SWID for this port */ + if (lag->primary) { + ice_lag_primary_swid(lag, true); + } else { + ice_lag_set_swid(prim_lag->pf->hw.port_info->sw_id, lag, true); + ice_lag_add_prune_list(prim_lag, pf); + if (act_port == loc_port) + ice_lag_move_vf_nodes_sync(prim_lag, &pf->hw); + } + + ice_lag_cfg_cp_fltr(lag, true); + + if (lag->pf_rule_id) + if (ice_lag_cfg_dflt_fltr(lag, true)) + dev_err(ice_pf_to_dev(pf), "Error adding default VSI rule in rebuild\n"); + + ice_clear_rdma_cap(pf); +lag_rebuild_out: + list_for_each_safe(tmp, n, &ndlist.node) { + struct ice_lag_netdev_list *entry; + + entry = list_entry(tmp, struct ice_lag_netdev_list, node); + list_del(&entry->node); + kfree(entry); + } + mutex_unlock(&pf->lag_mutex); +} diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h index df4af5184a75..18075b82485a 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.h +++ b/drivers/net/ethernet/intel/ice/ice_lag.h @@ -16,6 +16,8 @@ enum ice_lag_role { #define ICE_LAG_INVALID_PORT 0xFF +#define ICE_LAG_RESET_RETRIES 5 + struct ice_pf; struct ice_vf; @@ -59,4 +61,5 @@ struct ice_lag_work { void ice_lag_move_new_vf_nodes(struct ice_vf *vf); int ice_init_lag(struct ice_pf *pf); void ice_deinit_lag(struct ice_pf *pf); +void ice_lag_rebuild(struct ice_pf *pf); #endif /* _ICE_LAG_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 7f7728dadcbb..20d5ed572a8c 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -636,6 +636,11 @@ static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type) dev_dbg(dev, "reset_type 0x%x requested\n", reset_type); + if (pf->lag && pf->lag->bonded && reset_type == ICE_RESET_PFR) { + dev_dbg(dev, "PFR on a bonded interface, promoting to CORER\n"); + reset_type = ICE_RESET_CORER; + } + ice_prepare_for_reset(pf, reset_type); /* trigger the reset */ @@ -719,8 +724,13 @@ static void ice_reset_subtask(struct ice_pf *pf) } /* No pending resets to finish processing. Check for new resets */ - if (test_bit(ICE_PFR_REQ, pf->state)) + if (test_bit(ICE_PFR_REQ, pf->state)) { reset_type = ICE_RESET_PFR; + if (pf->lag && pf->lag->bonded) { + dev_dbg(ice_pf_to_dev(pf), "PFR on a bonded interface, promoting to CORER\n"); + reset_type = ICE_RESET_CORER; + } + } if (test_bit(ICE_CORER_REQ, pf->state)) reset_type = ICE_RESET_CORER; if (test_bit(ICE_GLOBR_REQ, pf->state)) @@ -7373,6 +7383,8 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) clear_bit(ICE_RESET_FAILED, pf->state); ice_plug_aux_dev(pf); + if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) + ice_lag_rebuild(pf); return; err_vsi_rebuild: -- cgit From 02ceda65f014e357d4142e9c004f40b3b3d61857 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 13 Jun 2023 10:42:05 +0300 Subject: net/mlx5: Use shared code for checking lag is supported Move shared function to check lag is supported to lag header file. Signed-off-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/dev.c | 6 ++---- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 10 ---------- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index edb06fb9bbc5..7909f378dc93 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -36,6 +36,7 @@ #include #include "mlx5_core.h" #include "devlink.h" +#include "lag/lag.h" /* intf dev list mutex */ static DEFINE_MUTEX(mlx5_intf_mutex); @@ -587,10 +588,7 @@ static int next_phys_dev_lag(struct device *dev, const void *data) if (!mdev) return 0; - if (!MLX5_CAP_GEN(mdev, vport_group_manager) || - !MLX5_CAP_GEN(mdev, lag_master) || - (MLX5_CAP_GEN(mdev, num_lag_ports) > MLX5_MAX_PORTS || - MLX5_CAP_GEN(mdev, num_lag_ports) <= 1)) + if (!mlx5_lag_is_supported(mdev)) return 0; return _next_phys_dev(mdev, data); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index f0a074b2fcdf..900a18883f28 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -1268,16 +1268,6 @@ recheck: mlx5_ldev_put(ldev); } -bool mlx5_lag_is_supported(struct mlx5_core_dev *dev) -{ - if (!MLX5_CAP_GEN(dev, vport_group_manager) || - !MLX5_CAP_GEN(dev, lag_master) || - MLX5_CAP_GEN(dev, num_lag_ports) < 2 || - MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS) - return false; - return true; -} - void mlx5_lag_add_mdev(struct mlx5_core_dev *dev) { int err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index a061b1873e27..481e92f39fe6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -74,8 +74,6 @@ struct mlx5_lag { struct lag_mpesw lag_mpesw; }; -bool mlx5_lag_is_supported(struct mlx5_core_dev *dev); - static inline struct mlx5_lag * mlx5_lag_dev(struct mlx5_core_dev *dev) { @@ -115,4 +113,14 @@ void mlx5_lag_remove_devices(struct mlx5_lag *ldev); int mlx5_deactivate_lag(struct mlx5_lag *ldev); void mlx5_lag_add_devices(struct mlx5_lag *ldev); +static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev) +{ + if (!MLX5_CAP_GEN(dev, vport_group_manager) || + !MLX5_CAP_GEN(dev, lag_master) || + MLX5_CAP_GEN(dev, num_lag_ports) < 2 || + MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS) + return false; + return true; +} + #endif /* __MLX5_LAG_H__ */ -- cgit From 88d162b479815f5d6b6a4ff5fdb07aec9dc6280c Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 4 May 2023 12:14:00 +0300 Subject: net/mlx5: Devcom, Infrastructure changes Update devcom infrastructure to be more generic, without depending on max supported ports definition or a device guid, and also more encapsulated so callers don't need to pass the register devcom component id per event call. Signed-off-by: Eli Cohen Signed-off-by: Roi Dayan Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 21 +- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 36 +- .../net/ethernet/mellanox/mlx5/core/esw/bridge.c | 22 +- .../ethernet/mellanox/mlx5/core/esw/bridge_mcast.c | 17 +- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 3 + .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 47 ++- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 2 +- .../net/ethernet/mellanox/mlx5/core/lib/devcom.c | 448 +++++++++++---------- .../net/ethernet/mellanox/mlx5/core/lib/devcom.h | 74 ++-- drivers/net/ethernet/mellanox/mlx5/core/main.c | 12 +- 10 files changed, 357 insertions(+), 325 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 152b62138450..ca4f57f5064f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -399,15 +399,13 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, } static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, - struct mlx5_devcom *devcom, struct mlx5e_rep_sq *rep_sq, int i) { - struct mlx5_eswitch *peer_esw = NULL; struct mlx5_flow_handle *flow_rule; - int tmp; + struct mlx5_devcom_comp_dev *tmp; + struct mlx5_eswitch *peer_esw; - mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS, - peer_esw, tmp) { + mlx5_devcom_for_each_peer_entry(esw->devcom, peer_esw, tmp) { u16 peer_rule_idx = MLX5_CAP_GEN(peer_esw->dev, vhca_id); struct mlx5e_rep_sq_peer *sq_peer; int err; @@ -443,7 +441,6 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, struct mlx5_flow_handle *flow_rule; struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; - struct mlx5_devcom *devcom; bool devcom_locked = false; int err; int i; @@ -451,10 +448,10 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; - devcom = esw->dev->priv.devcom; rpriv = mlx5e_rep_to_rep_priv(rep); - if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) && - mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + + if (mlx5_devcom_comp_is_ready(esw->devcom) && + mlx5_devcom_for_each_peer_begin(esw->devcom)) devcom_locked = true; for (i = 0; i < sqns_num; i++) { @@ -477,7 +474,7 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, xa_init(&rep_sq->sq_peer); if (devcom_locked) { - err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i); + err = mlx5e_sqs2vport_add_peers_rules(esw, rep, rep_sq, i); if (err) { mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); xa_destroy(&rep_sq->sq_peer); @@ -490,7 +487,7 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, } if (devcom_locked) - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(esw->devcom); return 0; @@ -498,7 +495,7 @@ out_err: mlx5e_sqs2vport_stop(esw, rep); if (devcom_locked) - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(esw->devcom); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 8d0a3f69693e..22bc88620653 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1668,11 +1668,10 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro { struct mlx5e_priv *out_priv, *route_priv; struct mlx5_core_dev *route_mdev; - struct mlx5_devcom *devcom; + struct mlx5_devcom_comp_dev *pos; struct mlx5_eswitch *esw; u16 vhca_id; int err; - int i; out_priv = netdev_priv(out_dev); esw = out_priv->mdev->priv.eswitch; @@ -1688,10 +1687,8 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro return err; rcu_read_lock(); - devcom = out_priv->mdev->priv.devcom; err = -ENODEV; - mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS, - esw, i) { + mlx5_devcom_for_each_peer_entry_rcu(esw->devcom, esw, pos) { err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); if (!err) break; @@ -2031,15 +2028,15 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { if (mlx5e_is_eswitch_flow(flow)) { - struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom; + struct mlx5_devcom_comp_dev *devcom = flow->priv->mdev->priv.eswitch->devcom; - if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + if (!mlx5_devcom_for_each_peer_begin(devcom)) { mlx5e_tc_del_fdb_flow(priv, flow); return; } mlx5e_tc_del_fdb_peers_flow(flow); - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom); mlx5e_tc_del_fdb_flow(priv, flow); } else { mlx5e_tc_del_nic_flow(priv, flow); @@ -4216,8 +4213,7 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) flow_flag_test(flow, INGRESS); bool act_is_encap = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); - bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS); + bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.eswitch->devcom); if (!esw_paired) return false; @@ -4471,14 +4467,13 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { - struct mlx5_devcom *devcom = priv->mdev->priv.devcom; + struct mlx5_devcom_comp_dev *devcom = priv->mdev->priv.eswitch->devcom, *pos; struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *in_rep = rpriv->rep; struct mlx5_core_dev *in_mdev = priv->mdev; struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; int err; - int i; flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, in_mdev); @@ -4490,27 +4485,25 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, return 0; } - if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + if (!mlx5_devcom_for_each_peer_begin(devcom)) { err = -ENODEV; goto clean_flow; } - mlx5_devcom_for_each_peer_entry(devcom, - MLX5_DEVCOM_ESW_OFFLOADS, - peer_esw, i) { + mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw); if (err) goto peer_clean; } - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom); *__flow = flow; return 0; peer_clean: mlx5e_tc_del_fdb_peers_flow(flow); - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom); clean_flow: mlx5e_tc_del_fdb_flow(priv, flow); return err; @@ -4728,7 +4721,7 @@ int mlx5e_tc_fill_action_stats(struct mlx5e_priv *priv, int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, struct flow_cls_offload *f, unsigned long flags) { - struct mlx5_devcom *devcom = priv->mdev->priv.devcom; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct rhashtable *tc_ht = get_tc_ht(priv, flags); struct mlx5e_tc_flow *flow; struct mlx5_fc *counter; @@ -4764,7 +4757,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, /* Under multipath it's possible for one rule to be currently * un-offloaded while the other rule is offloaded. */ - if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + if (esw && !mlx5_devcom_for_each_peer_begin(esw->devcom)) goto out; if (flow_flag_test(flow, DUP)) { @@ -4795,7 +4788,8 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, } no_peer_counter: - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + if (esw) + mlx5_devcom_for_each_peer_end(esw->devcom); out: flow_stats_update(&f->stats, bytes, packets, 0, lastuse, FLOW_ACTION_HW_STATS_DELAYED); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c index f4fe1daa4afd..e36294b7ade2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c @@ -652,30 +652,30 @@ mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_vlan *vlan, u32 counter_id, struct mlx5_esw_bridge *bridge) { - struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_devcom_comp_dev *devcom = bridge->br_offloads->esw->devcom, *pos; struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - int i; - if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + if (!mlx5_devcom_for_each_peer_begin(devcom)) return ERR_PTR(-ENODEV); - mlx5_devcom_for_each_peer_entry(devcom, - MLX5_DEVCOM_ESW_OFFLOADS, - tmp, i) { + mlx5_devcom_for_each_peer_entry(devcom, tmp, pos) { if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) { peer_esw = tmp; break; } } + if (!peer_esw) { - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - return ERR_PTR(-ENODEV); + handle = ERR_PTR(-ENODEV); + goto out; } handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id, bridge, peer_esw); - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + +out: + mlx5_devcom_for_each_peer_end(devcom); return handle; } @@ -1391,8 +1391,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow mlx5_fc_id(counter), bridge); if (IS_ERR(handle)) { err = PTR_ERR(handle); - esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d)\n", - vport_num, err); + esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d,peer=%d)\n", + vport_num, err, peer); goto err_ingress_flow_create; } entry->ingress_handle = handle; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c index 2455f8b93c1e..7a01714b3780 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c @@ -539,30 +539,29 @@ mlx5_esw_bridge_mcast_filter_flow_create(struct mlx5_esw_bridge_port *port) static struct mlx5_flow_handle * mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port) { - struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_devcom_comp_dev *devcom = port->bridge->br_offloads->esw->devcom, *pos; struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - int i; - if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + if (!mlx5_devcom_for_each_peer_begin(devcom)) return ERR_PTR(-ENODEV); - mlx5_devcom_for_each_peer_entry(devcom, - MLX5_DEVCOM_ESW_OFFLOADS, - tmp, i) { + mlx5_devcom_for_each_peer_entry(devcom, tmp, pos) { if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) { peer_esw = tmp; break; } } + if (!peer_esw) { - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - return ERR_PTR(-ENODEV); + handle = ERR_PTR(-ENODEV); + goto out; } handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw); - mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); +out: + mlx5_devcom_for_each_peer_end(devcom); return handle; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index ae0dc8a3060d..6d9378b0bce5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -354,6 +354,7 @@ struct mlx5_eswitch { } params; struct blocking_notifier_head n_head; struct xarray paired; + struct mlx5_devcom_comp_dev *devcom; }; void esw_offloads_disable(struct mlx5_eswitch *esw); @@ -383,6 +384,7 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw); void mlx5_eswitch_disable(struct mlx5_eswitch *esw); void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw); void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw); +bool mlx5_esw_offloads_devcom_is_ready(struct mlx5_eswitch *esw); int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, u16 vport, const u8 *mac); int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, @@ -818,6 +820,7 @@ static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool cle static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {} static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {} static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {} +static inline bool mlx5_esw_offloads_devcom_is_ready(struct mlx5_eswitch *esw) { return false; } static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; } static inline int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index bdfe609cc9ec..11cce630c1b8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2811,7 +2811,6 @@ static int mlx5_esw_offloads_devcom_event(int event, void *event_data) { struct mlx5_eswitch *esw = my_data; - struct mlx5_devcom *devcom = esw->dev->priv.devcom; struct mlx5_eswitch *peer_esw = event_data; u16 esw_i, peer_esw_i; bool esw_paired; @@ -2833,6 +2832,7 @@ static int mlx5_esw_offloads_devcom_event(int event, err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true); if (err) goto err_out; + err = mlx5_esw_offloads_pair(esw, peer_esw); if (err) goto err_peer; @@ -2851,7 +2851,7 @@ static int mlx5_esw_offloads_devcom_event(int event, esw->num_peers++; peer_esw->num_peers++; - mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); + mlx5_devcom_comp_set_ready(esw->devcom, true); break; case ESW_OFFLOADS_DEVCOM_UNPAIR: @@ -2861,7 +2861,7 @@ static int mlx5_esw_offloads_devcom_event(int event, peer_esw->num_peers--; esw->num_peers--; if (!esw->num_peers && !peer_esw->num_peers) - mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); + mlx5_devcom_comp_set_ready(esw->devcom, false); xa_erase(&peer_esw->paired, esw_i); xa_erase(&esw->paired, peer_esw_i); mlx5_esw_offloads_unpair(peer_esw, esw); @@ -2888,7 +2888,7 @@ err_out: void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) { - struct mlx5_devcom *devcom = esw->dev->priv.devcom; + u64 guid; int i; for (i = 0; i < MLX5_MAX_PORTS; i++) @@ -2902,34 +2902,41 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) return; xa_init(&esw->paired); - mlx5_devcom_register_component(devcom, - MLX5_DEVCOM_ESW_OFFLOADS, - mlx5_esw_offloads_devcom_event, - esw); + guid = mlx5_query_nic_system_image_guid(esw->dev); esw->num_peers = 0; - mlx5_devcom_send_event(devcom, - MLX5_DEVCOM_ESW_OFFLOADS, + esw->devcom = mlx5_devcom_register_component(esw->dev->priv.devc, + MLX5_DEVCOM_ESW_OFFLOADS, + guid, + mlx5_esw_offloads_devcom_event, + esw); + if (IS_ERR_OR_NULL(esw->devcom)) + return; + + mlx5_devcom_send_event(esw->devcom, ESW_OFFLOADS_DEVCOM_PAIR, - ESW_OFFLOADS_DEVCOM_UNPAIR, esw); + ESW_OFFLOADS_DEVCOM_UNPAIR, + esw); } void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) { - struct mlx5_devcom *devcom = esw->dev->priv.devcom; - - if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) + if (IS_ERR_OR_NULL(esw->devcom)) return; - if (!mlx5_lag_is_supported(esw->dev)) - return; - - mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + mlx5_devcom_send_event(esw->devcom, + ESW_OFFLOADS_DEVCOM_UNPAIR, ESW_OFFLOADS_DEVCOM_UNPAIR, - ESW_OFFLOADS_DEVCOM_UNPAIR, esw); + esw); - mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_unregister_component(esw->devcom); xa_destroy(&esw->paired); + esw->devcom = NULL; +} + +bool mlx5_esw_offloads_devcom_is_ready(struct mlx5_eswitch *esw) +{ + return mlx5_devcom_comp_is_ready(esw->devcom); } bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 900a18883f28..af3fac090b82 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -835,7 +835,7 @@ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) dev = ldev->pf[MLX5_LAG_P1].dev; if (is_mdev_switchdev_mode(dev) && mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && - mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) && + mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) && MLX5_CAP_ESW(dev, esw_shared_ingress_acl) && mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1) return true; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index 78c94b22bdc0..feb62d952643 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -2,214 +2,273 @@ /* Copyright (c) 2018 Mellanox Technologies */ #include +#include #include "lib/devcom.h" #include "mlx5_core.h" -static LIST_HEAD(devcom_list); +static LIST_HEAD(devcom_dev_list); +static LIST_HEAD(devcom_comp_list); +/* protect device list */ +static DEFINE_MUTEX(dev_list_lock); +/* protect component list */ +static DEFINE_MUTEX(comp_list_lock); -#define devcom_for_each_component(priv, comp, iter) \ - for (iter = 0; \ - comp = &(priv)->components[iter], iter < MLX5_DEVCOM_NUM_COMPONENTS; \ - iter++) +#define devcom_for_each_component(iter) \ + list_for_each_entry(iter, &devcom_comp_list, comp_list) -struct mlx5_devcom_component { - struct { - void __rcu *data; - } device[MLX5_DEVCOM_PORTS_SUPPORTED]; +struct mlx5_devcom_dev { + struct list_head list; + struct mlx5_core_dev *dev; + struct kref ref; +}; +struct mlx5_devcom_comp { + struct list_head comp_list; + enum mlx5_devcom_component id; + u64 key; + struct list_head comp_dev_list_head; mlx5_devcom_event_handler_t handler; - struct rw_semaphore sem; + struct kref ref; bool ready; + struct rw_semaphore sem; }; -struct mlx5_devcom_list { +struct mlx5_devcom_comp_dev { struct list_head list; - - struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS]; - struct mlx5_core_dev *devs[MLX5_DEVCOM_PORTS_SUPPORTED]; + struct mlx5_devcom_comp *comp; + struct mlx5_devcom_dev *devc; + void __rcu *data; }; -struct mlx5_devcom { - struct mlx5_devcom_list *priv; - int idx; -}; - -static struct mlx5_devcom_list *mlx5_devcom_list_alloc(void) +static bool devcom_dev_exists(struct mlx5_core_dev *dev) { - struct mlx5_devcom_component *comp; - struct mlx5_devcom_list *priv; - int i; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return NULL; + struct mlx5_devcom_dev *iter; - devcom_for_each_component(priv, comp, i) - init_rwsem(&comp->sem); + list_for_each_entry(iter, &devcom_dev_list, list) + if (iter->dev == dev) + return true; - return priv; + return false; } -static struct mlx5_devcom *mlx5_devcom_alloc(struct mlx5_devcom_list *priv, - u8 idx) +static struct mlx5_devcom_dev * +mlx5_devcom_dev_alloc(struct mlx5_core_dev *dev) { - struct mlx5_devcom *devcom; + struct mlx5_devcom_dev *devc; - devcom = kzalloc(sizeof(*devcom), GFP_KERNEL); - if (!devcom) + devc = kzalloc(sizeof(*devc), GFP_KERNEL); + if (!devc) return NULL; - devcom->priv = priv; - devcom->idx = idx; - return devcom; + devc->dev = dev; + kref_init(&devc->ref); + return devc; } -/* Must be called with intf_mutex held */ -struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) +struct mlx5_devcom_dev * +mlx5_devcom_register_device(struct mlx5_core_dev *dev) { - struct mlx5_devcom_list *priv = NULL, *iter; - struct mlx5_devcom *devcom = NULL; - bool new_priv = false; - u64 sguid0, sguid1; - int idx, i; - - if (!mlx5_core_is_pf(dev)) - return NULL; - if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED) - return NULL; - - mlx5_dev_list_lock(); - sguid0 = mlx5_query_nic_system_image_guid(dev); - list_for_each_entry(iter, &devcom_list, list) { - /* There is at least one device in iter */ - struct mlx5_core_dev *tmp_dev; - - idx = -1; - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { - if (iter->devs[i]) - tmp_dev = iter->devs[i]; - else - idx = i; - } - - if (idx == -1) - continue; - - sguid1 = mlx5_query_nic_system_image_guid(tmp_dev); - if (sguid0 != sguid1) - continue; - - priv = iter; - break; - } + struct mlx5_devcom_dev *devc; - if (!priv) { - priv = mlx5_devcom_list_alloc(); - if (!priv) { - devcom = ERR_PTR(-ENOMEM); - goto out; - } + mutex_lock(&dev_list_lock); - idx = 0; - new_priv = true; + if (devcom_dev_exists(dev)) { + devc = ERR_PTR(-EEXIST); + goto out; } - priv->devs[idx] = dev; - devcom = mlx5_devcom_alloc(priv, idx); - if (!devcom) { - if (new_priv) - kfree(priv); - devcom = ERR_PTR(-ENOMEM); + devc = mlx5_devcom_dev_alloc(dev); + if (!devc) { + devc = ERR_PTR(-ENOMEM); goto out; } - if (new_priv) - list_add(&priv->list, &devcom_list); + list_add_tail(&devc->list, &devcom_dev_list); out: - mlx5_dev_list_unlock(); - return devcom; + mutex_unlock(&dev_list_lock); + return devc; } -/* Must be called with intf_mutex held */ -void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom) +static void +mlx5_devcom_dev_release(struct kref *ref) { - struct mlx5_devcom_list *priv; - int i; + struct mlx5_devcom_dev *devc = container_of(ref, struct mlx5_devcom_dev, ref); - if (IS_ERR_OR_NULL(devcom)) - return; + mutex_lock(&dev_list_lock); + list_del(&devc->list); + mutex_unlock(&dev_list_lock); + kfree(devc); +} - mlx5_dev_list_lock(); - priv = devcom->priv; - priv->devs[devcom->idx] = NULL; +void mlx5_devcom_unregister_device(struct mlx5_devcom_dev *devc) +{ + if (!IS_ERR_OR_NULL(devc)) + kref_put(&devc->ref, mlx5_devcom_dev_release); +} - kfree(devcom); +static struct mlx5_devcom_comp * +mlx5_devcom_comp_alloc(u64 id, u64 key, mlx5_devcom_event_handler_t handler) +{ + struct mlx5_devcom_comp *comp; - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) - if (priv->devs[i]) - break; + comp = kzalloc(sizeof(*comp), GFP_KERNEL); + if (!comp) + return ERR_PTR(-ENOMEM); - if (i != MLX5_DEVCOM_PORTS_SUPPORTED) - goto out; + comp->id = id; + comp->key = key; + comp->handler = handler; + init_rwsem(&comp->sem); + kref_init(&comp->ref); + INIT_LIST_HEAD(&comp->comp_dev_list_head); - list_del(&priv->list); - kfree(priv); -out: - mlx5_dev_list_unlock(); + return comp; } -void mlx5_devcom_register_component(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - mlx5_devcom_event_handler_t handler, - void *data) +static void +mlx5_devcom_comp_release(struct kref *ref) { - struct mlx5_devcom_component *comp; + struct mlx5_devcom_comp *comp = container_of(ref, struct mlx5_devcom_comp, ref); - if (IS_ERR_OR_NULL(devcom)) - return; + mutex_lock(&comp_list_lock); + list_del(&comp->comp_list); + mutex_unlock(&comp_list_lock); + kfree(comp); +} + +static struct mlx5_devcom_comp_dev * +devcom_alloc_comp_dev(struct mlx5_devcom_dev *devc, + struct mlx5_devcom_comp *comp, + void *data) +{ + struct mlx5_devcom_comp_dev *devcom; - WARN_ON(!data); + devcom = kzalloc(sizeof(*devcom), GFP_KERNEL); + if (!devcom) + return ERR_PTR(-ENOMEM); + + kref_get(&devc->ref); + devcom->devc = devc; + devcom->comp = comp; + rcu_assign_pointer(devcom->data, data); - comp = &devcom->priv->components[id]; down_write(&comp->sem); - comp->handler = handler; - rcu_assign_pointer(comp->device[devcom->idx].data, data); + list_add_tail(&devcom->list, &comp->comp_dev_list_head); up_write(&comp->sem); + + return devcom; } -void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +static void +devcom_free_comp_dev(struct mlx5_devcom_comp_dev *devcom) { - struct mlx5_devcom_component *comp; - - if (IS_ERR_OR_NULL(devcom)) - return; + struct mlx5_devcom_comp *comp = devcom->comp; - comp = &devcom->priv->components[id]; down_write(&comp->sem); - RCU_INIT_POINTER(comp->device[devcom->idx].data, NULL); + list_del(&devcom->list); up_write(&comp->sem); - synchronize_rcu(); + + kref_put(&devcom->devc->ref, mlx5_devcom_dev_release); + kfree(devcom); + kref_put(&comp->ref, mlx5_devcom_comp_release); } -int mlx5_devcom_send_event(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, +static bool +devcom_component_equal(struct mlx5_devcom_comp *devcom, + enum mlx5_devcom_component id, + u64 key) +{ + return devcom->id == id && devcom->key == key; +} + +static struct mlx5_devcom_comp * +devcom_component_get(struct mlx5_devcom_dev *devc, + enum mlx5_devcom_component id, + u64 key, + mlx5_devcom_event_handler_t handler) +{ + struct mlx5_devcom_comp *comp; + + devcom_for_each_component(comp) { + if (devcom_component_equal(comp, id, key)) { + if (handler == comp->handler) { + kref_get(&comp->ref); + return comp; + } + + mlx5_core_err(devc->dev, + "Cannot register existing devcom component with different handler\n"); + return ERR_PTR(-EINVAL); + } + } + + return NULL; +} + +struct mlx5_devcom_comp_dev * +mlx5_devcom_register_component(struct mlx5_devcom_dev *devc, + enum mlx5_devcom_component id, + u64 key, + mlx5_devcom_event_handler_t handler, + void *data) +{ + struct mlx5_devcom_comp_dev *devcom; + struct mlx5_devcom_comp *comp; + + if (IS_ERR_OR_NULL(devc)) + return NULL; + + mutex_lock(&comp_list_lock); + comp = devcom_component_get(devc, id, key, handler); + if (IS_ERR(comp)) { + devcom = ERR_PTR(-EINVAL); + goto out_unlock; + } + + if (!comp) { + comp = mlx5_devcom_comp_alloc(id, key, handler); + if (IS_ERR(comp)) { + devcom = ERR_CAST(comp); + goto out_unlock; + } + list_add_tail(&comp->comp_list, &devcom_comp_list); + } + mutex_unlock(&comp_list_lock); + + devcom = devcom_alloc_comp_dev(devc, comp, data); + if (IS_ERR(devcom)) + kref_put(&comp->ref, mlx5_devcom_comp_release); + + return devcom; + +out_unlock: + mutex_unlock(&comp_list_lock); + return devcom; +} + +void mlx5_devcom_unregister_component(struct mlx5_devcom_comp_dev *devcom) +{ + if (!IS_ERR_OR_NULL(devcom)) + devcom_free_comp_dev(devcom); +} + +int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, int event, int rollback_event, void *event_data) { - struct mlx5_devcom_component *comp; - int err = -ENODEV, i; + struct mlx5_devcom_comp *comp = devcom->comp; + struct mlx5_devcom_comp_dev *pos; + int err = 0; + void *data; if (IS_ERR_OR_NULL(devcom)) - return err; + return -ENODEV; - comp = &devcom->priv->components[id]; down_write(&comp->sem); - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { - void *data = rcu_dereference_protected(comp->device[i].data, - lockdep_is_held(&comp->sem)); + list_for_each_entry(pos, &comp->comp_dev_list_head, list) { + data = rcu_dereference_protected(pos->data, lockdep_is_held(&comp->sem)); - if (i != devcom->idx && data) { + if (pos != devcom && data) { err = comp->handler(event, data, event_data); if (err) goto rollback; @@ -220,48 +279,43 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom, return 0; rollback: - while (i--) { - void *data = rcu_dereference_protected(comp->device[i].data, - lockdep_is_held(&comp->sem)); + if (list_entry_is_head(pos, &comp->comp_dev_list_head, list)) + goto out; + pos = list_prev_entry(pos, list); + list_for_each_entry_from_reverse(pos, &comp->comp_dev_list_head, list) { + data = rcu_dereference_protected(pos->data, lockdep_is_held(&comp->sem)); - if (i != devcom->idx && data) + if (pos != devcom && data) comp->handler(rollback_event, data, event_data); } - +out: up_write(&comp->sem); return err; } -void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool ready) +void mlx5_devcom_comp_set_ready(struct mlx5_devcom_comp_dev *devcom, bool ready) { - struct mlx5_devcom_component *comp; - - comp = &devcom->priv->components[id]; - WARN_ON(!rwsem_is_locked(&comp->sem)); + WARN_ON(!rwsem_is_locked(&devcom->comp->sem)); - WRITE_ONCE(comp->ready, ready); + WRITE_ONCE(devcom->comp->ready, ready); } -bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom_comp_dev *devcom) { if (IS_ERR_OR_NULL(devcom)) return false; - return READ_ONCE(devcom->priv->components[id].ready); + return READ_ONCE(devcom->comp->ready); } -bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom_comp_dev *devcom) { - struct mlx5_devcom_component *comp; + struct mlx5_devcom_comp *comp; if (IS_ERR_OR_NULL(devcom)) return false; - comp = &devcom->priv->components[id]; + comp = devcom->comp; down_read(&comp->sem); if (!READ_ONCE(comp->ready)) { up_read(&comp->sem); @@ -271,74 +325,60 @@ bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, return true; } -void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom_comp_dev *devcom) { - struct mlx5_devcom_component *comp = &devcom->priv->components[id]; - - up_read(&comp->sem); + up_read(&devcom->comp->sem); } -void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - int *i) +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom_comp_dev *devcom, + struct mlx5_devcom_comp_dev **pos) { - struct mlx5_devcom_component *comp; - void *ret; - int idx; + struct mlx5_devcom_comp *comp = devcom->comp; + struct mlx5_devcom_comp_dev *tmp; + void *data; - comp = &devcom->priv->components[id]; + tmp = list_prepare_entry(*pos, &comp->comp_dev_list_head, list); - if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) - return NULL; - for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { - if (idx != devcom->idx) { - ret = rcu_dereference_protected(comp->device[idx].data, - lockdep_is_held(&comp->sem)); - if (ret) + list_for_each_entry_continue(tmp, &comp->comp_dev_list_head, list) { + if (tmp != devcom) { + data = rcu_dereference_protected(tmp->data, lockdep_is_held(&comp->sem)); + if (data) break; } } - if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { - *i = idx; + if (list_entry_is_head(tmp, &comp->comp_dev_list_head, list)) return NULL; - } - *i = idx + 1; - return ret; + *pos = tmp; + return data; } -void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - int *i) +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom_comp_dev *devcom, + struct mlx5_devcom_comp_dev **pos) { - struct mlx5_devcom_component *comp; - void *ret; - int idx; + struct mlx5_devcom_comp *comp = devcom->comp; + struct mlx5_devcom_comp_dev *tmp; + void *data; - comp = &devcom->priv->components[id]; + tmp = list_prepare_entry(*pos, &comp->comp_dev_list_head, list); - if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) - return NULL; - for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { - if (idx != devcom->idx) { + list_for_each_entry_continue(tmp, &comp->comp_dev_list_head, list) { + if (tmp != devcom) { /* This can change concurrently, however 'data' pointer will remain * valid for the duration of RCU read section. */ if (!READ_ONCE(comp->ready)) return NULL; - ret = rcu_dereference(comp->device[idx].data); - if (ret) + data = rcu_dereference(tmp->data); + if (data) break; } } - if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { - *i = idx; + if (list_entry_is_head(tmp, &comp->comp_dev_list_head, list)) return NULL; - } - *i = idx + 1; - return ret; + *pos = tmp; + return data; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h index d953a01b8eaa..8389ac0af708 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h @@ -6,11 +6,8 @@ #include -#define MLX5_DEVCOM_PORTS_SUPPORTED 4 - -enum mlx5_devcom_components { +enum mlx5_devcom_component { MLX5_DEVCOM_ESW_OFFLOADS, - MLX5_DEVCOM_NUM_COMPONENTS, }; @@ -18,45 +15,40 @@ typedef int (*mlx5_devcom_event_handler_t)(int event, void *my_data, void *event_data); -struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev); -void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom); +struct mlx5_devcom_dev *mlx5_devcom_register_device(struct mlx5_core_dev *dev); +void mlx5_devcom_unregister_device(struct mlx5_devcom_dev *devc); -void mlx5_devcom_register_component(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - mlx5_devcom_event_handler_t handler, - void *data); -void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); +struct mlx5_devcom_comp_dev * +mlx5_devcom_register_component(struct mlx5_devcom_dev *devc, + enum mlx5_devcom_component id, + u64 key, + mlx5_devcom_event_handler_t handler, + void *data); +void mlx5_devcom_unregister_component(struct mlx5_devcom_comp_dev *devcom); -int mlx5_devcom_send_event(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, +int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, int event, int rollback_event, void *event_data); -void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool ready); -bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); - -bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); -void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); -void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, int *i); - -#define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \ - for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \ - data; \ - data = mlx5_devcom_get_next_peer_data(devcom, id, &i)) - -void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, int *i); - -#define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \ - for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \ - data; \ - data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i)) - -#endif +void mlx5_devcom_comp_set_ready(struct mlx5_devcom_comp_dev *devcom, bool ready); +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom_comp_dev *devcom); + +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom_comp_dev *devcom); +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom_comp_dev *devcom); +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom_comp_dev *devcom, + struct mlx5_devcom_comp_dev **pos); + +#define mlx5_devcom_for_each_peer_entry(devcom, data, pos) \ + for (pos = NULL, data = mlx5_devcom_get_next_peer_data(devcom, &pos); \ + data; \ + data = mlx5_devcom_get_next_peer_data(devcom, &pos)) + +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom_comp_dev *devcom, + struct mlx5_devcom_comp_dev **pos); + +#define mlx5_devcom_for_each_peer_entry_rcu(devcom, data, pos) \ + for (pos = NULL, data = mlx5_devcom_get_next_peer_data_rcu(devcom, &pos); \ + data; \ + data = mlx5_devcom_get_next_peer_data_rcu(devcom, &pos)) + +#endif /* __LIB_MLX5_DEVCOM_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 88dbea6631d5..a79c9b8286a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -951,10 +951,10 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) { int err; - dev->priv.devcom = mlx5_devcom_register_device(dev); - if (IS_ERR(dev->priv.devcom)) - mlx5_core_err(dev, "failed to register with devcom (0x%p)\n", - dev->priv.devcom); + dev->priv.devc = mlx5_devcom_register_device(dev); + if (IS_ERR(dev->priv.devc)) + mlx5_core_warn(dev, "failed to register devcom device %ld\n", + PTR_ERR(dev->priv.devc)); err = mlx5_query_board_id(dev); if (err) { @@ -1089,7 +1089,7 @@ err_eq_cleanup: err_irq_cleanup: mlx5_irq_table_cleanup(dev); err_devcom: - mlx5_devcom_unregister_device(dev->priv.devcom); + mlx5_devcom_unregister_device(dev->priv.devc); return err; } @@ -1118,7 +1118,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) mlx5_events_cleanup(dev); mlx5_eq_table_cleanup(dev); mlx5_irq_table_cleanup(dev); - mlx5_devcom_unregister_device(dev->priv.devcom); + mlx5_devcom_unregister_device(dev->priv.devc); } static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout) -- cgit From 1161d22ded072335c950723af2f21fd52ba47cbb Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Mon, 22 May 2023 18:16:50 +0300 Subject: net/mlx5e: E-Switch, Register devcom device with switch id key Register devcom devices with switch id instead of guid. Devcom interface is used to sync between ports in the eswitch, e.g. Adding miss rules between the ports. New eswitch devices could have the same guid but a different switch id so its more correct to group according to switch id which is the identifier if the ports are on the same eswitch. Signed-off-by: Roi Dayan Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 9 +++++++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 7 ++----- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 22bc88620653..507825a1abc8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -5194,11 +5194,12 @@ void mlx5e_tc_ht_cleanup(struct rhashtable *tc_ht) int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) { const size_t sz_enc_opts = sizeof(struct tunnel_match_enc_opts); + struct netdev_phys_item_id ppid; struct mlx5e_rep_priv *rpriv; struct mapping_ctx *mapping; struct mlx5_eswitch *esw; struct mlx5e_priv *priv; - u64 mapping_id; + u64 mapping_id, key; int err = 0; rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv); @@ -5252,7 +5253,11 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) goto err_action_counter; } - mlx5_esw_offloads_devcom_init(esw); + err = dev_get_port_parent_id(priv->netdev, &ppid, false); + if (!err) { + memcpy(&key, &ppid.id, sizeof(key)); + mlx5_esw_offloads_devcom_init(esw, key); + } return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 6d9378b0bce5..9b5a1651b877 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -382,7 +382,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs); void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf); void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw); void mlx5_eswitch_disable(struct mlx5_eswitch *esw); -void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw); +void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key); void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw); bool mlx5_esw_offloads_devcom_is_ready(struct mlx5_eswitch *esw); int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, @@ -818,7 +818,7 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {} static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; } static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) {} static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {} -static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {} +static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key) {} static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {} static inline bool mlx5_esw_offloads_devcom_is_ready(struct mlx5_eswitch *esw) { return false; } static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 11cce630c1b8..7d100cd4afab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2886,9 +2886,8 @@ err_out: return err; } -void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) +void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key) { - u64 guid; int i; for (i = 0; i < MLX5_MAX_PORTS; i++) @@ -2902,12 +2901,10 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) return; xa_init(&esw->paired); - guid = mlx5_query_nic_system_image_guid(esw->dev); - esw->num_peers = 0; esw->devcom = mlx5_devcom_register_component(esw->dev->priv.devc, MLX5_DEVCOM_ESW_OFFLOADS, - guid, + key, mlx5_esw_offloads_devcom_event, esw); if (IS_ERR_OR_NULL(esw->devcom)) -- cgit From e2bb7984719bb1138e955ba3bbafd3a16d1cb8e3 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 23 May 2023 11:50:17 +0300 Subject: net/mlx5e: E-Switch, Allow devcom initialization on more vports New features could use the devcom interface but not necessarily the lag feature although for vport managers and ECPF still check for lag support. Signed-off-by: Roi Dayan Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 7d100cd4afab..b4b8cb788573 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2897,7 +2897,8 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key) if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) return; - if (!mlx5_lag_is_supported(esw->dev)) + if ((MLX5_VPORT_MANAGER(esw->dev) || mlx5_core_is_ecpf_esw_manager(esw->dev)) && + !mlx5_lag_is_supported(esw->dev)) return; xa_init(&esw->paired); -- cgit From 58db72869a9f8e01910844ca145efc2ea91bbbf9 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Wed, 18 Jan 2023 16:52:17 +0200 Subject: net/mlx5: Re-organize mlx5_cmd struct Downstream patch will split mlx5_cmd_init() to probe and reload routines. As a preparation, organize mlx5_cmd struct so that any field that will be used in the reload routine are grouped at new nested struct. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 94 +++++++++++------------ drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 4 +- 2 files changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index d532883b42d7..f175af528fe0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -162,18 +162,18 @@ static int cmd_alloc_index(struct mlx5_cmd *cmd) int ret; spin_lock_irqsave(&cmd->alloc_lock, flags); - ret = find_first_bit(&cmd->bitmask, cmd->max_reg_cmds); - if (ret < cmd->max_reg_cmds) - clear_bit(ret, &cmd->bitmask); + ret = find_first_bit(&cmd->vars.bitmask, cmd->vars.max_reg_cmds); + if (ret < cmd->vars.max_reg_cmds) + clear_bit(ret, &cmd->vars.bitmask); spin_unlock_irqrestore(&cmd->alloc_lock, flags); - return ret < cmd->max_reg_cmds ? ret : -ENOMEM; + return ret < cmd->vars.max_reg_cmds ? ret : -ENOMEM; } static void cmd_free_index(struct mlx5_cmd *cmd, int idx) { lockdep_assert_held(&cmd->alloc_lock); - set_bit(idx, &cmd->bitmask); + set_bit(idx, &cmd->vars.bitmask); } static void cmd_ent_get(struct mlx5_cmd_work_ent *ent) @@ -192,7 +192,7 @@ static void cmd_ent_put(struct mlx5_cmd_work_ent *ent) if (ent->idx >= 0) { cmd_free_index(cmd, ent->idx); - up(ent->page_queue ? &cmd->pages_sem : &cmd->sem); + up(ent->page_queue ? &cmd->vars.pages_sem : &cmd->vars.sem); } cmd_free_ent(ent); @@ -202,7 +202,7 @@ out: static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx) { - return cmd->cmd_buf + (idx << cmd->log_stride); + return cmd->cmd_buf + (idx << cmd->vars.log_stride); } static int mlx5_calc_cmd_blocks(struct mlx5_cmd_msg *msg) @@ -974,7 +974,7 @@ static void cmd_work_handler(struct work_struct *work) cb_timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD)); complete(&ent->handling); - sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + sem = ent->page_queue ? &cmd->vars.pages_sem : &cmd->vars.sem; down(sem); if (!ent->page_queue) { alloc_ret = cmd_alloc_index(cmd); @@ -994,9 +994,9 @@ static void cmd_work_handler(struct work_struct *work) } ent->idx = alloc_ret; } else { - ent->idx = cmd->max_reg_cmds; + ent->idx = cmd->vars.max_reg_cmds; spin_lock_irqsave(&cmd->alloc_lock, flags); - clear_bit(ent->idx, &cmd->bitmask); + clear_bit(ent->idx, &cmd->vars.bitmask); spin_unlock_irqrestore(&cmd->alloc_lock, flags); } @@ -1572,15 +1572,15 @@ void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode) struct mlx5_cmd *cmd = &dev->cmd; int i; - for (i = 0; i < cmd->max_reg_cmds; i++) - down(&cmd->sem); - down(&cmd->pages_sem); + for (i = 0; i < cmd->vars.max_reg_cmds; i++) + down(&cmd->vars.sem); + down(&cmd->vars.pages_sem); cmd->allowed_opcode = opcode; - up(&cmd->pages_sem); - for (i = 0; i < cmd->max_reg_cmds; i++) - up(&cmd->sem); + up(&cmd->vars.pages_sem); + for (i = 0; i < cmd->vars.max_reg_cmds; i++) + up(&cmd->vars.sem); } static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) @@ -1588,15 +1588,15 @@ static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) struct mlx5_cmd *cmd = &dev->cmd; int i; - for (i = 0; i < cmd->max_reg_cmds; i++) - down(&cmd->sem); - down(&cmd->pages_sem); + for (i = 0; i < cmd->vars.max_reg_cmds; i++) + down(&cmd->vars.sem); + down(&cmd->vars.pages_sem); cmd->mode = mode; - up(&cmd->pages_sem); - for (i = 0; i < cmd->max_reg_cmds; i++) - up(&cmd->sem); + up(&cmd->vars.pages_sem); + for (i = 0; i < cmd->vars.max_reg_cmds; i++) + up(&cmd->vars.sem); } static int cmd_comp_notifier(struct notifier_block *nb, @@ -1655,7 +1655,7 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force /* there can be at most 32 command queues */ vector = vec & 0xffffffff; - for (i = 0; i < (1 << cmd->log_sz); i++) { + for (i = 0; i < (1 << cmd->vars.log_sz); i++) { if (test_bit(i, &vector)) { ent = cmd->ent_arr[i]; @@ -1744,7 +1744,7 @@ static void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev) /* wait for pending handlers to complete */ mlx5_eq_synchronize_cmd_irq(dev); spin_lock_irqsave(&dev->cmd.alloc_lock, flags); - vector = ~dev->cmd.bitmask & ((1ul << (1 << dev->cmd.log_sz)) - 1); + vector = ~dev->cmd.vars.bitmask & ((1ul << (1 << dev->cmd.vars.log_sz)) - 1); if (!vector) goto no_trig; @@ -1753,14 +1753,14 @@ static void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev) * to guarantee pending commands will not get freed in the meanwhile. * For that reason, it also has to be done inside the alloc_lock. */ - for_each_set_bit(i, &bitmask, (1 << cmd->log_sz)) + for_each_set_bit(i, &bitmask, (1 << cmd->vars.log_sz)) cmd_ent_get(cmd->ent_arr[i]); vector |= MLX5_TRIGGERED_CMD_COMP; spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); mlx5_core_dbg(dev, "vector 0x%llx\n", vector); mlx5_cmd_comp_handler(dev, vector, true); - for_each_set_bit(i, &bitmask, (1 << cmd->log_sz)) + for_each_set_bit(i, &bitmask, (1 << cmd->vars.log_sz)) cmd_ent_put(cmd->ent_arr[i]); return; @@ -1773,22 +1773,22 @@ void mlx5_cmd_flush(struct mlx5_core_dev *dev) struct mlx5_cmd *cmd = &dev->cmd; int i; - for (i = 0; i < cmd->max_reg_cmds; i++) { - while (down_trylock(&cmd->sem)) { + for (i = 0; i < cmd->vars.max_reg_cmds; i++) { + while (down_trylock(&cmd->vars.sem)) { mlx5_cmd_trigger_completions(dev); cond_resched(); } } - while (down_trylock(&cmd->pages_sem)) { + while (down_trylock(&cmd->vars.pages_sem)) { mlx5_cmd_trigger_completions(dev); cond_resched(); } /* Unlock cmdif */ - up(&cmd->pages_sem); - for (i = 0; i < cmd->max_reg_cmds; i++) - up(&cmd->sem); + up(&cmd->vars.pages_sem); + for (i = 0; i < cmd->vars.max_reg_cmds; i++) + up(&cmd->vars.sem); } static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, @@ -1858,7 +1858,7 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, /* atomic context may not sleep */ if (callback) return -EINVAL; - down(&dev->cmd.throttle_sem); + down(&dev->cmd.vars.throttle_sem); } pages_queue = is_manage_pages(in); @@ -1903,7 +1903,7 @@ out_in: free_msg(dev, inb); out_up: if (throttle_op) - up(&dev->cmd.throttle_sem); + up(&dev->cmd.vars.throttle_sem); return err; } @@ -2213,16 +2213,16 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) goto err_free_pool; cmd_l = ioread32be(&dev->iseg->cmdq_addr_l_sz) & 0xff; - cmd->log_sz = cmd_l >> 4 & 0xf; - cmd->log_stride = cmd_l & 0xf; - if (1 << cmd->log_sz > MLX5_MAX_COMMANDS) { + cmd->vars.log_sz = cmd_l >> 4 & 0xf; + cmd->vars.log_stride = cmd_l & 0xf; + if (1 << cmd->vars.log_sz > MLX5_MAX_COMMANDS) { mlx5_core_err(dev, "firmware reports too many outstanding commands %d\n", - 1 << cmd->log_sz); + 1 << cmd->vars.log_sz); err = -EINVAL; goto err_free_page; } - if (cmd->log_sz + cmd->log_stride > MLX5_ADAPTER_PAGE_SHIFT) { + if (cmd->vars.log_sz + cmd->vars.log_stride > MLX5_ADAPTER_PAGE_SHIFT) { mlx5_core_err(dev, "command queue size overflow\n"); err = -EINVAL; goto err_free_page; @@ -2230,13 +2230,13 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) cmd->state = MLX5_CMDIF_STATE_DOWN; cmd->checksum_disabled = 1; - cmd->max_reg_cmds = (1 << cmd->log_sz) - 1; - cmd->bitmask = (1UL << cmd->max_reg_cmds) - 1; + cmd->vars.max_reg_cmds = (1 << cmd->vars.log_sz) - 1; + cmd->vars.bitmask = (1UL << cmd->vars.max_reg_cmds) - 1; - cmd->cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; - if (cmd->cmdif_rev > CMD_IF_REV) { + cmd->vars.cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; + if (cmd->vars.cmdif_rev > CMD_IF_REV) { mlx5_core_err(dev, "driver does not support command interface version. driver %d, firmware %d\n", - CMD_IF_REV, cmd->cmdif_rev); + CMD_IF_REV, cmd->vars.cmdif_rev); err = -EOPNOTSUPP; goto err_free_page; } @@ -2246,9 +2246,9 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) for (i = 0; i < MLX5_CMD_OP_MAX; i++) spin_lock_init(&cmd->stats[i].lock); - sema_init(&cmd->sem, cmd->max_reg_cmds); - sema_init(&cmd->pages_sem, 1); - sema_init(&cmd->throttle_sem, DIV_ROUND_UP(cmd->max_reg_cmds, 2)); + sema_init(&cmd->vars.sem, cmd->vars.max_reg_cmds); + sema_init(&cmd->vars.pages_sem, 1); + sema_init(&cmd->vars.throttle_sem, DIV_ROUND_UP(cmd->vars.max_reg_cmds, 2)); cmd_h = (u32)((u64)(cmd->dma) >> 32); cmd_l = (u32)(cmd->dma); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 2138f28a2931..9a826fb3ca38 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -176,8 +176,8 @@ static ssize_t slots_read(struct file *filp, char __user *buf, size_t count, int ret; cmd = filp->private_data; - weight = bitmap_weight(&cmd->bitmask, cmd->max_reg_cmds); - field = cmd->max_reg_cmds - weight; + weight = bitmap_weight(&cmd->vars.bitmask, cmd->vars.max_reg_cmds); + field = cmd->vars.max_reg_cmds - weight; ret = snprintf(tbuf, sizeof(tbuf), "%d\n", field); return simple_read_from_buffer(buf, count, pos, tbuf, ret); } -- cgit From 0714ec9ea1f291447a925657e0808f34b8fbce2b Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Sun, 29 Jan 2023 12:08:30 +0200 Subject: net/mlx5: Remove redundant cmdif revision check mlx5 is checking the cmdif revision twice, for no reason. Remove the latter check. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index f175af528fe0..9ced943ebd0d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -2191,16 +2191,15 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) int align = roundup_pow_of_two(size); struct mlx5_cmd *cmd = &dev->cmd; u32 cmd_h, cmd_l; - u16 cmd_if_rev; int err; int i; memset(cmd, 0, sizeof(*cmd)); - cmd_if_rev = cmdif_rev(dev); - if (cmd_if_rev != CMD_IF_REV) { + cmd->vars.cmdif_rev = cmdif_rev(dev); + if (cmd->vars.cmdif_rev != CMD_IF_REV) { mlx5_core_err(dev, "Driver cmdif rev(%d) differs from firmware's(%d)\n", - CMD_IF_REV, cmd_if_rev); + CMD_IF_REV, cmd->vars.cmdif_rev); return -EINVAL; } @@ -2233,14 +2232,6 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) cmd->vars.max_reg_cmds = (1 << cmd->vars.log_sz) - 1; cmd->vars.bitmask = (1UL << cmd->vars.max_reg_cmds) - 1; - cmd->vars.cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; - if (cmd->vars.cmdif_rev > CMD_IF_REV) { - mlx5_core_err(dev, "driver does not support command interface version. driver %d, firmware %d\n", - CMD_IF_REV, cmd->vars.cmdif_rev); - err = -EOPNOTSUPP; - goto err_free_page; - } - spin_lock_init(&cmd->alloc_lock); spin_lock_init(&cmd->token_lock); for (i = 0; i < MLX5_CMD_OP_MAX; i++) -- cgit From 06cd555f73caec515a14d42ef052221fa2587ff9 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Wed, 18 Jan 2023 20:55:54 +0200 Subject: net/mlx5: split mlx5_cmd_init() to probe and reload routines There is no need to destroy and allocate cmd SW structs during reload, this is time consuming for no reason. Hence, split mlx5_cmd_init() to probe and reload routines. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 121 ++++++++++++--------- drivers/net/ethernet/mellanox/mlx5/core/main.c | 15 ++- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2 + 3 files changed, 82 insertions(+), 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 9ced943ebd0d..45edd5a110c8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1548,7 +1548,6 @@ static void clean_debug_files(struct mlx5_core_dev *dev) if (!mlx5_debugfs_root) return; - mlx5_cmdif_debugfs_cleanup(dev); debugfs_remove_recursive(dbg->dbg_root); } @@ -1563,8 +1562,6 @@ static void create_debugfs_files(struct mlx5_core_dev *dev) debugfs_create_file("out_len", 0600, dbg->dbg_root, dev, &olfops); debugfs_create_u8("status", 0600, dbg->dbg_root, &dbg->status); debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops); - - mlx5_cmdif_debugfs_init(dev); } void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode) @@ -2190,19 +2187,10 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) int size = sizeof(struct mlx5_cmd_prot_block); int align = roundup_pow_of_two(size); struct mlx5_cmd *cmd = &dev->cmd; - u32 cmd_h, cmd_l; + u32 cmd_l; int err; int i; - memset(cmd, 0, sizeof(*cmd)); - cmd->vars.cmdif_rev = cmdif_rev(dev); - if (cmd->vars.cmdif_rev != CMD_IF_REV) { - mlx5_core_err(dev, - "Driver cmdif rev(%d) differs from firmware's(%d)\n", - CMD_IF_REV, cmd->vars.cmdif_rev); - return -EINVAL; - } - cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); if (!cmd->pool) return -ENOMEM; @@ -2211,43 +2199,93 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) if (err) goto err_free_pool; + cmd_l = (u32)(cmd->dma); + if (cmd_l & 0xfff) { + mlx5_core_err(dev, "invalid command queue address\n"); + err = -ENOMEM; + goto err_cmd_page; + } + cmd->checksum_disabled = 1; + + spin_lock_init(&cmd->alloc_lock); + spin_lock_init(&cmd->token_lock); + for (i = 0; i < MLX5_CMD_OP_MAX; i++) + spin_lock_init(&cmd->stats[i].lock); + + create_msg_cache(dev); + + set_wqname(dev); + cmd->wq = create_singlethread_workqueue(cmd->wq_name); + if (!cmd->wq) { + mlx5_core_err(dev, "failed to create command workqueue\n"); + err = -ENOMEM; + goto err_cache; + } + + mlx5_cmdif_debugfs_init(dev); + + return 0; + +err_cache: + destroy_msg_cache(dev); +err_cmd_page: + free_cmd_page(dev, cmd); +err_free_pool: + dma_pool_destroy(cmd->pool); + return err; +} + +void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + + mlx5_cmdif_debugfs_cleanup(dev); + destroy_workqueue(cmd->wq); + destroy_msg_cache(dev); + free_cmd_page(dev, cmd); + dma_pool_destroy(cmd->pool); +} + +int mlx5_cmd_enable(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + u32 cmd_h, cmd_l; + + memset(&cmd->vars, 0, sizeof(cmd->vars)); + cmd->vars.cmdif_rev = cmdif_rev(dev); + if (cmd->vars.cmdif_rev != CMD_IF_REV) { + mlx5_core_err(dev, + "Driver cmdif rev(%d) differs from firmware's(%d)\n", + CMD_IF_REV, cmd->vars.cmdif_rev); + return -EINVAL; + } + cmd_l = ioread32be(&dev->iseg->cmdq_addr_l_sz) & 0xff; cmd->vars.log_sz = cmd_l >> 4 & 0xf; cmd->vars.log_stride = cmd_l & 0xf; if (1 << cmd->vars.log_sz > MLX5_MAX_COMMANDS) { mlx5_core_err(dev, "firmware reports too many outstanding commands %d\n", 1 << cmd->vars.log_sz); - err = -EINVAL; - goto err_free_page; + return -EINVAL; } if (cmd->vars.log_sz + cmd->vars.log_stride > MLX5_ADAPTER_PAGE_SHIFT) { mlx5_core_err(dev, "command queue size overflow\n"); - err = -EINVAL; - goto err_free_page; + return -EINVAL; } cmd->state = MLX5_CMDIF_STATE_DOWN; - cmd->checksum_disabled = 1; cmd->vars.max_reg_cmds = (1 << cmd->vars.log_sz) - 1; cmd->vars.bitmask = (1UL << cmd->vars.max_reg_cmds) - 1; - spin_lock_init(&cmd->alloc_lock); - spin_lock_init(&cmd->token_lock); - for (i = 0; i < MLX5_CMD_OP_MAX; i++) - spin_lock_init(&cmd->stats[i].lock); - sema_init(&cmd->vars.sem, cmd->vars.max_reg_cmds); sema_init(&cmd->vars.pages_sem, 1); sema_init(&cmd->vars.throttle_sem, DIV_ROUND_UP(cmd->vars.max_reg_cmds, 2)); cmd_h = (u32)((u64)(cmd->dma) >> 32); cmd_l = (u32)(cmd->dma); - if (cmd_l & 0xfff) { - mlx5_core_err(dev, "invalid command queue address\n"); - err = -ENOMEM; - goto err_free_page; - } + if (WARN_ON(cmd_l & 0xfff)) + return -EINVAL; iowrite32be(cmd_h, &dev->iseg->cmdq_addr_h); iowrite32be(cmd_l, &dev->iseg->cmdq_addr_l_sz); @@ -2260,40 +2298,17 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) cmd->mode = CMD_MODE_POLLING; cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL; - create_msg_cache(dev); - - set_wqname(dev); - cmd->wq = create_singlethread_workqueue(cmd->wq_name); - if (!cmd->wq) { - mlx5_core_err(dev, "failed to create command workqueue\n"); - err = -ENOMEM; - goto err_cache; - } - create_debugfs_files(dev); return 0; - -err_cache: - destroy_msg_cache(dev); - -err_free_page: - free_cmd_page(dev, cmd); - -err_free_pool: - dma_pool_destroy(cmd->pool); - return err; } -void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) +void mlx5_cmd_disable(struct mlx5_core_dev *dev) { struct mlx5_cmd *cmd = &dev->cmd; clean_debug_files(dev); - destroy_workqueue(cmd->wq); - destroy_msg_cache(dev); - free_cmd_page(dev, cmd); - dma_pool_destroy(cmd->pool); + flush_workqueue(cmd->wq); } void mlx5_cmd_set_state(struct mlx5_core_dev *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a79c9b8286a7..740d4476c413 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1142,7 +1142,7 @@ static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeou return err; } - err = mlx5_cmd_init(dev); + err = mlx5_cmd_enable(dev); if (err) { mlx5_core_err(dev, "Failed initializing command interface, aborting\n"); return err; @@ -1196,7 +1196,7 @@ stop_health_poll: mlx5_stop_health_poll(dev, boot); err_cmd_cleanup: mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); + mlx5_cmd_disable(dev); return err; } @@ -1207,7 +1207,7 @@ static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot) mlx5_core_disable_hca(dev, 0); mlx5_stop_health_poll(dev, boot); mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); + mlx5_cmd_disable(dev); } static int mlx5_function_open(struct mlx5_core_dev *dev) @@ -1796,6 +1796,12 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx) debugfs_create_file("vhca_id", 0400, priv->dbg.dbg_root, dev, &vhca_id_fops); INIT_LIST_HEAD(&priv->traps); + err = mlx5_cmd_init(dev); + if (err) { + mlx5_core_err(dev, "Failed initializing cmdif SW structs, aborting\n"); + goto err_cmd_init; + } + err = mlx5_tout_init(dev); if (err) { mlx5_core_err(dev, "Failed initializing timeouts, aborting\n"); @@ -1841,6 +1847,8 @@ err_pagealloc_init: err_health_init: mlx5_tout_cleanup(dev); err_timeout_init: + mlx5_cmd_cleanup(dev); +err_cmd_init: debugfs_remove(dev->priv.dbg.dbg_root); mutex_destroy(&priv->pgdir_mutex); mutex_destroy(&priv->alloc_mutex); @@ -1863,6 +1871,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev) mlx5_pagealloc_cleanup(dev); mlx5_health_cleanup(dev); mlx5_tout_cleanup(dev); + mlx5_cmd_cleanup(dev); debugfs_remove_recursive(dev->priv.dbg.dbg_root); mutex_destroy(&priv->pgdir_mutex); mutex_destroy(&priv->alloc_mutex); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index c4be257c043d..43b0144121ca 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -178,6 +178,8 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev); int mlx5_query_board_id(struct mlx5_core_dev *dev); int mlx5_cmd_init(struct mlx5_core_dev *dev); void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); +int mlx5_cmd_enable(struct mlx5_core_dev *dev); +void mlx5_cmd_disable(struct mlx5_core_dev *dev); void mlx5_cmd_set_state(struct mlx5_core_dev *dev, enum mlx5_cmdif_state cmdif_state); int mlx5_cmd_init_hca(struct mlx5_core_dev *dev, uint32_t *sw_owner_id); -- cgit From b90ebfc018b087ba1e4981b298b58733236ff296 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Thu, 19 Jan 2023 09:10:50 +0200 Subject: net/mlx5: Allocate command stats with xarray Command stats is an array with more than 2K entries, which amounts to ~180KB. This is way more than actually needed, as only ~190 entries are being used. Therefore, replace the array with xarray. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 15 ++++++------ drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 30 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 45edd5a110c8..afb348579577 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1225,8 +1225,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, goto out_free; ds = ent->ts2 - ent->ts1; - if (ent->op < MLX5_CMD_OP_MAX) { - stats = &cmd->stats[ent->op]; + stats = xa_load(&cmd->stats, ent->op); + if (stats) { spin_lock_irq(&stats->lock); stats->sum += ds; ++stats->n; @@ -1695,8 +1695,8 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force if (ent->callback) { ds = ent->ts2 - ent->ts1; - if (ent->op < MLX5_CMD_OP_MAX) { - stats = &cmd->stats[ent->op]; + stats = xa_load(&cmd->stats, ent->op); + if (stats) { spin_lock_irqsave(&stats->lock, flags); stats->sum += ds; ++stats->n; @@ -1923,7 +1923,9 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, if (!err || !(strcmp(namep, "unknown command opcode"))) return; - stats = &dev->cmd.stats[opcode]; + stats = xa_load(&dev->cmd.stats, opcode); + if (!stats) + return; spin_lock_irq(&stats->lock); stats->failed++; if (err < 0) @@ -2189,7 +2191,6 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) struct mlx5_cmd *cmd = &dev->cmd; u32 cmd_l; int err; - int i; cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); if (!cmd->pool) @@ -2209,8 +2210,6 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) spin_lock_init(&cmd->alloc_lock); spin_lock_init(&cmd->token_lock); - for (i = 0; i < MLX5_CMD_OP_MAX; i++) - spin_lock_init(&cmd->stats[i].lock); create_msg_cache(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 9a826fb3ca38..09652dc89115 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -188,6 +188,24 @@ static const struct file_operations slots_fops = { .read = slots_read, }; +static struct mlx5_cmd_stats * +mlx5_cmdif_alloc_stats(struct xarray *stats_xa, int opcode) +{ + struct mlx5_cmd_stats *stats = kzalloc(sizeof(*stats), GFP_KERNEL); + int err; + + if (!stats) + return NULL; + + err = xa_insert(stats_xa, opcode, stats, GFP_KERNEL); + if (err) { + kfree(stats); + return NULL; + } + spin_lock_init(&stats->lock); + return stats; +} + void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) { struct mlx5_cmd_stats *stats; @@ -200,10 +218,14 @@ void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) debugfs_create_file("slots_inuse", 0400, *cmd, &dev->cmd, &slots_fops); + xa_init(&dev->cmd.stats); + for (i = 0; i < MLX5_CMD_OP_MAX; i++) { - stats = &dev->cmd.stats[i]; namep = mlx5_command_str(i); if (strcmp(namep, "unknown command opcode")) { + stats = mlx5_cmdif_alloc_stats(&dev->cmd.stats, i); + if (!stats) + continue; stats->root = debugfs_create_dir(namep, *cmd); debugfs_create_file("average", 0400, stats->root, stats, @@ -224,7 +246,13 @@ void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev) { + struct mlx5_cmd_stats *stats; + unsigned long i; + debugfs_remove_recursive(dev->priv.dbg.cmdif_debugfs); + xa_for_each(&dev->cmd.stats, i, stats) + kfree(stats); + xa_destroy(&dev->cmd.stats); } void mlx5_cq_debugfs_init(struct mlx5_core_dev *dev) -- cgit From 9ec85cc9c90e7cc2d91531132e9c1f1ebe067ce2 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Sun, 2 Jul 2023 01:19:29 +0300 Subject: net/mlx5e: Remove duplicate code for user flow Flow table and priority detection is same for IP user flows and other L4 flows. Hence, use same code for all these flow types. Signed-off-by: Parav Pandit Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c index aac32e505c14..08eb186615c8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c @@ -96,10 +96,6 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv, case UDP_V4_FLOW: case TCP_V6_FLOW: case UDP_V6_FLOW: - max_tuples = ETHTOOL_NUM_L3_L4_FTS; - prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples); - eth_ft = ðtool->l3_l4_ft[prio]; - break; case IP_USER_FLOW: case IPV6_USER_FLOW: max_tuples = ETHTOOL_NUM_L3_L4_FTS; -- cgit From b9335a757232e9ac03e5fc8ed71d834661b7a8ac Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Sun, 2 Jul 2023 01:25:08 +0300 Subject: net/mlx5e: Make flow classification filters static Get and set flow classification filters are used in a single file. Hence, make them static. Signed-off-by: Parav Pandit Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index b1807bfb815f..0f8f70b91485 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1167,9 +1167,6 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc); int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, const u8 hfunc); -int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, - u32 *rule_locs); -int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv); u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv); int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 27861b68ced5..04195a673a6b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2163,8 +2163,8 @@ static u32 mlx5e_get_priv_flags(struct net_device *netdev) return priv->channels.params.pflags; } -int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, - u32 *rule_locs) +static int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, + u32 *rule_locs) { struct mlx5e_priv *priv = netdev_priv(dev); @@ -2181,7 +2181,7 @@ int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs); } -int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct mlx5e_priv *priv = netdev_priv(dev); -- cgit From 550449d8e3890b19a6d780cb5854af1ff0a8961b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Jun 2023 08:22:43 +0200 Subject: net/mlx5: Don't check vport->enabled in port ops vport->enabled is always set for a vport for which a devlink port is registered, therefore the checks in the ops are pointless. Remove those. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 28 +++++----------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index b4b8cb788573..c192000e3614 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4125,7 +4125,6 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab { struct mlx5_eswitch *esw; struct mlx5_vport *vport; - int err = -EOPNOTSUPP; esw = mlx5_devlink_eswitch_get(port->devlink); if (IS_ERR(esw)) @@ -4133,7 +4132,7 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab if (!MLX5_CAP_GEN(esw->dev, migration)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration"); - return err; + return -EOPNOTSUPP; } vport = mlx5_devlink_port_fn_get_vport(port, esw); @@ -4143,12 +4142,9 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab } mutex_lock(&esw->state_lock); - if (vport->enabled) { - *is_enabled = vport->info.mig_enabled; - err = 0; - } + *is_enabled = vport->info.mig_enabled; mutex_unlock(&esw->state_lock); - return err; + return 0; } int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, @@ -4177,10 +4173,6 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, } mutex_lock(&esw->state_lock); - if (!vport->enabled) { - NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); - goto out; - } if (vport->info.mig_enabled == enable) { err = 0; @@ -4224,7 +4216,6 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, { struct mlx5_eswitch *esw; struct mlx5_vport *vport; - int err = -EOPNOTSUPP; esw = mlx5_devlink_eswitch_get(port->devlink); if (IS_ERR(esw)) @@ -4237,12 +4228,9 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, } mutex_lock(&esw->state_lock); - if (vport->enabled) { - *is_enabled = vport->info.roce_enabled; - err = 0; - } + *is_enabled = vport->info.roce_enabled; mutex_unlock(&esw->state_lock); - return err; + return 0; } int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, @@ -4251,10 +4239,10 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); struct mlx5_eswitch *esw; struct mlx5_vport *vport; - int err = -EOPNOTSUPP; void *query_ctx; void *hca_caps; u16 vport_num; + int err; esw = mlx5_devlink_eswitch_get(port->devlink); if (IS_ERR(esw)) @@ -4268,10 +4256,6 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, vport_num = vport->vport; mutex_lock(&esw->state_lock); - if (!vport->enabled) { - NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); - goto out; - } if (vport->info.roce_enabled == enable) { err = 0; -- cgit From 3e82a9cf579e18ca6b7cd0344597e5e8c5869fdb Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 31 May 2023 13:25:15 +0200 Subject: net/mlx5: Remove pointless devlink_rate checks It is guaranteed that the devlink rate leaf is created during init paths. No need to check during cleanup. Remove the checks. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index af779c700278..433541ac36a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -132,10 +132,8 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vpo if (IS_ERR(vport)) return; - if (vport->dl_port->devlink_rate) { - mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); - devl_rate_leaf_destroy(vport->dl_port); - } + mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); + devl_rate_leaf_destroy(vport->dl_port); devl_port_unregister(vport->dl_port); mlx5_esw_dl_port_free(vport->dl_port); @@ -211,10 +209,8 @@ void mlx5_esw_devlink_sf_port_unregister(struct mlx5_eswitch *esw, u16 vport_num if (IS_ERR(vport)) return; - if (vport->dl_port->devlink_rate) { - mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); - devl_rate_leaf_destroy(vport->dl_port); - } + mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); + devl_rate_leaf_destroy(vport->dl_port); devl_port_unregister(vport->dl_port); vport->dl_port = NULL; -- cgit From b71863876f840a12642ee4dc483471aec8793ba6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 09:15:20 +0200 Subject: net/mlx5: Make mlx5_esw_offloads_rep_load/unload() static mlx5_esw_offloads_rep_load/unload() functions are not used outside of eswitch_offloads.c. Make them static. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 3 --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 9b5a1651b877..6f360a15aa62 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -730,9 +730,6 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); -int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num); -void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num); - int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index c192000e3614..b4df57962b2b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2391,7 +2391,7 @@ static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type) __esw_offloads_unload_rep(esw, rep, rep_type); } -int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num) +static int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_eswitch_rep *rep; int rep_type; @@ -2415,7 +2415,7 @@ err_reps: return err; } -void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num) +static void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_eswitch_rep *rep; int rep_type; -- cgit From 329980d05d8ce9682a94fb3a6e4e6fc930293a01 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 09:25:48 +0200 Subject: net/mlx5: Make mlx5_eswitch_load/unload_vport() static mlx5_eswitch_load/unload_vport()() functions are not used outside of eswitch.c. Make them static. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 7 +++---- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 4 ---- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 243c455f1029..4b13269f49e0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1068,9 +1068,8 @@ static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) } } -/* Public E-Switch API */ -int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, - enum mlx5_eswitch_vport_event enabled_events) +static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, + enum mlx5_eswitch_vport_event enabled_events) { int err; @@ -1089,7 +1088,7 @@ err_rep: return err; } -void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) +static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) { esw_offloads_unload_rep(esw, vport_num); mlx5_esw_vport_disable(esw, vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 6f360a15aa62..837bdd03557b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -730,10 +730,6 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); -int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, - enum mlx5_eswitch_vport_event enabled_events); -void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num); - int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs); -- cgit From 9eca8bb8da4385b02bd02b6876af8d4225bf4713 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 09:42:09 +0200 Subject: net/mlx5: Give esw_offloads_load/unload_rep() "mlx5_" prefix As esw_offloads_load/unload_rep() are used outside eswitch.c it is nicer for them to have "mlx5_" prefix. Add it. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 4b13269f49e0..4a7a13169a90 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1077,7 +1077,7 @@ static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, if (err) return err; - err = esw_offloads_load_rep(esw, vport_num); + err = mlx5_esw_offloads_load_rep(esw, vport_num); if (err) goto err_rep; @@ -1090,7 +1090,7 @@ err_rep: static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) { - esw_offloads_unload_rep(esw, vport_num); + mlx5_esw_offloads_unload_rep(esw, vport_num); mlx5_esw_vport_disable(esw, vport_num); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 837bdd03557b..2944c9207487 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -727,8 +727,8 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, u16 vport, struct mlx5_flow_spec *spec); -int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); -void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index b4df57962b2b..f83667b4339e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2425,7 +2425,7 @@ static void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num __esw_offloads_unload_rep(esw, rep, rep_type); } -int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) { int err; @@ -2449,7 +2449,7 @@ load_err: return err; } -void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num) { if (esw->mode != MLX5_ESWITCH_OFFLOADS) return; @@ -3361,7 +3361,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; /* Uplink vport rep must load first. */ - err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK); + err = mlx5_esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK); if (err) goto err_uplink; @@ -3372,7 +3372,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) return 0; err_vports: - esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); + mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); err_uplink: esw_offloads_steering_cleanup(esw); err_steering_init: @@ -3410,7 +3410,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, void esw_offloads_disable(struct mlx5_eswitch *esw) { mlx5_eswitch_disable_pf_vf_vports(esw); - esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); + mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); esw_set_passing_vport_metadata(esw, false); esw_offloads_steering_cleanup(esw); mapping_destroy(esw->offloads.reg_c0_obj_pool); -- cgit From d928d14be6514af9da37009c2091270c5c714366 Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Tue, 25 Jul 2023 16:04:25 -0500 Subject: net: stmmac: Make ptp_clk_freq_config variable type explicit The priv variable is _always_ of type (struct stmmac_priv *), so let's stop using (void *) since it isn't abstracting anything. Reviewed-by: Simon Horman Signed-off-by: Andrew Halaney Link: https://lore.kernel.org/r/20230725211853.895832-3-ahalaney@redhat.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 0ffae785d8bd..979c755964b1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -257,9 +257,8 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data) /* Program PTP Clock Frequency for different variant of * Intel mGBE that has slightly different GPO mapping */ -static void intel_mgbe_ptp_clk_freq_config(void *npriv) +static void intel_mgbe_ptp_clk_freq_config(struct stmmac_priv *priv) { - struct stmmac_priv *priv = (struct stmmac_priv *)npriv; struct intel_priv_data *intel_priv; u32 gpio_value; -- cgit From db845b9b2040f4ed5f8bce6cd30103e3b8557566 Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Tue, 25 Jul 2023 16:04:26 -0500 Subject: net: stmmac: dwmac-qcom-ethqos: Use max frequency for clk_ptp_ref Qualcomm clocks can set their frequency to a variety of levels generally. Let's use the max for clk_ptp_ref to ensure the best timestamping resolution possible. Without this, the default value of the clock is used. For sa8775p-ride this is 19.2 MHz, far less than the 230.4 MHz possible. Reviewed-by: Simon Horman Signed-off-by: Andrew Halaney Link: https://lore.kernel.org/r/20230725211853.895832-4-ahalaney@redhat.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 735525ba8b93..a85501874801 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -694,6 +694,23 @@ static void ethqos_clks_disable(void *data) ethqos_clks_config(data, false); } +static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv) +{ + struct plat_stmmacenet_data *plat_dat = priv->plat; + int err; + + if (!plat_dat->clk_ptp_ref) + return; + + /* Max the PTP ref clock out to get the best resolution possible */ + err = clk_set_rate(plat_dat->clk_ptp_ref, ULONG_MAX); + if (err) + netdev_err(priv->dev, "Failed to max out clk_ptp_ref: %d\n", err); + plat_dat->clk_ptp_rate = clk_get_rate(plat_dat->clk_ptp_ref); + + netdev_dbg(priv->dev, "PTP rate %d\n", plat_dat->clk_ptp_rate); +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -779,6 +796,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->bsp_priv = ethqos; plat_dat->fix_mac_speed = ethqos_fix_mac_speed; plat_dat->dump_debug_regs = rgmii_dump; + plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config; plat_dat->has_gmac4 = 1; if (ethqos->has_emac_ge_3) plat_dat->dwmac4_addrs = &data->dwmac4_addrs; -- cgit From 81b04a800d3c537d1d9ac1f0c2192011c4ebabb7 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 26 Jul 2023 15:40:54 -0700 Subject: Revert "net: stmmac: correct MAC propagation delay" This reverts commit 20bf98c94146eb6fe62177817cb32f53e72dd2e8. Richard raised concerns about correctness of the code on previous generations of the HW. Fixes: 20bf98c94146 ("net: stmmac: correct MAC propagation delay") Link: https://lore.kernel.org/all/ZMGIuKVP7BEotbrn@hoboy.vegasvil.org/ Link: https://lore.kernel.org/r/20230726224054.3241127-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 -- .../net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 43 ---------------------- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 -- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 6 --- 4 files changed, 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 40147ef24963..652af8f6e75f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -532,7 +532,6 @@ struct stmmac_hwtimestamp { void (*get_systime) (void __iomem *ioaddr, u64 *systime); void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time); void (*timestamp_interrupt)(struct stmmac_priv *priv); - void (*correct_latency)(struct stmmac_priv *priv); }; #define stmmac_config_hw_tstamping(__priv, __args...) \ @@ -551,8 +550,6 @@ struct stmmac_hwtimestamp { stmmac_do_void_callback(__priv, ptp, get_ptptime, __args) #define stmmac_timestamp_interrupt(__priv, __args...) \ stmmac_do_void_callback(__priv, ptp, timestamp_interrupt, __args) -#define stmmac_correct_latency(__priv, __args...) \ - stmmac_do_void_callback(__priv, ptp, correct_latency, __args) struct stmmac_tx_queue; struct stmmac_rx_queue; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index 7e0fa024e0ad..fa2c3ba7e9fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -60,48 +60,6 @@ static void config_sub_second_increment(void __iomem *ioaddr, *ssinc = data; } -static void correct_latency(struct stmmac_priv *priv) -{ - void __iomem *ioaddr = priv->ptpaddr; - u32 reg_tsic, reg_tsicsns; - u32 reg_tsec, reg_tsecsns; - u64 scaled_ns; - u32 val; - - /* MAC-internal ingress latency */ - scaled_ns = readl(ioaddr + PTP_TS_INGR_LAT); - - /* See section 11.7.2.5.3.1 "Ingress Correction" on page 4001 of - * i.MX8MP Applications Processor Reference Manual Rev. 1, 06/2021 - */ - val = readl(ioaddr + PTP_TCR); - if (val & PTP_TCR_TSCTRLSSR) - /* nanoseconds field is in decimal format with granularity of 1ns/bit */ - scaled_ns = ((u64)NSEC_PER_SEC << 16) - scaled_ns; - else - /* nanoseconds field is in binary format with granularity of ~0.466ns/bit */ - scaled_ns = ((1ULL << 31) << 16) - - DIV_U64_ROUND_CLOSEST(scaled_ns * PSEC_PER_NSEC, 466U); - - reg_tsic = scaled_ns >> 16; - reg_tsicsns = scaled_ns & 0xff00; - - /* set bit 31 for 2's compliment */ - reg_tsic |= BIT(31); - - writel(reg_tsic, ioaddr + PTP_TS_INGR_CORR_NS); - writel(reg_tsicsns, ioaddr + PTP_TS_INGR_CORR_SNS); - - /* MAC-internal egress latency */ - scaled_ns = readl(ioaddr + PTP_TS_EGR_LAT); - - reg_tsec = scaled_ns >> 16; - reg_tsecsns = scaled_ns & 0xff00; - - writel(reg_tsec, ioaddr + PTP_TS_EGR_CORR_NS); - writel(reg_tsecsns, ioaddr + PTP_TS_EGR_CORR_SNS); -} - static int init_systime(void __iomem *ioaddr, u32 sec, u32 nsec) { u32 value; @@ -263,5 +221,4 @@ const struct stmmac_hwtimestamp stmmac_ptp = { .get_systime = get_systime, .get_ptptime = get_ptptime, .timestamp_interrupt = timestamp_interrupt, - .correct_latency = correct_latency, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 19e46e8f626a..e1f1c034d325 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -909,8 +909,6 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) priv->hwts_tx_en = 0; priv->hwts_rx_en = 0; - stmmac_correct_latency(priv, priv); - return 0; } @@ -1096,8 +1094,6 @@ static void stmmac_mac_link_up(struct phylink_config *config, if (priv->dma_cap.fpesel) stmmac_fpe_link_state_handle(priv, true); - - stmmac_correct_latency(priv, priv); } static const struct phylink_mac_ops stmmac_phylink_mac_ops = { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index d1fe4b46f162..bf619295d079 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -26,12 +26,6 @@ #define PTP_ACR 0x40 /* Auxiliary Control Reg */ #define PTP_ATNR 0x48 /* Auxiliary Timestamp - Nanoseconds Reg */ #define PTP_ATSR 0x4c /* Auxiliary Timestamp - Seconds Reg */ -#define PTP_TS_INGR_CORR_NS 0x58 /* Ingress timestamp correction nanoseconds */ -#define PTP_TS_EGR_CORR_NS 0x5C /* Egress timestamp correction nanoseconds*/ -#define PTP_TS_INGR_CORR_SNS 0x60 /* Ingress timestamp correction subnanoseconds */ -#define PTP_TS_EGR_CORR_SNS 0x64 /* Egress timestamp correction subnanoseconds */ -#define PTP_TS_INGR_LAT 0x68 /* MAC internal Ingress Latency */ -#define PTP_TS_EGR_LAT 0x6c /* MAC internal Egress Latency */ #define PTP_STNSUR_ADDSUB_SHIFT 31 #define PTP_DIGITAL_ROLLOVER_MODE 0x3B9ACA00 /* 10e9-1 ns */ -- cgit From 3d40aed862874db14e1dd41fd6f12636dcfdcc3e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 26 Jul 2023 19:49:39 -0600 Subject: net: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Acked-by: Alex Elder Reviewed-by: Bhupesh Sharma Reviewed-by: Wei Fang Signed-off-by: Rob Herring Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230727014944.3972546-1-robh@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/aeroflex/greth.c | 4 ++-- drivers/net/ethernet/amd/sunlance.c | 2 +- drivers/net/ethernet/apm/xgene-v2/main.h | 1 + drivers/net/ethernet/arc/emac_main.c | 2 +- drivers/net/ethernet/atheros/ag71xx.c | 3 ++- drivers/net/ethernet/cadence/macb_main.c | 1 - drivers/net/ethernet/cirrus/cs89x0.c | 1 - drivers/net/ethernet/ezchip/nps_enet.c | 5 ++--- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 3 ++- drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 2 ++ drivers/net/ethernet/freescale/enetc/enetc_ierb.c | 2 +- drivers/net/ethernet/freescale/fec_mpc52xx.c | 4 ++-- drivers/net/ethernet/freescale/fec_mpc52xx_phy.c | 3 ++- drivers/net/ethernet/freescale/fec_ptp.c | 1 - drivers/net/ethernet/freescale/fman/fman.c | 1 + drivers/net/ethernet/freescale/fman/fman_port.c | 1 + drivers/net/ethernet/freescale/fman/mac.c | 2 ++ drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 1 - drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 1 - drivers/net/ethernet/freescale/fs_enet/mac-scc.c | 1 - drivers/net/ethernet/freescale/fsl_pq_mdio.c | 1 + drivers/net/ethernet/freescale/gianfar.c | 2 +- drivers/net/ethernet/freescale/gianfar_ethtool.c | 2 ++ drivers/net/ethernet/freescale/ucc_geth.c | 3 ++- drivers/net/ethernet/freescale/xgmac_mdio.c | 4 ++-- drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 3 --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 4 ---- drivers/net/ethernet/ibm/ehea/ehea_main.c | 1 + drivers/net/ethernet/ibm/emac/core.c | 1 + drivers/net/ethernet/ibm/emac/core.h | 1 - drivers/net/ethernet/ibm/emac/mal.c | 2 ++ drivers/net/ethernet/ibm/emac/rgmii.c | 2 ++ drivers/net/ethernet/ibm/emac/tah.c | 2 ++ drivers/net/ethernet/ibm/emac/zmii.c | 2 ++ drivers/net/ethernet/korina.c | 2 +- drivers/net/ethernet/marvell/mvmdio.c | 2 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 - drivers/net/ethernet/marvell/prestera/prestera_rxtx.c | 3 --- drivers/net/ethernet/marvell/sky2.c | 1 - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++- drivers/net/ethernet/mediatek/mtk_star_emac.c | 1 - drivers/net/ethernet/mediatek/mtk_wed.c | 1 + drivers/net/ethernet/mediatek/mtk_wed_wo.c | 3 +-- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 3 ++- drivers/net/ethernet/mscc/ocelot_fdma.c | 1 - drivers/net/ethernet/mscc/ocelot_vsc7514.c | 3 ++- drivers/net/ethernet/ni/nixge.c | 5 ++--- drivers/net/ethernet/qualcomm/emac/emac-sgmii.c | 2 ++ drivers/net/ethernet/qualcomm/emac/emac.c | 1 - drivers/net/ethernet/qualcomm/qca_spi.c | 1 - drivers/net/ethernet/qualcomm/qca_uart.c | 1 - drivers/net/ethernet/renesas/ravb_main.c | 3 +-- drivers/net/ethernet/renesas/rswitch.c | 3 +-- drivers/net/ethernet/renesas/sh_eth.c | 2 -- drivers/net/ethernet/smsc/smsc911x.c | 1 - drivers/net/ethernet/socionext/sni_ave.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c | 4 +++- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 - drivers/net/ethernet/sun/niu.c | 2 +- drivers/net/ethernet/sun/sunbmac.c | 2 +- drivers/net/ethernet/sun/sungem.c | 1 + drivers/net/ethernet/sun/sunhme.c | 3 ++- drivers/net/ethernet/sun/sunqe.c | 2 +- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 + drivers/net/ethernet/ti/cpsw-common.c | 1 - drivers/net/ethernet/ti/cpsw-phy-sel.c | 1 - drivers/net/ethernet/ti/davinci_mdio.c | 1 - drivers/net/ethernet/via/via-rhine.c | 2 +- drivers/net/ethernet/via/via-velocity.c | 2 +- drivers/net/ethernet/xilinx/ll_temac.h | 1 + drivers/net/ethernet/xilinx/ll_temac_main.c | 4 +--- drivers/net/ethernet/xilinx/ll_temac_mdio.c | 2 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 3 ++- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 4 ++-- drivers/net/ieee802154/ca8210.c | 1 - drivers/net/ipa/ipa_main.c | 2 +- 89 files changed, 87 insertions(+), 92 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index aa0d2f3aaeaa..597a02c75d52 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -29,9 +29,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 68ca1225eedc..33bb539ad70a 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -92,7 +92,7 @@ static char lancestr[] = "LANCE"; #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h b/drivers/net/ethernet/apm/xgene-v2/main.h index b3985a7be59d..7be6f83e22fe 100644 --- a/drivers/net/ethernet/apm/xgene-v2/main.h +++ b/drivers/net/ethernet/apm/xgene-v2/main.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "mac.h" #include "enet.h" diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 2b427d8a1831..31ee477dd131 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -15,11 +15,11 @@ #include #include #include +#include #include #include #include #include -#include #include "emac.h" diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index ff1a5edf8df1..009e0b3066fa 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -29,9 +29,10 @@ #include #include +#include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f6a0f12a6d52..b61566afb2f4 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index 276c32c3926a..7c51fd9fc9be 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c index f1eb660aaee2..edf000e7bab4 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.c +++ b/drivers/net/ethernet/ezchip/nps_enet.c @@ -6,10 +6,9 @@ #include #include #include -#include -#include +#include #include -#include +#include #include "nps_enet.h" #define DRV_NAME "nps_mgt_enet" diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 85e38a1ec22a..dcbc598b11c6 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -7,8 +7,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include -#include #include #include #include @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c index 9c71cbbb13d8..5bd0b36d1feb 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -6,7 +6,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include +#include #include #include diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ierb.c b/drivers/net/ethernet/freescale/enetc/enetc_ierb.c index b307bef4dc29..d39617ab9306 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ierb.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ierb.c @@ -18,8 +18,8 @@ */ #include +#include #include -#include #include #include #include "enetc.h" diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 984ece5cd64f..ebae71ec26c6 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -29,12 +29,12 @@ #include #include #include +#include #include -#include #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c index 61d3776d6750..39689826cc8f 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c @@ -13,10 +13,11 @@ #include #include #include -#include #include +#include #include #include +#include #include #include #include "fec_mpc52xx.h" diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index afc658d2c271..fc4674cb65be 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c index 9d85fb136e34..d96028f01770 100644 --- a/drivers/net/ethernet/freescale/fman/fman.c +++ b/drivers/net/ethernet/freescale/fman/fman.c @@ -7,6 +7,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c index ab90fe2bee5e..406e75e9e5ea 100644 --- a/drivers/net/ethernet/freescale/fman/fman_port.c +++ b/drivers/net/ethernet/freescale/fman/fman_port.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index c5045891d694..b6c7c4c0b367 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -12,12 +12,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "mac.h" #include "fman_mac.h" diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c index b47490be872c..925428f1b0c8 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c index 61f4b6e50d29..f609dc112458 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c index 64300ac13e02..66d40da5cde0 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 01d594886f52..eee675a25b2c 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 0c898f9ee358..e3dfbd7a4236 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -60,6 +60,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -75,7 +76,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index b2b0d3c26fcc..7a15b9245698 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -38,7 +38,9 @@ #include #include #include +#include #include +#include #include #include "gianfar.h" diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 2b3a15f24e7c..ab421243a419 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -28,11 +28,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index a13b4ba4d6e1..65dc07d0df0f 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -19,10 +19,10 @@ #include #include #include -#include +#include #include -#include #include +#include #include /* Number of microseconds to wait for a register to respond */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index a7eb87da4e70..a08d1f0a5a16 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -9,9 +9,6 @@ #include #include #include -#include -#include -#include #include "hns_dsaf_ppe.h" diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index e2ff3ca198d1..93344563a259 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -11,10 +11,6 @@ #include #include #include -#include -#include -#include -#include #include #include "hns_dsaf_main.h" diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index b4aff59b3eb4..0a56e9752464 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -31,6 +31,7 @@ #include #include #include +#include #include diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index c97095abd26a..0c314bf97480 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 89a1b0fea158..295516b07662 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index ff5487bbebe3..c3236b59e7e9 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -22,7 +22,9 @@ #include #include +#include #include +#include #include "core.h" #include diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index 50358cf00130..fd437f986edf 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include "emac.h" diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c index 008bbdaf1204..aae9a88d95d7 100644 --- a/drivers/net/ethernet/ibm/emac/tah.c +++ b/drivers/net/ethernet/ibm/emac/tah.c @@ -14,7 +14,9 @@ * * Copyright (c) 2005 Eugene Surovegin */ +#include #include +#include #include #include "emac.h" diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index 57a25c7a9e70..6337388ee5f4 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include "emac.h" diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 2b9335cb4bb3..25f7a2a3b847 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index 8662543ca5c8..a1a80f13b1e8 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -24,8 +24,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 1fec84b4c068..9e1b596c8f08 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c index 9277a8fd1339..cc2a9ae794be 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c @@ -5,9 +5,6 @@ #include #include #include -#include -#include -#include #include #include "prestera_dsa.h" diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 7c487f9b36ec..c4cca27fb0d5 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 30e3935e83f9..38f39be04eae 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -6,11 +6,12 @@ * Copyright (C) 2013-2016 Michael Lee */ -#include +#include #include #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c index 02c03325911f..31aebeb2e285 100644 --- a/drivers/net/ethernet/mediatek/mtk_star_emac.c +++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c index 5f062ecb402c..00aeee0d5e45 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -2,6 +2,7 @@ /* Copyright (C) 2021 Felix Fietkau */ #include +#include #include #include #include diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c index 69fba29055e9..3bd51a3d6650 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c @@ -7,10 +7,9 @@ #include #include -#include #include -#include #include +#include #include #include diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index fbb0bb4594cd..73f20683210e 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -5,9 +5,10 @@ #include #include #include -#include +#include #include #include +#include #include #include diff --git a/drivers/net/ethernet/mscc/ocelot_fdma.c b/drivers/net/ethernet/mscc/ocelot_fdma.c index 83a3ce0c568e..312a46832154 100644 --- a/drivers/net/ethernet/mscc/ocelot_fdma.c +++ b/drivers/net/ethernet/mscc/ocelot_fdma.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "ocelot_fdma.h" diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 97e90e2869d4..151b42465348 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -10,8 +10,9 @@ #include #include #include +#include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 0fd156286d4d..ba27bbc68f85 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -7,11 +7,10 @@ #include #include #include -#include +#include #include #include -#include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c index 802ef81493e0..e4bc18009d08 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include "emac.h" #include "emac-mac.h" #include "emac-sgmii.h" diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index eaa50050aa0b..19bb16daf4e7 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 4a1b94e5a8ea..bec723028e96 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c index 26646cb6a20a..ace99c62d03a 100644 --- a/drivers/net/ethernet/qualcomm/qca_uart.c +++ b/drivers/net/ethernet/qualcomm/qca_uart.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 4d6b3b7d6abb..7df9f9f8e134 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -21,10 +21,9 @@ #include #include #include -#include -#include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 4e412ac0965a..0ba7fb75d589 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -12,11 +12,10 @@ #include #include #include -#include -#include #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d8ec729825be..274ea16c0a1f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index c362bff3cb83..cb590db625e8 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 492c39c08af1..4838d2383a43 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -15,10 +15,11 @@ #include #include #include +#include #include #include -#include #include +#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index b5efd9c2eac7..74c10373cc39 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index b9378a63f0e8..92e06a96757a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c index 8063ba1c3ce8..e22ef0d6bc73 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 4d877d75642d..7580077383c0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -7,8 +7,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index 92b16048f91c..0b159dc0d5f6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c index 42954020de2c..f91753565d60 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index a85501874801..5b3df27035ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index d81591b470a2..35789cb549f7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c index d3a39d2fb3a9..b1c5f2527c0d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c @@ -7,8 +7,10 @@ * */ +#include +#include +#include #include -#include #include #include "stmmac_platform.h" diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index dcbb17c4f07a..ef03e4669491 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "stmmac_platform.h" diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index bdb4de59a672..3a09085819dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index b607279e8cbd..c23420863a8d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -11,9 +11,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c index 99e2e5a5cd60..2bc6ef1eca1f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c index acbb284be174..a8731ce0fff0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c @@ -6,7 +6,8 @@ */ #include -#include +#include +#include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 23d53ea04b24..be8e79c7aa34 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "stmmac.h" diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 7a2e76776297..011d74087f86 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include "niu.h" diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 34b94153bf0c..cc34d92d2e3d 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 4154e68639ac..9bd1df8308d2 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index b93613cd1994..b983b9c23be6 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -32,9 +32,10 @@ #include #include #include -#include #include +#include #include +#include #include #include #include diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index 6418fcc3139f..b37360f44972 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -27,8 +27,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index bebcfd5e6b57..bea6fc0f324c 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c index bfa81bbfce3f..26dc906eae90 100644 --- a/drivers/net/ethernet/ti/cpsw-common.c +++ b/drivers/net/ethernet/ti/cpsw-common.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index 25e707d7b87c..4edb7963f856 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "cpsw.h" diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 23169e36a3d4..89b6d23e9937 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index d716e6fe26e1..3e09e5036490 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -94,7 +94,7 @@ static const int multicast_filter_limit = 32; #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 86f7843b4591..731f689412e6 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -57,8 +57,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/ethernet/xilinx/ll_temac.h b/drivers/net/ethernet/xilinx/ll_temac.h index 6668d1b760d8..90d122d5475c 100644 --- a/drivers/net/ethernet/xilinx/ll_temac.h +++ b/drivers/net/ethernet/xilinx/ll_temac.h @@ -5,6 +5,7 @@ #include #include +#include #include #ifdef CONFIG_PPC_DCR diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index e0ac1bcd9925..0bf9cdee1df2 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -35,12 +35,10 @@ #include #include #include -#include #include #include #include -#include -#include +#include #include #include #include /* needed for sizeof(tcphdr) */ diff --git a/drivers/net/ethernet/xilinx/ll_temac_mdio.c b/drivers/net/ethernet/xilinx/ll_temac_mdio.c index 2371c072b53f..07a9fb49eda1 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_mdio.c +++ b/drivers/net/ethernet/xilinx/ll_temac_mdio.c @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 8e32dc50a408..b7ec4dafae90 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -27,11 +27,12 @@ #include #include #include +#include #include #include -#include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index ad2c30d9a482..b358ecc67227 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -15,9 +16,8 @@ #include #include #include +#include #include -#include -#include #include #include #include diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index f9b10e84de06..aebb19f1b3a4 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 6a2f2fc2f501..da853353a5c7 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include #include -- cgit From 74dedbd74d2bfac24b44acb268ea77faa9fc9c41 Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Fri, 21 Jul 2023 20:07:58 +0200 Subject: can: peak_usb: remove unused/legacy peak_usb_netif_rx() function Remove unused/legacy peak_usb_netif_rx() function (not longer used since commit 28e0a70cede3 ("can: peak_usb: CANFD: store 64-bits hw timestamps"). Signed-off-by: Peter Seiderer Link: https://lore.kernel.org/all/20230721180758.26199-1-ps.report@gmx.net Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 13 ------------- drivers/net/can/usb/peak_usb/pcan_usb_core.h | 2 -- 2 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index d881e1d30183..24ad9f593a77 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -214,19 +214,6 @@ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) } } -/* - * post received skb after having set any hw timestamp - */ -int peak_usb_netif_rx(struct sk_buff *skb, - struct peak_time_ref *time_ref, u32 ts_low) -{ - struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); - - peak_usb_get_ts_time(time_ref, ts_low, &hwts->hwtstamp); - - return netif_rx(skb); -} - /* post received skb with native 64-bit hw timestamp */ int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high) { diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index 980e315186cf..f6cf84bb718f 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -142,8 +142,6 @@ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *tv); -int peak_usb_netif_rx(struct sk_buff *skb, - struct peak_time_ref *time_ref, u32 ts_low); int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high); void peak_usb_async_complete(struct urb *urb); void peak_usb_restart_complete(struct peak_usb_device *dev); -- cgit From 8cda0c6dfd42ee6f2586e7dffb553aaf1fcb62ca Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:52 +1000 Subject: can: sun4i_can: Add acceptance register quirk The Allwinner D1's CAN controllers have the ACPC and ACPM registers moved down. Compensate for this by adding an offset quirk for the acceptance registers. Signed-off-by: John Watts Link: https://lore.kernel.org/all/20230721221552.1973203-5-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 0827830bbf28..1f90fe6dbb8b 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -205,9 +205,11 @@ * struct sun4ican_quirks - Differences between SoC variants. * * @has_reset: SoC needs reset deasserted. + * @acp_offset: Offset of ACPC and ACPM registers */ struct sun4ican_quirks { bool has_reset; + int acp_offset; }; struct sun4ican_priv { @@ -216,6 +218,7 @@ struct sun4ican_priv { struct clk *clk; struct reset_control *reset; spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */ + int acp_offset; }; static const struct can_bittiming_const sun4ican_bittiming_const = { @@ -338,8 +341,8 @@ static int sun4i_can_start(struct net_device *dev) } /* set filters - we accept all */ - writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR); - writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR); + writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR + priv->acp_offset); + writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR + priv->acp_offset); /* clear error counters and error code capture */ writel(0, priv->base + SUN4I_REG_ERRC_ADDR); @@ -768,10 +771,12 @@ static const struct ethtool_ops sun4ican_ethtool_ops = { static const struct sun4ican_quirks sun4ican_quirks_a10 = { .has_reset = false, + .acp_offset = 0, }; static const struct sun4ican_quirks sun4ican_quirks_r40 = { .has_reset = true, + .acp_offset = 0, }; static const struct of_device_id sun4ican_of_match[] = { @@ -870,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev) priv->base = addr; priv->clk = clk; priv->reset = reset; + priv->acp_offset = quirks->acp_offset; spin_lock_init(&priv->cmdreg_lock); platform_set_drvdata(pdev, dev); -- cgit From 8abb95250ae6af2d51993da8fcae18da2ce24cc4 Mon Sep 17 00:00:00 2001 From: John Watts Date: Sat, 22 Jul 2023 08:15:53 +1000 Subject: can: sun4i_can: Add support for the Allwinner D1 The controllers present in the D1 are extremely similar to the R40 and require the same reset quirks, but An extra quirk is needed to support receiving packets. Signed-off-by: John Watts Link: https://lore.kernel.org/all/20230721221552.1973203-6-contact@jookia.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 4 ++-- drivers/net/can/sun4i_can.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 18e4a6e94ba9..649453a3c858 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -190,10 +190,10 @@ config CAN_SLCAN config CAN_SUN4I tristate "Allwinner A10 CAN controller" - depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST + depends on MACH_SUN4I || MACH_SUN7I || RISCV || COMPILE_TEST help Say Y here if you want to use CAN controller found on Allwinner - A10/A20 SoCs. + A10/A20/D1 SoCs. To compile this driver as a module, choose M here: the module will be called sun4i_can. diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 1f90fe6dbb8b..c508a328e38d 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -91,6 +91,8 @@ #define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */ #define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */ #define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */ +#define SUN4I_REG_ACPC_ADDR_D1 0x0028 /* CAN Acceptance Code 0 on the D1 */ +#define SUN4I_REG_ACPM_ADDR_D1 0x002C /* CAN Acceptance Mask 0 on the D1 */ #define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */ #define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */ @@ -779,6 +781,11 @@ static const struct sun4ican_quirks sun4ican_quirks_r40 = { .acp_offset = 0, }; +static const struct sun4ican_quirks sun4ican_quirks_d1 = { + .has_reset = true, + .acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR), +}; + static const struct of_device_id sun4ican_of_match[] = { { .compatible = "allwinner,sun4i-a10-can", @@ -789,6 +796,9 @@ static const struct of_device_id sun4ican_of_match[] = { }, { .compatible = "allwinner,sun8i-r40-can", .data = &sun4ican_quirks_r40 + }, { + .compatible = "allwinner,sun20i-d1-can", + .data = &sun4ican_quirks_d1 }, { /* sentinel */ }, @@ -913,4 +923,4 @@ module_platform_driver(sun4i_can_driver); MODULE_AUTHOR("Peter Chen "); MODULE_AUTHOR("Gerhard Bertelsmann "); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)"); +MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20/D1)"); -- cgit From 07382e6b68a742f18d57a27fec5fd0c2b0b61b40 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 24 Jul 2023 15:18:40 -0600 Subject: can: Explicitly include correct DT includes, part 2 The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/all/20230724211841.805053-1-robh@kernel.org Signed-off-by: Marc Kleine-Budde --- drivers/net/can/bxcan.c | 1 - drivers/net/can/ifi_canfd/ifi_canfd.c | 1 - drivers/net/can/m_can/m_can.c | 1 - drivers/net/can/m_can/m_can.h | 1 - drivers/net/can/rcar/rcar_canfd.c | 1 - drivers/net/can/sja1000/sja1000_platform.c | 1 - drivers/net/can/sun4i_can.c | 1 - drivers/net/can/ti_hecc.c | 1 - 8 files changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c index 39de7164bc4e..49cf9682b925 100644 --- a/drivers/net/can/bxcan.c +++ b/drivers/net/can/bxcan.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 1d6642c94f2f..72307297d75e 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 13fd84b2e2dd..a6263a617ac9 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index 2ac18ac867a4..c543928c756f 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index e4d748913439..b82842718735 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 4e59952c66d4..33f0e46ab1c2 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "sja1000.h" diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index c508a328e38d..ab8d01784686 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 54284661992e..a8243acde92d 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include -- cgit From f1a14714bf48f87fa8e774f415ea9815daf3750d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 18 Jul 2023 11:11:22 +0200 Subject: can: gs_usb: remove leading space from goto labels Remove leading spaces from goto labels in accordance with the kernel encoding style. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-1-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index bd9eb066ecf1..c604377138fd 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -645,7 +645,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) netif_rx(skb); } - resubmit_urb: +resubmit_urb: usb_fill_bulk_urb(urb, usbcan->udev, usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN), hf, dev->parent->hf_size_rx, @@ -655,7 +655,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) /* USB failure take down all interfaces */ if (rc == -ENODEV) { - device_detach: +device_detach: for (rc = 0; rc < GS_MAX_INTF; rc++) { if (usbcan->canch[rc]) netif_device_detach(usbcan->canch[rc]->netdev); @@ -818,12 +818,12 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; - badidx: +badidx: kfree(hf); - nomem_hf: +nomem_hf: usb_free_urb(urb); - nomem_urb: +nomem_urb: gs_free_tx_context(txc); dev_kfree_skb(skb); stats->tx_dropped++; @@ -1354,7 +1354,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, return dev; - out_free_candev: +out_free_candev: free_candev(dev->netdev); return ERR_PTR(rc); } -- cgit From 5780148bedd6aa7e51d3a18cd70f5b9b6cefb79e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 13:08:43 +0200 Subject: can: gs_usb: gs_usb_probe(): align block comment Indent block comment so that it aligns the * on each line. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-2-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index c604377138fd..966e00ea768d 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1443,8 +1443,8 @@ static int gs_usb_probe(struct usb_interface *intf, dev->canch[i]->parent = dev; /* set RX packet size based on FD and if hardware - * timestamps are supported. - */ + * timestamps are supported. + */ if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, canfd_ts, 1); -- cgit From a2002f455c0e1f1c8802e7bdafe370d47d4328de Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 13:04:45 +0200 Subject: can: gs_usb: gs_usb_set_timestamp(): remove return statements form void function Remove the return statements from void gs_usb_set_timestamp() function, as it's not generally useful. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-3-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 966e00ea768d..1e08d38b0f96 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -520,8 +520,6 @@ static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us); gs_usb_skb_set_timestamp(dev, skb, timestamp); - - return; } static void gs_usb_receive_bulk_callback(struct urb *urb) -- cgit From b6980ad3a90c73c95cab97e9a33129b8f53e2a5b Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 16:16:33 +0200 Subject: can: gs_usb: uniformly use "parent" as variable name for struct gs_usb To ease readability and maintainability uniformly use the variable name "parent" for the struct gs_usb in the gs_usb driver. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-4-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 62 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 1e08d38b0f96..441143ad740b 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -524,7 +524,7 @@ static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, static void gs_usb_receive_bulk_callback(struct urb *urb) { - struct gs_usb *usbcan = urb->context; + struct gs_usb *parent = urb->context; struct gs_can *dev; struct net_device *netdev; int rc; @@ -535,7 +535,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) struct canfd_frame *cfd; struct sk_buff *skb; - BUG_ON(!usbcan); + BUG_ON(!parent); switch (urb->status) { case 0: /* success */ @@ -552,7 +552,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (hf->channel >= GS_MAX_INTF) goto device_detach; - dev = usbcan->canch[hf->channel]; + dev = parent->canch[hf->channel]; netdev = dev->netdev; stats = &netdev->stats; @@ -644,10 +644,10 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } resubmit_urb: - usb_fill_bulk_urb(urb, usbcan->udev, - usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN), + usb_fill_bulk_urb(urb, parent->udev, + usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN), hf, dev->parent->hf_size_rx, - gs_usb_receive_bulk_callback, usbcan); + gs_usb_receive_bulk_callback, parent); rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -655,8 +655,8 @@ resubmit_urb: if (rc == -ENODEV) { device_detach: for (rc = 0; rc < GS_MAX_INTF; rc++) { - if (usbcan->canch[rc]) - netif_device_detach(usbcan->canch[rc]->netdev); + if (parent->canch[rc]) + netif_device_detach(parent->canch[rc]->netdev); } } } @@ -1369,7 +1369,7 @@ static int gs_usb_probe(struct usb_interface *intf, { struct usb_device *udev = interface_to_usbdev(intf); struct gs_host_frame *hf; - struct gs_usb *dev; + struct gs_usb *parent; struct gs_host_config hconf = { .byte_order = cpu_to_le32(0x0000beef), }; @@ -1412,49 +1412,49 @@ static int gs_usb_probe(struct usb_interface *intf, return -EINVAL; } - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) + parent = kzalloc(sizeof(*parent), GFP_KERNEL); + if (!parent) return -ENOMEM; - init_usb_anchor(&dev->rx_submitted); + init_usb_anchor(&parent->rx_submitted); - usb_set_intfdata(intf, dev); - dev->udev = udev; + usb_set_intfdata(intf, parent); + parent->udev = udev; for (i = 0; i < icount; i++) { unsigned int hf_size_rx = 0; - dev->canch[i] = gs_make_candev(i, intf, &dconf); - if (IS_ERR_OR_NULL(dev->canch[i])) { + parent->canch[i] = gs_make_candev(i, intf, &dconf); + if (IS_ERR_OR_NULL(parent->canch[i])) { /* save error code to return later */ - rc = PTR_ERR(dev->canch[i]); + rc = PTR_ERR(parent->canch[i]); /* on failure destroy previously created candevs */ icount = i; for (i = 0; i < icount; i++) - gs_destroy_candev(dev->canch[i]); + gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&dev->rx_submitted); - kfree(dev); + usb_kill_anchored_urbs(&parent->rx_submitted); + kfree(parent); return rc; } - dev->canch[i]->parent = dev; + parent->canch[i]->parent = parent; /* set RX packet size based on FD and if hardware * timestamps are supported. */ - if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { - if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + if (parent->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, canfd_ts, 1); else hf_size_rx = struct_size(hf, canfd, 1); } else { - if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) hf_size_rx = struct_size(hf, classic_can_ts, 1); else hf_size_rx = struct_size(hf, classic_can, 1); } - dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx); + parent->hf_size_rx = max(parent->hf_size_rx, hf_size_rx); } return 0; @@ -1462,22 +1462,22 @@ static int gs_usb_probe(struct usb_interface *intf, static void gs_usb_disconnect(struct usb_interface *intf) { - struct gs_usb *dev = usb_get_intfdata(intf); + struct gs_usb *parent = usb_get_intfdata(intf); unsigned int i; usb_set_intfdata(intf, NULL); - if (!dev) { + if (!parent) { dev_err(&intf->dev, "Disconnect (nodata)\n"); return; } for (i = 0; i < GS_MAX_INTF; i++) - if (dev->canch[i]) - gs_destroy_candev(dev->canch[i]); + if (parent->canch[i]) + gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&dev->rx_submitted); - kfree(dev); + usb_kill_anchored_urbs(&parent->rx_submitted); + kfree(parent); } static const struct usb_device_id gs_usb_table[] = { -- cgit From fcb880ef2f55b9d50baf42c7efa5c45a9baabea9 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 20:37:20 +0200 Subject: can: gs_usb: gs_usb_receive_bulk_callback(): make use of netdev Make use the previously assigned variable netdev instead of using dev->netdev. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-5-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 441143ad740b..04cbe949c290 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -565,7 +565,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (hf->echo_id == -1) { /* normal rx */ if (hf->flags & GS_CAN_FLAG_FD) { - skb = alloc_canfd_skb(dev->netdev, &cfd); + skb = alloc_canfd_skb(netdev, &cfd); if (!skb) return; @@ -578,7 +578,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) memcpy(cfd->data, hf->canfd->data, cfd->len); } else { - skb = alloc_can_skb(dev->netdev, &cf); + skb = alloc_can_skb(netdev, &cf); if (!skb) return; -- cgit From 55ad95d944251bb53df958e408964be2499603fd Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 20:39:19 +0200 Subject: can: gs_usb: gs_usb_receive_bulk_callback(): make use of stats Make use the previously assigned variable stats instead of using netdev->stats. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-6-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 04cbe949c290..0d0a3405ba19 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -594,8 +594,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_usb_set_timestamp(dev, skb, hf); - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += hf->can_dlc; + stats->rx_packets++; + stats->rx_bytes += hf->can_dlc; netif_rx(skb); } else { /* echo_id == hf->echo_id */ @@ -619,9 +619,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) skb = dev->can.echo_skb[hf->echo_id]; gs_usb_set_timestamp(dev, skb, hf); - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += can_get_echo_skb(netdev, hf->echo_id, - NULL); + stats->tx_packets++; + stats->tx_bytes += can_get_echo_skb(netdev, hf->echo_id, + NULL); gs_free_tx_context(txc); -- cgit From 6c8bc15f02b85bc8f47074110d8fd8caf7a1e42d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 4 Jul 2023 11:23:37 +0200 Subject: can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also in case of OOM In case of an RX overflow error from the CAN controller and an OOM where no skb can be allocated, the error counters are not incremented. Fix this by first incrementing the error counters and then allocate the skb. Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-7-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 0d0a3405ba19..e302d7d568aa 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -631,6 +631,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } if (hf->flags & GS_CAN_FLAG_OVERFLOW) { + stats->rx_over_errors++; + stats->rx_errors++; + skb = alloc_can_err_skb(netdev, &cf); if (!skb) goto resubmit_urb; @@ -638,8 +641,6 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id |= CAN_ERR_CRTL; cf->len = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_over_errors++; - stats->rx_errors++; netif_rx(skb); } -- cgit From 1494ffe4cbe0f97af9c57a4cc37131c8efbe79fc Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Jul 2023 15:49:43 +0200 Subject: can: gs_usb: gs_can_start_xmit(), gs_can_open(): clean up printouts in error path Remove unnecessary "out of memory" message from the error path of gs_can_start_xmit() and gs_can_open(). Convert the printout in case of a failing usb_submit_urb() in gs_can_open() from numbers to human readable error codes. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-8-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index e302d7d568aa..a5cab6a07002 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -741,10 +741,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, goto nomem_urb; hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC); - if (!hf) { - netdev_err(netdev, "No memory left for USB buffer\n"); + if (!hf) goto nomem_hf; - } idx = txc->echo_id; @@ -877,8 +875,6 @@ static int gs_can_open(struct net_device *netdev) buf = kmalloc(dev->parent->hf_size_rx, GFP_KERNEL); if (!buf) { - netdev_err(netdev, - "No memory left for USB buffer\n"); rc = -ENOMEM; goto out_usb_free_urb; } @@ -901,7 +897,8 @@ static int gs_can_open(struct net_device *netdev) netif_device_detach(dev->netdev); netdev_err(netdev, - "usb_submit failed (err=%d)\n", rc); + "usb_submit_urb() failed, error %pe\n", + ERR_PTR(rc)); goto out_usb_unanchor_urb; } -- cgit From 5c6c313acdfc3455b20ac1dc9655aa4afcf51ab1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 8 Feb 2023 10:26:33 +0100 Subject: can: gs_usb: gs_can_close(): don't complain about failed device reset during ndo_stop When the USB device is unplugged, gs_can_close() (which implements the struct net_device_ops::ndo_stop callback) is called. In this function an attempt is made to shut down the USB device with a USB control message. For disconnected devices this will fail and a warning message is printed. Silence the driver by removing the printout of the error message if the reset command fails. Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-9-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index a5cab6a07002..7718f6a4367e 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1029,9 +1029,7 @@ static int gs_can_close(struct net_device *netdev) dev->can.state = CAN_STATE_STOPPED; /* reset the device */ - rc = gs_cmd_reset(dev); - if (rc < 0) - netdev_warn(netdev, "Couldn't shutdown device (err=%d)", rc); + gs_cmd_reset(dev); /* reset tx contexts */ for (rc = 0; rc < GS_MAX_TX_URBS; rc++) { -- cgit From 5391e0cbae02cdf2df501f104c2c7dc0bceeec3d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 11:38:25 +0200 Subject: can: gs_usb: gs_destroy_candev(): remove not needed usb_kill_anchored_urbs() In gs_destroy_candev(), the netdev is unregistered first, then all anchored TX URBs (dev->tx_submitted) are disposed with usb_kill_anchored_urbs(). The call to usb_kill_anchored_urbs() is not needed, as unregister_candev() calls gs_can_close(), which already disposes the TX URBS. Remove not needed call to usb_kill_anchored_urbs() from gs_destroy_candev(). Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-10-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 7718f6a4367e..5a0017b98532 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1356,7 +1356,6 @@ out_free_candev: static void gs_destroy_candev(struct gs_can *dev) { unregister_candev(dev->netdev); - usb_kill_anchored_urbs(&dev->tx_submitted); free_candev(dev->netdev); } -- cgit From d4cfb83d566c56d062a73d94a9fc7ec258a437c2 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Jul 2023 11:38:25 +0200 Subject: can: gs_usb: gs_usb_disconnect(): remove not needed usb_kill_anchored_urbs() In gs_usb_disconnect(), all channels are destroyed first, then all anchored RX URBs (parent->rx_submitted) are disposed with usb_kill_anchored_urbs(). The call to usb_kill_anchored_urbs() is not needed, as gs_destroy_candev() of the last active channel already disposes the RX URBS. Remove not needed call to usb_kill_anchored_urbs() from gs_usb_disconnect(). Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-11-c3b9154ec605@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/gs_usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 5a0017b98532..6caf3974e028 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -1471,7 +1471,6 @@ static void gs_usb_disconnect(struct usb_interface *intf) if (parent->canch[i]) gs_destroy_candev(parent->canch[i]); - usb_kill_anchored_urbs(&parent->rx_submitted); kfree(parent); } -- cgit From 2e3df4a3b3178006d530f4c4d0e91f3d96cddb3c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 2 Jun 2023 09:36:38 +0200 Subject: can: rx-offload: rename rx_offload_get_echo_skb() -> can_rx_offload_get_echo_skb_queue_timestamp() Rename the rx_offload_get_echo_skb() function to can_rx_offload_get_echo_skb_queue_timestamp(), since it inserts the echo skb into the rx-offload queue sorted by timestamp. This is a preparation for adding can_rx_offload_get_echo_skb_queue_tail(), which adds the echo skb to the end of the queue. This is intended for devices that do not support timestamps. Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-1-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/rx-offload.c | 9 +++++---- drivers/net/can/flexcan/flexcan-core.c | 4 ++-- drivers/net/can/m_can/m_can.c | 8 ++++---- drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 6 +++--- drivers/net/can/ti_hecc.c | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 161e45a7e8c1..6e87ad908346 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -240,9 +240,10 @@ int can_rx_offload_queue_timestamp(struct can_rx_offload *offload, } EXPORT_SYMBOL_GPL(can_rx_offload_queue_timestamp); -unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, - unsigned int idx, u32 timestamp, - unsigned int *frame_len_ptr) +unsigned int +can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload, + unsigned int idx, u32 timestamp, + unsigned int *frame_len_ptr) { struct net_device *dev = offload->dev; struct net_device_stats *stats = &dev->stats; @@ -262,7 +263,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, return len; } -EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb); +EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_timestamp); int can_rx_offload_queue_tail(struct can_rx_offload *offload, struct sk_buff *skb) diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index ff0fc18baf13..48273d51f271 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -1097,8 +1097,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) handled = IRQ_HANDLED; stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, 0, - reg_ctrl << 16, NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 0, + reg_ctrl << 16, NULL); stats->tx_packets++; /* after sending a RTR frame MB is in RX mode */ diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index a6263a617ac9..d204703521d2 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1016,10 +1016,10 @@ static void m_can_tx_update_stats(struct m_can_classdev *cdev, if (cdev->is_peripheral) stats->tx_bytes += - can_rx_offload_get_echo_skb(&cdev->offload, - msg_mark, - timestamp, - NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&cdev->offload, + msg_mark, + timestamp, + NULL); else stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL); diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c index 237617b0c125..e5bd57b65aaf 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c @@ -111,9 +111,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, if (skb) mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts); stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, - tef_tail, hw_tef_obj->ts, - frame_len_ptr); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, + tef_tail, hw_tef_obj->ts, + frame_len_ptr); stats->tx_packets++; priv->tef->tail++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index a8243acde92d..5aab440074c6 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -747,8 +747,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&priv->mbx_lock, flags); stamp = hecc_read_stamp(priv, mbxno); stats->tx_bytes += - can_rx_offload_get_echo_skb(&priv->offload, - mbxno, stamp, NULL); + can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, + mbxno, stamp, NULL); stats->tx_packets++; --priv->tx_tail; } -- cgit From 8e0e2950c9ef48f7f40a7175048744ec2390b16e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 3 Jul 2023 18:18:19 +0200 Subject: can: rx-offload: add can_rx_offload_get_echo_skb_queue_tail() Add can_rx_offload_get_echo_skb_queue_tail(). This function addds the echo skb at the end of rx-offload the queue. This is intended for devices without timestamp support. Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-2-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/rx-offload.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 6e87ad908346..77091f7d1fa7 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2014 Protonic Holland, * David Jander - * Copyright (C) 2014-2021 Pengutronix, + * Copyright (C) 2014-2021, 2023 Pengutronix, * Marc Kleine-Budde */ @@ -280,6 +280,31 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload, } EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail); +unsigned int +can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload, + unsigned int idx, + unsigned int *frame_len_ptr) +{ + struct net_device *dev = offload->dev; + struct net_device_stats *stats = &dev->stats; + struct sk_buff *skb; + unsigned int len; + int err; + + skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr); + if (!skb) + return 0; + + err = can_rx_offload_queue_tail(offload, skb); + if (err) { + stats->rx_errors++; + stats->tx_fifo_errors++; + } + + return len; +} +EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_tail); + void can_rx_offload_irq_finish(struct can_rx_offload *offload) { unsigned long flags; -- cgit From 24bc41b4558347672a3db61009c339b1f5692169 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 2 Jun 2023 09:29:07 +0200 Subject: can: gs_usb: convert to NAPI/rx-offload to avoid OoO reception The driver used to pass received CAN frames/skbs to the network stack with netif_rx(). In netif_rx() the skbs are queued to the local CPU. If IRQs are handled in round robin, OoO packets may occur. To avoid out-of-order reception convert the driver from netif_rx() to NAPI. For USB devices with timestamping support use the rx-offload helper can_rx_offload_queue_timestamp() for the RX, and can_rx_offload_get_echo_skb_queue_timestamp() for the TX path. Devices without timestamping support use can_rx_offload_queue_tail() for RX, and can_rx_offload_get_echo_skb_queue_tail() for the TX path. Link: https://lore.kernel.org/all/559D628C.5020100@hartkopp.net Link: https://github.com/candle-usb/candleLight_fw/issues/166 Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-3-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/Kconfig | 1 + drivers/net/can/usb/gs_usb.c | 85 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index 58fcd2b34820..d1450722cb3c 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -52,6 +52,7 @@ config CAN_F81604 config CAN_GS_USB tristate "Geschwister Schneider UG and candleLight compatible interfaces" + select CAN_RX_OFFLOAD help This driver supports the Geschwister Schneider and bytewerk.org candleLight compatible diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 6caf3974e028..95b0fdb602c8 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -5,6 +5,7 @@ * Copyright (C) 2013-2016 Geschwister Schneider Technologie-, * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt). * Copyright (C) 2016 Hubert Denkmair + * Copyright (c) 2023 Pengutronix, Marc Kleine-Budde * * Many thanks to all socketcan devs! */ @@ -24,6 +25,7 @@ #include #include #include +#include /* Device specific constants */ #define USB_GS_USB_1_VENDOR_ID 0x1d50 @@ -282,6 +284,8 @@ struct gs_host_frame { #define GS_MAX_TX_URBS 10 /* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */ #define GS_MAX_RX_URBS 30 +#define GS_NAPI_WEIGHT 32 + /* Maximum number of interfaces the driver supports per device. * Current hardware only supports 3 interfaces. The future may vary. */ @@ -295,6 +299,7 @@ struct gs_tx_context { struct gs_can { struct can_priv can; /* must be the first member */ + struct can_rx_offload offload; struct gs_usb *parent; struct net_device *netdev; @@ -506,20 +511,59 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf) } } -static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, - const struct gs_host_frame *hf) +static u32 gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) { u32 timestamp; - if (!(dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)) - return; - if (hf->flags & GS_CAN_FLAG_FD) timestamp = le32_to_cpu(hf->canfd_ts->timestamp_us); else timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us); - gs_usb_skb_set_timestamp(dev, skb, timestamp); + if (skb) + gs_usb_skb_set_timestamp(dev, skb, timestamp); + + return timestamp; +} + +static void gs_usb_rx_offload(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) +{ + struct can_rx_offload *offload = &dev->offload; + int rc; + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) { + const u32 ts = gs_usb_set_timestamp(dev, skb, hf); + + rc = can_rx_offload_queue_timestamp(offload, skb, ts); + } else { + rc = can_rx_offload_queue_tail(offload, skb); + } + + if (rc) + dev->netdev->stats.rx_fifo_errors++; +} + +static unsigned int +gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) +{ + struct can_rx_offload *offload = &dev->offload; + const u32 echo_id = hf->echo_id; + unsigned int len; + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) { + const u32 ts = gs_usb_set_timestamp(dev, skb, hf); + + len = can_rx_offload_get_echo_skb_queue_timestamp(offload, echo_id, + ts, NULL); + } else { + len = can_rx_offload_get_echo_skb_queue_tail(offload, echo_id, + NULL); + } + + return len; } static void gs_usb_receive_bulk_callback(struct urb *urb) @@ -592,12 +636,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_update_state(dev, cf); } - gs_usb_set_timestamp(dev, skb, hf); - - stats->rx_packets++; - stats->rx_bytes += hf->can_dlc; - - netif_rx(skb); + gs_usb_rx_offload(dev, skb, hf); } else { /* echo_id == hf->echo_id */ if (hf->echo_id >= GS_MAX_TX_URBS) { netdev_err(netdev, @@ -617,12 +656,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } skb = dev->can.echo_skb[hf->echo_id]; - gs_usb_set_timestamp(dev, skb, hf); - stats->tx_packets++; - stats->tx_bytes += can_get_echo_skb(netdev, hf->echo_id, - NULL); - + stats->tx_bytes += gs_usb_get_echo_skb(dev, skb, hf); gs_free_tx_context(txc); atomic_dec(&dev->active_tx_urbs); @@ -641,9 +676,12 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id |= CAN_ERR_CRTL; cf->len = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - netif_rx(skb); + + gs_usb_rx_offload(dev, skb, hf); } + can_rx_offload_irq_finish(&dev->offload); + resubmit_urb: usb_fill_bulk_urb(urb, parent->udev, usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN), @@ -857,6 +895,8 @@ static int gs_can_open(struct net_device *netdev) dev->hf_size_tx = struct_size(hf, classic_can, 1); } + can_rx_offload_enable(&dev->offload); + if (!parent->active_channels) { if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) gs_usb_timestamp_init(parent); @@ -965,6 +1005,7 @@ out_usb_kill_anchored_urbs: gs_usb_timestamp_stop(parent); } + can_rx_offload_disable(&dev->offload); close_candev(netdev); return rc; @@ -1037,6 +1078,8 @@ static int gs_can_close(struct net_device *netdev) dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; } + can_rx_offload_disable(&dev->offload); + /* close the netdev */ close_candev(netdev); @@ -1336,6 +1379,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev->can.data_bittiming_const = &dev->data_bt_const; } + can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT); SET_NETDEV_DEV(netdev, &intf->dev); rc = register_candev(dev->netdev); @@ -1343,11 +1387,13 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev_err(&intf->dev, "Couldn't register candev for channel %d (%pe)\n", channel, ERR_PTR(rc)); - goto out_free_candev; + goto out_can_rx_offload_del; } return dev; +out_can_rx_offload_del: + can_rx_offload_del(&dev->offload); out_free_candev: free_candev(dev->netdev); return ERR_PTR(rc); @@ -1356,6 +1402,7 @@ out_free_candev: static void gs_destroy_candev(struct gs_can *dev) { unregister_candev(dev->netdev); + can_rx_offload_del(&dev->offload); free_candev(dev->netdev); } -- cgit From 0212e5d915a293dcde06415f8c82d31576576a97 Mon Sep 17 00:00:00 2001 From: Joe Damato Date: Tue, 25 Jul 2023 20:56:55 +0000 Subject: net/mlx5: Fix flowhash key set/get for custom RSS mlx5 flow hash field retrieval and set only worked on the default RSS context as of commit f01cc58c18d6 ("net/mlx5e: Support multiple RSS contexts"), not custom RSS contexts. For example, before this patch attempting to retrieve the flow hash fields for RSS context 1 fails: $ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1 Cannot get RX network flow hashing options: Invalid argument This patch fixes getting and setting the flow hash fields for contexts other than the default context. Getting the flow hash fields for RSS context 1: $ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1 For RSS context 1: TCP over IPV4 flows use these fields for computing Hash flow key: IP DA Now, setting the flash hash fields to a custom value: $ sudo ethtool -U eth1 rx-flow-hash tcp4 sdfn context 1 And retrieving them again: $ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1 For RSS context 1: TCP over IPV4 flows use these fields for computing Hash flow key: IP SA IP DA L4 bytes 0 & 1 [TCP/UDP src port] L4 bytes 2 & 3 [TCP/UDP dst port] Signed-off-by: Joe Damato Reviewed-by: Tariq Toukan Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en/rx_res.c | 25 ++++++++++++---- .../net/ethernet/mellanox/mlx5/core/en/rx_res.h | 7 +++-- .../ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 33 ++++++++++++++++------ 3 files changed, 48 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c index e1095bc36543..56e6b8c7501f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c @@ -218,17 +218,32 @@ int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, res->rss_rqns, res->rss_nch); } -u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) +int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, + enum mlx5_traffic_types tt) { - struct mlx5e_rss *rss = res->rss[0]; + struct mlx5e_rss *rss; + + if (rss_idx >= MLX5E_MAX_NUM_RSS) + return -EINVAL; + + rss = res->rss[rss_idx]; + if (!rss) + return -ENOENT; return mlx5e_rss_get_hash_fields(rss, tt); } -int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, - u8 rx_hash_fields) +int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, + enum mlx5_traffic_types tt, u8 rx_hash_fields) { - struct mlx5e_rss *rss = res->rss[0]; + struct mlx5e_rss *rss; + + if (rss_idx >= MLX5E_MAX_NUM_RSS) + return -EINVAL; + + rss = res->rss[rss_idx]; + if (!rss) + return -ENOENT; return mlx5e_rss_set_hash_fields(rss, tt, rx_hash_fields); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h index 5d5f64fab60f..580fe8bc3cd2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h @@ -48,9 +48,10 @@ int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, const u32 *indir, const u8 *key, const u8 *hfunc); -u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); -int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, - u8 rx_hash_fields); +int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, + enum mlx5_traffic_types tt); +int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx, + enum mlx5_traffic_types tt, u8 rx_hash_fields); int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, struct mlx5e_packet_merge_param *pkt_merge_param); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c index aac32e505c14..aed599db9d84 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c @@ -900,10 +900,16 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv, struct ethtool_rxnfc *nfc) { u8 rx_hash_field = 0; + u32 flow_type = 0; + u32 rss_idx = 0; int err; int tt; - tt = flow_type_to_traffic_type(nfc->flow_type); + if (nfc->flow_type & FLOW_RSS) + rss_idx = nfc->rss_context; + + flow_type = flow_type_mask(nfc->flow_type); + tt = flow_type_to_traffic_type(flow_type); if (tt < 0) return tt; @@ -911,10 +917,10 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv, * on src IP, dest IP, TCP/UDP src port and TCP/UDP dest * port. */ - if (nfc->flow_type != TCP_V4_FLOW && - nfc->flow_type != TCP_V6_FLOW && - nfc->flow_type != UDP_V4_FLOW && - nfc->flow_type != UDP_V6_FLOW) + if (flow_type != TCP_V4_FLOW && + flow_type != TCP_V6_FLOW && + flow_type != UDP_V4_FLOW && + flow_type != UDP_V6_FLOW) return -EOPNOTSUPP; if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | @@ -931,7 +937,7 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv, rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_DPORT; mutex_lock(&priv->state_lock); - err = mlx5e_rx_res_rss_set_hash_fields(priv->rx_res, tt, rx_hash_field); + err = mlx5e_rx_res_rss_set_hash_fields(priv->rx_res, rss_idx, tt, rx_hash_field); mutex_unlock(&priv->state_lock); return err; @@ -940,14 +946,23 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv, static int mlx5e_get_rss_hash_opt(struct mlx5e_priv *priv, struct ethtool_rxnfc *nfc) { - u32 hash_field = 0; + int hash_field = 0; + u32 flow_type = 0; + u32 rss_idx = 0; int tt; - tt = flow_type_to_traffic_type(nfc->flow_type); + if (nfc->flow_type & FLOW_RSS) + rss_idx = nfc->rss_context; + + flow_type = flow_type_mask(nfc->flow_type); + tt = flow_type_to_traffic_type(flow_type); if (tt < 0) return tt; - hash_field = mlx5e_rx_res_rss_get_hash_fields(priv->rx_res, tt); + hash_field = mlx5e_rx_res_rss_get_hash_fields(priv->rx_res, rss_idx, tt); + if (hash_field < 0) + return hash_field; + nfc->data = 0; if (hash_field & MLX5_HASH_FIELD_SEL_SRC_IP) -- cgit From 806521bc48aac06d8aa22a9e1d8b5bdf2377bbdc Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:40:43 +0100 Subject: sfc: Remove falcon references Siena was using functions from the Falcon architecture. These start with the efx_farch prefix. Now that both of these are in separate modules the references are no longer used in the sfc.ko module. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/farch_regs.h | 2929 --------------------------------- drivers/net/ethernet/sfc/mcdi.c | 1 - drivers/net/ethernet/sfc/net_driver.h | 5 +- drivers/net/ethernet/sfc/nic.c | 153 -- drivers/net/ethernet/sfc/nic.h | 83 - drivers/net/ethernet/sfc/ptp.c | 1 - 6 files changed, 2 insertions(+), 3170 deletions(-) delete mode 100644 drivers/net/ethernet/sfc/farch_regs.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/farch_regs.h b/drivers/net/ethernet/sfc/farch_regs.h deleted file mode 100644 index d138be423e63..000000000000 --- a/drivers/net/ethernet/sfc/farch_regs.h +++ /dev/null @@ -1,2929 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/**************************************************************************** - * Driver for Solarflare network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2012 Solarflare Communications Inc. - */ - -#ifndef EFX_FARCH_REGS_H -#define EFX_FARCH_REGS_H - -/* - * Falcon hardware architecture definitions have a name prefix following - * the format: - * - * F__ - * - * The following strings are used: - * - * MMIO register MC register Host memory structure - * ------------------------------------------------------------- - * Address R MCR - * Bitfield RF MCRF SF - * Enumerator FE MCFE SE - * - * is the first revision to which the definition applies: - * - * A: Falcon A1 (SFC4000AB) - * B: Falcon B0 (SFC4000BA) - * C: Siena A0 (SFL9021AA) - * - * If the definition has been changed or removed in later revisions - * then is the last revision to which the definition applies; - * otherwise it is "Z". - */ - -/************************************************************************** - * - * Falcon/Siena registers and descriptors - * - ************************************************************************** - */ - -/* ADR_REGION_REG: Address region register */ -#define FR_AZ_ADR_REGION 0x00000000 -#define FRF_AZ_ADR_REGION3_LBN 96 -#define FRF_AZ_ADR_REGION3_WIDTH 18 -#define FRF_AZ_ADR_REGION2_LBN 64 -#define FRF_AZ_ADR_REGION2_WIDTH 18 -#define FRF_AZ_ADR_REGION1_LBN 32 -#define FRF_AZ_ADR_REGION1_WIDTH 18 -#define FRF_AZ_ADR_REGION0_LBN 0 -#define FRF_AZ_ADR_REGION0_WIDTH 18 - -/* INT_EN_REG_KER: Kernel driver Interrupt enable register */ -#define FR_AZ_INT_EN_KER 0x00000010 -#define FRF_AZ_KER_INT_LEVE_SEL_LBN 8 -#define FRF_AZ_KER_INT_LEVE_SEL_WIDTH 6 -#define FRF_AZ_KER_INT_CHAR_LBN 4 -#define FRF_AZ_KER_INT_CHAR_WIDTH 1 -#define FRF_AZ_KER_INT_KER_LBN 3 -#define FRF_AZ_KER_INT_KER_WIDTH 1 -#define FRF_AZ_DRV_INT_EN_KER_LBN 0 -#define FRF_AZ_DRV_INT_EN_KER_WIDTH 1 - -/* INT_EN_REG_CHAR: Char Driver interrupt enable register */ -#define FR_BZ_INT_EN_CHAR 0x00000020 -#define FRF_BZ_CHAR_INT_LEVE_SEL_LBN 8 -#define FRF_BZ_CHAR_INT_LEVE_SEL_WIDTH 6 -#define FRF_BZ_CHAR_INT_CHAR_LBN 4 -#define FRF_BZ_CHAR_INT_CHAR_WIDTH 1 -#define FRF_BZ_CHAR_INT_KER_LBN 3 -#define FRF_BZ_CHAR_INT_KER_WIDTH 1 -#define FRF_BZ_DRV_INT_EN_CHAR_LBN 0 -#define FRF_BZ_DRV_INT_EN_CHAR_WIDTH 1 - -/* INT_ADR_REG_KER: Interrupt host address for Kernel driver */ -#define FR_AZ_INT_ADR_KER 0x00000030 -#define FRF_AZ_NORM_INT_VEC_DIS_KER_LBN 64 -#define FRF_AZ_NORM_INT_VEC_DIS_KER_WIDTH 1 -#define FRF_AZ_INT_ADR_KER_LBN 0 -#define FRF_AZ_INT_ADR_KER_WIDTH 64 - -/* INT_ADR_REG_CHAR: Interrupt host address for Char driver */ -#define FR_BZ_INT_ADR_CHAR 0x00000040 -#define FRF_BZ_NORM_INT_VEC_DIS_CHAR_LBN 64 -#define FRF_BZ_NORM_INT_VEC_DIS_CHAR_WIDTH 1 -#define FRF_BZ_INT_ADR_CHAR_LBN 0 -#define FRF_BZ_INT_ADR_CHAR_WIDTH 64 - -/* INT_ACK_KER: Kernel interrupt acknowledge register */ -#define FR_AA_INT_ACK_KER 0x00000050 -#define FRF_AA_INT_ACK_KER_FIELD_LBN 0 -#define FRF_AA_INT_ACK_KER_FIELD_WIDTH 32 - -/* INT_ISR0_REG: Function 0 Interrupt Acknowledge Status register */ -#define FR_BZ_INT_ISR0 0x00000090 -#define FRF_BZ_INT_ISR_REG_LBN 0 -#define FRF_BZ_INT_ISR_REG_WIDTH 64 - -/* HW_INIT_REG: Hardware initialization register */ -#define FR_AZ_HW_INIT 0x000000c0 -#define FRF_BB_BDMRD_CPLF_FULL_LBN 124 -#define FRF_BB_BDMRD_CPLF_FULL_WIDTH 1 -#define FRF_BB_PCIE_CPL_TIMEOUT_CTRL_LBN 121 -#define FRF_BB_PCIE_CPL_TIMEOUT_CTRL_WIDTH 3 -#define FRF_CZ_TX_MRG_TAGS_LBN 120 -#define FRF_CZ_TX_MRG_TAGS_WIDTH 1 -#define FRF_AB_TRGT_MASK_ALL_LBN 100 -#define FRF_AB_TRGT_MASK_ALL_WIDTH 1 -#define FRF_AZ_DOORBELL_DROP_LBN 92 -#define FRF_AZ_DOORBELL_DROP_WIDTH 8 -#define FRF_AB_TX_RREQ_MASK_EN_LBN 76 -#define FRF_AB_TX_RREQ_MASK_EN_WIDTH 1 -#define FRF_AB_PE_EIDLE_DIS_LBN 75 -#define FRF_AB_PE_EIDLE_DIS_WIDTH 1 -#define FRF_AA_FC_BLOCKING_EN_LBN 45 -#define FRF_AA_FC_BLOCKING_EN_WIDTH 1 -#define FRF_BZ_B2B_REQ_EN_LBN 45 -#define FRF_BZ_B2B_REQ_EN_WIDTH 1 -#define FRF_AA_B2B_REQ_EN_LBN 44 -#define FRF_AA_B2B_REQ_EN_WIDTH 1 -#define FRF_BB_FC_BLOCKING_EN_LBN 44 -#define FRF_BB_FC_BLOCKING_EN_WIDTH 1 -#define FRF_AZ_POST_WR_MASK_LBN 40 -#define FRF_AZ_POST_WR_MASK_WIDTH 4 -#define FRF_AZ_TLP_TC_LBN 34 -#define FRF_AZ_TLP_TC_WIDTH 3 -#define FRF_AZ_TLP_ATTR_LBN 32 -#define FRF_AZ_TLP_ATTR_WIDTH 2 -#define FRF_AB_INTB_VEC_LBN 24 -#define FRF_AB_INTB_VEC_WIDTH 5 -#define FRF_AB_INTA_VEC_LBN 16 -#define FRF_AB_INTA_VEC_WIDTH 5 -#define FRF_AZ_WD_TIMER_LBN 8 -#define FRF_AZ_WD_TIMER_WIDTH 8 -#define FRF_AZ_US_DISABLE_LBN 5 -#define FRF_AZ_US_DISABLE_WIDTH 1 -#define FRF_AZ_TLP_EP_LBN 4 -#define FRF_AZ_TLP_EP_WIDTH 1 -#define FRF_AZ_ATTR_SEL_LBN 3 -#define FRF_AZ_ATTR_SEL_WIDTH 1 -#define FRF_AZ_TD_SEL_LBN 1 -#define FRF_AZ_TD_SEL_WIDTH 1 -#define FRF_AZ_TLP_TD_LBN 0 -#define FRF_AZ_TLP_TD_WIDTH 1 - -/* EE_SPI_HCMD_REG: SPI host command register */ -#define FR_AB_EE_SPI_HCMD 0x00000100 -#define FRF_AB_EE_SPI_HCMD_CMD_EN_LBN 31 -#define FRF_AB_EE_SPI_HCMD_CMD_EN_WIDTH 1 -#define FRF_AB_EE_WR_TIMER_ACTIVE_LBN 28 -#define FRF_AB_EE_WR_TIMER_ACTIVE_WIDTH 1 -#define FRF_AB_EE_SPI_HCMD_SF_SEL_LBN 24 -#define FRF_AB_EE_SPI_HCMD_SF_SEL_WIDTH 1 -#define FRF_AB_EE_SPI_HCMD_DABCNT_LBN 16 -#define FRF_AB_EE_SPI_HCMD_DABCNT_WIDTH 5 -#define FRF_AB_EE_SPI_HCMD_READ_LBN 15 -#define FRF_AB_EE_SPI_HCMD_READ_WIDTH 1 -#define FRF_AB_EE_SPI_HCMD_DUBCNT_LBN 12 -#define FRF_AB_EE_SPI_HCMD_DUBCNT_WIDTH 2 -#define FRF_AB_EE_SPI_HCMD_ADBCNT_LBN 8 -#define FRF_AB_EE_SPI_HCMD_ADBCNT_WIDTH 2 -#define FRF_AB_EE_SPI_HCMD_ENC_LBN 0 -#define FRF_AB_EE_SPI_HCMD_ENC_WIDTH 8 - -/* USR_EV_CFG: User Level Event Configuration register */ -#define FR_CZ_USR_EV_CFG 0x00000100 -#define FRF_CZ_USREV_DIS_LBN 16 -#define FRF_CZ_USREV_DIS_WIDTH 1 -#define FRF_CZ_DFLT_EVQ_LBN 0 -#define FRF_CZ_DFLT_EVQ_WIDTH 10 - -/* EE_SPI_HADR_REG: SPI host address register */ -#define FR_AB_EE_SPI_HADR 0x00000110 -#define FRF_AB_EE_SPI_HADR_DUBYTE_LBN 24 -#define FRF_AB_EE_SPI_HADR_DUBYTE_WIDTH 8 -#define FRF_AB_EE_SPI_HADR_ADR_LBN 0 -#define FRF_AB_EE_SPI_HADR_ADR_WIDTH 24 - -/* EE_SPI_HDATA_REG: SPI host data register */ -#define FR_AB_EE_SPI_HDATA 0x00000120 -#define FRF_AB_EE_SPI_HDATA3_LBN 96 -#define FRF_AB_EE_SPI_HDATA3_WIDTH 32 -#define FRF_AB_EE_SPI_HDATA2_LBN 64 -#define FRF_AB_EE_SPI_HDATA2_WIDTH 32 -#define FRF_AB_EE_SPI_HDATA1_LBN 32 -#define FRF_AB_EE_SPI_HDATA1_WIDTH 32 -#define FRF_AB_EE_SPI_HDATA0_LBN 0 -#define FRF_AB_EE_SPI_HDATA0_WIDTH 32 - -/* EE_BASE_PAGE_REG: Expansion ROM base mirror register */ -#define FR_AB_EE_BASE_PAGE 0x00000130 -#define FRF_AB_EE_EXPROM_MASK_LBN 16 -#define FRF_AB_EE_EXPROM_MASK_WIDTH 13 -#define FRF_AB_EE_EXP_ROM_WINDOW_BASE_LBN 0 -#define FRF_AB_EE_EXP_ROM_WINDOW_BASE_WIDTH 13 - -/* EE_VPD_CFG0_REG: SPI/VPD configuration register 0 */ -#define FR_AB_EE_VPD_CFG0 0x00000140 -#define FRF_AB_EE_SF_FASTRD_EN_LBN 127 -#define FRF_AB_EE_SF_FASTRD_EN_WIDTH 1 -#define FRF_AB_EE_SF_CLOCK_DIV_LBN 120 -#define FRF_AB_EE_SF_CLOCK_DIV_WIDTH 7 -#define FRF_AB_EE_VPD_WIP_POLL_LBN 119 -#define FRF_AB_EE_VPD_WIP_POLL_WIDTH 1 -#define FRF_AB_EE_EE_CLOCK_DIV_LBN 112 -#define FRF_AB_EE_EE_CLOCK_DIV_WIDTH 7 -#define FRF_AB_EE_EE_WR_TMR_VALUE_LBN 96 -#define FRF_AB_EE_EE_WR_TMR_VALUE_WIDTH 16 -#define FRF_AB_EE_VPDW_LENGTH_LBN 80 -#define FRF_AB_EE_VPDW_LENGTH_WIDTH 15 -#define FRF_AB_EE_VPDW_BASE_LBN 64 -#define FRF_AB_EE_VPDW_BASE_WIDTH 15 -#define FRF_AB_EE_VPD_WR_CMD_EN_LBN 56 -#define FRF_AB_EE_VPD_WR_CMD_EN_WIDTH 8 -#define FRF_AB_EE_VPD_BASE_LBN 32 -#define FRF_AB_EE_VPD_BASE_WIDTH 24 -#define FRF_AB_EE_VPD_LENGTH_LBN 16 -#define FRF_AB_EE_VPD_LENGTH_WIDTH 15 -#define FRF_AB_EE_VPD_AD_SIZE_LBN 8 -#define FRF_AB_EE_VPD_AD_SIZE_WIDTH 5 -#define FRF_AB_EE_VPD_ACCESS_ON_LBN 5 -#define FRF_AB_EE_VPD_ACCESS_ON_WIDTH 1 -#define FRF_AB_EE_VPD_ACCESS_BLOCK_LBN 4 -#define FRF_AB_EE_VPD_ACCESS_BLOCK_WIDTH 1 -#define FRF_AB_EE_VPD_DEV_SF_SEL_LBN 2 -#define FRF_AB_EE_VPD_DEV_SF_SEL_WIDTH 1 -#define FRF_AB_EE_VPD_EN_AD9_MODE_LBN 1 -#define FRF_AB_EE_VPD_EN_AD9_MODE_WIDTH 1 -#define FRF_AB_EE_VPD_EN_LBN 0 -#define FRF_AB_EE_VPD_EN_WIDTH 1 - -/* EE_VPD_SW_CNTL_REG: VPD access SW control register */ -#define FR_AB_EE_VPD_SW_CNTL 0x00000150 -#define FRF_AB_EE_VPD_CYCLE_PENDING_LBN 31 -#define FRF_AB_EE_VPD_CYCLE_PENDING_WIDTH 1 -#define FRF_AB_EE_VPD_CYC_WRITE_LBN 28 -#define FRF_AB_EE_VPD_CYC_WRITE_WIDTH 1 -#define FRF_AB_EE_VPD_CYC_ADR_LBN 0 -#define FRF_AB_EE_VPD_CYC_ADR_WIDTH 15 - -/* EE_VPD_SW_DATA_REG: VPD access SW data register */ -#define FR_AB_EE_VPD_SW_DATA 0x00000160 -#define FRF_AB_EE_VPD_CYC_DAT_LBN 0 -#define FRF_AB_EE_VPD_CYC_DAT_WIDTH 32 - -/* PBMX_DBG_IADDR_REG: Capture Module address register */ -#define FR_CZ_PBMX_DBG_IADDR 0x000001f0 -#define FRF_CZ_PBMX_DBG_IADDR_LBN 0 -#define FRF_CZ_PBMX_DBG_IADDR_WIDTH 32 - -/* PCIE_CORE_INDIRECT_REG: Indirect Access to PCIE Core registers */ -#define FR_BB_PCIE_CORE_INDIRECT 0x000001f0 -#define FRF_BB_PCIE_CORE_TARGET_DATA_LBN 32 -#define FRF_BB_PCIE_CORE_TARGET_DATA_WIDTH 32 -#define FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_LBN 15 -#define FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_WIDTH 1 -#define FRF_BB_PCIE_CORE_TARGET_REG_ADRS_LBN 0 -#define FRF_BB_PCIE_CORE_TARGET_REG_ADRS_WIDTH 12 - -/* PBMX_DBG_IDATA_REG: Capture Module data register */ -#define FR_CZ_PBMX_DBG_IDATA 0x000001f8 -#define FRF_CZ_PBMX_DBG_IDATA_LBN 0 -#define FRF_CZ_PBMX_DBG_IDATA_WIDTH 64 - -/* NIC_STAT_REG: NIC status register */ -#define FR_AB_NIC_STAT 0x00000200 -#define FRF_BB_AER_DIS_LBN 34 -#define FRF_BB_AER_DIS_WIDTH 1 -#define FRF_BB_EE_STRAP_EN_LBN 31 -#define FRF_BB_EE_STRAP_EN_WIDTH 1 -#define FRF_BB_EE_STRAP_LBN 24 -#define FRF_BB_EE_STRAP_WIDTH 4 -#define FRF_BB_REVISION_ID_LBN 17 -#define FRF_BB_REVISION_ID_WIDTH 7 -#define FRF_AB_ONCHIP_SRAM_LBN 16 -#define FRF_AB_ONCHIP_SRAM_WIDTH 1 -#define FRF_AB_SF_PRST_LBN 9 -#define FRF_AB_SF_PRST_WIDTH 1 -#define FRF_AB_EE_PRST_LBN 8 -#define FRF_AB_EE_PRST_WIDTH 1 -#define FRF_AB_ATE_MODE_LBN 3 -#define FRF_AB_ATE_MODE_WIDTH 1 -#define FRF_AB_STRAP_PINS_LBN 0 -#define FRF_AB_STRAP_PINS_WIDTH 3 - -/* GPIO_CTL_REG: GPIO control register */ -#define FR_AB_GPIO_CTL 0x00000210 -#define FRF_AB_GPIO_OUT3_LBN 112 -#define FRF_AB_GPIO_OUT3_WIDTH 16 -#define FRF_AB_GPIO_IN3_LBN 104 -#define FRF_AB_GPIO_IN3_WIDTH 8 -#define FRF_AB_GPIO_PWRUP_VALUE3_LBN 96 -#define FRF_AB_GPIO_PWRUP_VALUE3_WIDTH 8 -#define FRF_AB_GPIO_OUT2_LBN 80 -#define FRF_AB_GPIO_OUT2_WIDTH 16 -#define FRF_AB_GPIO_IN2_LBN 72 -#define FRF_AB_GPIO_IN2_WIDTH 8 -#define FRF_AB_GPIO_PWRUP_VALUE2_LBN 64 -#define FRF_AB_GPIO_PWRUP_VALUE2_WIDTH 8 -#define FRF_AB_GPIO15_OEN_LBN 63 -#define FRF_AB_GPIO15_OEN_WIDTH 1 -#define FRF_AB_GPIO14_OEN_LBN 62 -#define FRF_AB_GPIO14_OEN_WIDTH 1 -#define FRF_AB_GPIO13_OEN_LBN 61 -#define FRF_AB_GPIO13_OEN_WIDTH 1 -#define FRF_AB_GPIO12_OEN_LBN 60 -#define FRF_AB_GPIO12_OEN_WIDTH 1 -#define FRF_AB_GPIO11_OEN_LBN 59 -#define FRF_AB_GPIO11_OEN_WIDTH 1 -#define FRF_AB_GPIO10_OEN_LBN 58 -#define FRF_AB_GPIO10_OEN_WIDTH 1 -#define FRF_AB_GPIO9_OEN_LBN 57 -#define FRF_AB_GPIO9_OEN_WIDTH 1 -#define FRF_AB_GPIO8_OEN_LBN 56 -#define FRF_AB_GPIO8_OEN_WIDTH 1 -#define FRF_AB_GPIO15_OUT_LBN 55 -#define FRF_AB_GPIO15_OUT_WIDTH 1 -#define FRF_AB_GPIO14_OUT_LBN 54 -#define FRF_AB_GPIO14_OUT_WIDTH 1 -#define FRF_AB_GPIO13_OUT_LBN 53 -#define FRF_AB_GPIO13_OUT_WIDTH 1 -#define FRF_AB_GPIO12_OUT_LBN 52 -#define FRF_AB_GPIO12_OUT_WIDTH 1 -#define FRF_AB_GPIO11_OUT_LBN 51 -#define FRF_AB_GPIO11_OUT_WIDTH 1 -#define FRF_AB_GPIO10_OUT_LBN 50 -#define FRF_AB_GPIO10_OUT_WIDTH 1 -#define FRF_AB_GPIO9_OUT_LBN 49 -#define FRF_AB_GPIO9_OUT_WIDTH 1 -#define FRF_AB_GPIO8_OUT_LBN 48 -#define FRF_AB_GPIO8_OUT_WIDTH 1 -#define FRF_AB_GPIO15_IN_LBN 47 -#define FRF_AB_GPIO15_IN_WIDTH 1 -#define FRF_AB_GPIO14_IN_LBN 46 -#define FRF_AB_GPIO14_IN_WIDTH 1 -#define FRF_AB_GPIO13_IN_LBN 45 -#define FRF_AB_GPIO13_IN_WIDTH 1 -#define FRF_AB_GPIO12_IN_LBN 44 -#define FRF_AB_GPIO12_IN_WIDTH 1 -#define FRF_AB_GPIO11_IN_LBN 43 -#define FRF_AB_GPIO11_IN_WIDTH 1 -#define FRF_AB_GPIO10_IN_LBN 42 -#define FRF_AB_GPIO10_IN_WIDTH 1 -#define FRF_AB_GPIO9_IN_LBN 41 -#define FRF_AB_GPIO9_IN_WIDTH 1 -#define FRF_AB_GPIO8_IN_LBN 40 -#define FRF_AB_GPIO8_IN_WIDTH 1 -#define FRF_AB_GPIO15_PWRUP_VALUE_LBN 39 -#define FRF_AB_GPIO15_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO14_PWRUP_VALUE_LBN 38 -#define FRF_AB_GPIO14_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO13_PWRUP_VALUE_LBN 37 -#define FRF_AB_GPIO13_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO12_PWRUP_VALUE_LBN 36 -#define FRF_AB_GPIO12_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO11_PWRUP_VALUE_LBN 35 -#define FRF_AB_GPIO11_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO10_PWRUP_VALUE_LBN 34 -#define FRF_AB_GPIO10_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO9_PWRUP_VALUE_LBN 33 -#define FRF_AB_GPIO9_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO8_PWRUP_VALUE_LBN 32 -#define FRF_AB_GPIO8_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_CLK156_OUT_EN_LBN 31 -#define FRF_AB_CLK156_OUT_EN_WIDTH 1 -#define FRF_AB_USE_NIC_CLK_LBN 30 -#define FRF_AB_USE_NIC_CLK_WIDTH 1 -#define FRF_AB_GPIO5_OEN_LBN 29 -#define FRF_AB_GPIO5_OEN_WIDTH 1 -#define FRF_AB_GPIO4_OEN_LBN 28 -#define FRF_AB_GPIO4_OEN_WIDTH 1 -#define FRF_AB_GPIO3_OEN_LBN 27 -#define FRF_AB_GPIO3_OEN_WIDTH 1 -#define FRF_AB_GPIO2_OEN_LBN 26 -#define FRF_AB_GPIO2_OEN_WIDTH 1 -#define FRF_AB_GPIO1_OEN_LBN 25 -#define FRF_AB_GPIO1_OEN_WIDTH 1 -#define FRF_AB_GPIO0_OEN_LBN 24 -#define FRF_AB_GPIO0_OEN_WIDTH 1 -#define FRF_AB_GPIO7_OUT_LBN 23 -#define FRF_AB_GPIO7_OUT_WIDTH 1 -#define FRF_AB_GPIO6_OUT_LBN 22 -#define FRF_AB_GPIO6_OUT_WIDTH 1 -#define FRF_AB_GPIO5_OUT_LBN 21 -#define FRF_AB_GPIO5_OUT_WIDTH 1 -#define FRF_AB_GPIO4_OUT_LBN 20 -#define FRF_AB_GPIO4_OUT_WIDTH 1 -#define FRF_AB_GPIO3_OUT_LBN 19 -#define FRF_AB_GPIO3_OUT_WIDTH 1 -#define FRF_AB_GPIO2_OUT_LBN 18 -#define FRF_AB_GPIO2_OUT_WIDTH 1 -#define FRF_AB_GPIO1_OUT_LBN 17 -#define FRF_AB_GPIO1_OUT_WIDTH 1 -#define FRF_AB_GPIO0_OUT_LBN 16 -#define FRF_AB_GPIO0_OUT_WIDTH 1 -#define FRF_AB_GPIO7_IN_LBN 15 -#define FRF_AB_GPIO7_IN_WIDTH 1 -#define FRF_AB_GPIO6_IN_LBN 14 -#define FRF_AB_GPIO6_IN_WIDTH 1 -#define FRF_AB_GPIO5_IN_LBN 13 -#define FRF_AB_GPIO5_IN_WIDTH 1 -#define FRF_AB_GPIO4_IN_LBN 12 -#define FRF_AB_GPIO4_IN_WIDTH 1 -#define FRF_AB_GPIO3_IN_LBN 11 -#define FRF_AB_GPIO3_IN_WIDTH 1 -#define FRF_AB_GPIO2_IN_LBN 10 -#define FRF_AB_GPIO2_IN_WIDTH 1 -#define FRF_AB_GPIO1_IN_LBN 9 -#define FRF_AB_GPIO1_IN_WIDTH 1 -#define FRF_AB_GPIO0_IN_LBN 8 -#define FRF_AB_GPIO0_IN_WIDTH 1 -#define FRF_AB_GPIO7_PWRUP_VALUE_LBN 7 -#define FRF_AB_GPIO7_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO6_PWRUP_VALUE_LBN 6 -#define FRF_AB_GPIO6_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO5_PWRUP_VALUE_LBN 5 -#define FRF_AB_GPIO5_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO4_PWRUP_VALUE_LBN 4 -#define FRF_AB_GPIO4_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO3_PWRUP_VALUE_LBN 3 -#define FRF_AB_GPIO3_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO2_PWRUP_VALUE_LBN 2 -#define FRF_AB_GPIO2_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO1_PWRUP_VALUE_LBN 1 -#define FRF_AB_GPIO1_PWRUP_VALUE_WIDTH 1 -#define FRF_AB_GPIO0_PWRUP_VALUE_LBN 0 -#define FRF_AB_GPIO0_PWRUP_VALUE_WIDTH 1 - -/* GLB_CTL_REG: Global control register */ -#define FR_AB_GLB_CTL 0x00000220 -#define FRF_AB_EXT_PHY_RST_CTL_LBN 63 -#define FRF_AB_EXT_PHY_RST_CTL_WIDTH 1 -#define FRF_AB_XAUI_SD_RST_CTL_LBN 62 -#define FRF_AB_XAUI_SD_RST_CTL_WIDTH 1 -#define FRF_AB_PCIE_SD_RST_CTL_LBN 61 -#define FRF_AB_PCIE_SD_RST_CTL_WIDTH 1 -#define FRF_AA_PCIX_RST_CTL_LBN 60 -#define FRF_AA_PCIX_RST_CTL_WIDTH 1 -#define FRF_BB_BIU_RST_CTL_LBN 60 -#define FRF_BB_BIU_RST_CTL_WIDTH 1 -#define FRF_AB_PCIE_STKY_RST_CTL_LBN 59 -#define FRF_AB_PCIE_STKY_RST_CTL_WIDTH 1 -#define FRF_AB_PCIE_NSTKY_RST_CTL_LBN 58 -#define FRF_AB_PCIE_NSTKY_RST_CTL_WIDTH 1 -#define FRF_AB_PCIE_CORE_RST_CTL_LBN 57 -#define FRF_AB_PCIE_CORE_RST_CTL_WIDTH 1 -#define FRF_AB_XGRX_RST_CTL_LBN 56 -#define FRF_AB_XGRX_RST_CTL_WIDTH 1 -#define FRF_AB_XGTX_RST_CTL_LBN 55 -#define FRF_AB_XGTX_RST_CTL_WIDTH 1 -#define FRF_AB_EM_RST_CTL_LBN 54 -#define FRF_AB_EM_RST_CTL_WIDTH 1 -#define FRF_AB_EV_RST_CTL_LBN 53 -#define FRF_AB_EV_RST_CTL_WIDTH 1 -#define FRF_AB_SR_RST_CTL_LBN 52 -#define FRF_AB_SR_RST_CTL_WIDTH 1 -#define FRF_AB_RX_RST_CTL_LBN 51 -#define FRF_AB_RX_RST_CTL_WIDTH 1 -#define FRF_AB_TX_RST_CTL_LBN 50 -#define FRF_AB_TX_RST_CTL_WIDTH 1 -#define FRF_AB_EE_RST_CTL_LBN 49 -#define FRF_AB_EE_RST_CTL_WIDTH 1 -#define FRF_AB_CS_RST_CTL_LBN 48 -#define FRF_AB_CS_RST_CTL_WIDTH 1 -#define FRF_AB_HOT_RST_CTL_LBN 40 -#define FRF_AB_HOT_RST_CTL_WIDTH 2 -#define FRF_AB_RST_EXT_PHY_LBN 31 -#define FRF_AB_RST_EXT_PHY_WIDTH 1 -#define FRF_AB_RST_XAUI_SD_LBN 30 -#define FRF_AB_RST_XAUI_SD_WIDTH 1 -#define FRF_AB_RST_PCIE_SD_LBN 29 -#define FRF_AB_RST_PCIE_SD_WIDTH 1 -#define FRF_AA_RST_PCIX_LBN 28 -#define FRF_AA_RST_PCIX_WIDTH 1 -#define FRF_BB_RST_BIU_LBN 28 -#define FRF_BB_RST_BIU_WIDTH 1 -#define FRF_AB_RST_PCIE_STKY_LBN 27 -#define FRF_AB_RST_PCIE_STKY_WIDTH 1 -#define FRF_AB_RST_PCIE_NSTKY_LBN 26 -#define FRF_AB_RST_PCIE_NSTKY_WIDTH 1 -#define FRF_AB_RST_PCIE_CORE_LBN 25 -#define FRF_AB_RST_PCIE_CORE_WIDTH 1 -#define FRF_AB_RST_XGRX_LBN 24 -#define FRF_AB_RST_XGRX_WIDTH 1 -#define FRF_AB_RST_XGTX_LBN 23 -#define FRF_AB_RST_XGTX_WIDTH 1 -#define FRF_AB_RST_EM_LBN 22 -#define FRF_AB_RST_EM_WIDTH 1 -#define FRF_AB_RST_EV_LBN 21 -#define FRF_AB_RST_EV_WIDTH 1 -#define FRF_AB_RST_SR_LBN 20 -#define FRF_AB_RST_SR_WIDTH 1 -#define FRF_AB_RST_RX_LBN 19 -#define FRF_AB_RST_RX_WIDTH 1 -#define FRF_AB_RST_TX_LBN 18 -#define FRF_AB_RST_TX_WIDTH 1 -#define FRF_AB_RST_SF_LBN 17 -#define FRF_AB_RST_SF_WIDTH 1 -#define FRF_AB_RST_CS_LBN 16 -#define FRF_AB_RST_CS_WIDTH 1 -#define FRF_AB_INT_RST_DUR_LBN 4 -#define FRF_AB_INT_RST_DUR_WIDTH 3 -#define FRF_AB_EXT_PHY_RST_DUR_LBN 1 -#define FRF_AB_EXT_PHY_RST_DUR_WIDTH 3 -#define FFE_AB_EXT_PHY_RST_DUR_10240US 7 -#define FFE_AB_EXT_PHY_RST_DUR_5120US 6 -#define FFE_AB_EXT_PHY_RST_DUR_2560US 5 -#define FFE_AB_EXT_PHY_RST_DUR_1280US 4 -#define FFE_AB_EXT_PHY_RST_DUR_640US 3 -#define FFE_AB_EXT_PHY_RST_DUR_320US 2 -#define FFE_AB_EXT_PHY_RST_DUR_160US 1 -#define FFE_AB_EXT_PHY_RST_DUR_80US 0 -#define FRF_AB_SWRST_LBN 0 -#define FRF_AB_SWRST_WIDTH 1 - -/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */ -#define FR_AZ_FATAL_INTR_KER 0x00000230 -#define FRF_CZ_SRAM_PERR_INT_P_KER_EN_LBN 44 -#define FRF_CZ_SRAM_PERR_INT_P_KER_EN_WIDTH 1 -#define FRF_AB_PCI_BUSERR_INT_KER_EN_LBN 43 -#define FRF_AB_PCI_BUSERR_INT_KER_EN_WIDTH 1 -#define FRF_CZ_MBU_PERR_INT_KER_EN_LBN 43 -#define FRF_CZ_MBU_PERR_INT_KER_EN_WIDTH 1 -#define FRF_AZ_SRAM_OOB_INT_KER_EN_LBN 42 -#define FRF_AZ_SRAM_OOB_INT_KER_EN_WIDTH 1 -#define FRF_AZ_BUFID_OOB_INT_KER_EN_LBN 41 -#define FRF_AZ_BUFID_OOB_INT_KER_EN_WIDTH 1 -#define FRF_AZ_MEM_PERR_INT_KER_EN_LBN 40 -#define FRF_AZ_MEM_PERR_INT_KER_EN_WIDTH 1 -#define FRF_AZ_RBUF_OWN_INT_KER_EN_LBN 39 -#define FRF_AZ_RBUF_OWN_INT_KER_EN_WIDTH 1 -#define FRF_AZ_TBUF_OWN_INT_KER_EN_LBN 38 -#define FRF_AZ_TBUF_OWN_INT_KER_EN_WIDTH 1 -#define FRF_AZ_RDESCQ_OWN_INT_KER_EN_LBN 37 -#define FRF_AZ_RDESCQ_OWN_INT_KER_EN_WIDTH 1 -#define FRF_AZ_TDESCQ_OWN_INT_KER_EN_LBN 36 -#define FRF_AZ_TDESCQ_OWN_INT_KER_EN_WIDTH 1 -#define FRF_AZ_EVQ_OWN_INT_KER_EN_LBN 35 -#define FRF_AZ_EVQ_OWN_INT_KER_EN_WIDTH 1 -#define FRF_AZ_EVF_OFLO_INT_KER_EN_LBN 34 -#define FRF_AZ_EVF_OFLO_INT_KER_EN_WIDTH 1 -#define FRF_AZ_ILL_ADR_INT_KER_EN_LBN 33 -#define FRF_AZ_ILL_ADR_INT_KER_EN_WIDTH 1 -#define FRF_AZ_SRM_PERR_INT_KER_EN_LBN 32 -#define FRF_AZ_SRM_PERR_INT_KER_EN_WIDTH 1 -#define FRF_CZ_SRAM_PERR_INT_P_KER_LBN 12 -#define FRF_CZ_SRAM_PERR_INT_P_KER_WIDTH 1 -#define FRF_AB_PCI_BUSERR_INT_KER_LBN 11 -#define FRF_AB_PCI_BUSERR_INT_KER_WIDTH 1 -#define FRF_CZ_MBU_PERR_INT_KER_LBN 11 -#define FRF_CZ_MBU_PERR_INT_KER_WIDTH 1 -#define FRF_AZ_SRAM_OOB_INT_KER_LBN 10 -#define FRF_AZ_SRAM_OOB_INT_KER_WIDTH 1 -#define FRF_AZ_BUFID_DC_OOB_INT_KER_LBN 9 -#define FRF_AZ_BUFID_DC_OOB_INT_KER_WIDTH 1 -#define FRF_AZ_MEM_PERR_INT_KER_LBN 8 -#define FRF_AZ_MEM_PERR_INT_KER_WIDTH 1 -#define FRF_AZ_RBUF_OWN_INT_KER_LBN 7 -#define FRF_AZ_RBUF_OWN_INT_KER_WIDTH 1 -#define FRF_AZ_TBUF_OWN_INT_KER_LBN 6 -#define FRF_AZ_TBUF_OWN_INT_KER_WIDTH 1 -#define FRF_AZ_RDESCQ_OWN_INT_KER_LBN 5 -#define FRF_AZ_RDESCQ_OWN_INT_KER_WIDTH 1 -#define FRF_AZ_TDESCQ_OWN_INT_KER_LBN 4 -#define FRF_AZ_TDESCQ_OWN_INT_KER_WIDTH 1 -#define FRF_AZ_EVQ_OWN_INT_KER_LBN 3 -#define FRF_AZ_EVQ_OWN_INT_KER_WIDTH 1 -#define FRF_AZ_EVF_OFLO_INT_KER_LBN 2 -#define FRF_AZ_EVF_OFLO_INT_KER_WIDTH 1 -#define FRF_AZ_ILL_ADR_INT_KER_LBN 1 -#define FRF_AZ_ILL_ADR_INT_KER_WIDTH 1 -#define FRF_AZ_SRM_PERR_INT_KER_LBN 0 -#define FRF_AZ_SRM_PERR_INT_KER_WIDTH 1 - -/* FATAL_INTR_REG_CHAR: Fatal interrupt register for Char */ -#define FR_BZ_FATAL_INTR_CHAR 0x00000240 -#define FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_LBN 44 -#define FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_WIDTH 1 -#define FRF_BB_PCI_BUSERR_INT_CHAR_EN_LBN 43 -#define FRF_BB_PCI_BUSERR_INT_CHAR_EN_WIDTH 1 -#define FRF_CZ_MBU_PERR_INT_CHAR_EN_LBN 43 -#define FRF_CZ_MBU_PERR_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_SRAM_OOB_INT_CHAR_EN_LBN 42 -#define FRF_BZ_SRAM_OOB_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_BUFID_OOB_INT_CHAR_EN_LBN 41 -#define FRF_BZ_BUFID_OOB_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_MEM_PERR_INT_CHAR_EN_LBN 40 -#define FRF_BZ_MEM_PERR_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_RBUF_OWN_INT_CHAR_EN_LBN 39 -#define FRF_BZ_RBUF_OWN_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_TBUF_OWN_INT_CHAR_EN_LBN 38 -#define FRF_BZ_TBUF_OWN_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_LBN 37 -#define FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_LBN 36 -#define FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_EVQ_OWN_INT_CHAR_EN_LBN 35 -#define FRF_BZ_EVQ_OWN_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_EVF_OFLO_INT_CHAR_EN_LBN 34 -#define FRF_BZ_EVF_OFLO_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_ILL_ADR_INT_CHAR_EN_LBN 33 -#define FRF_BZ_ILL_ADR_INT_CHAR_EN_WIDTH 1 -#define FRF_BZ_SRM_PERR_INT_CHAR_EN_LBN 32 -#define FRF_BZ_SRM_PERR_INT_CHAR_EN_WIDTH 1 -#define FRF_CZ_SRAM_PERR_INT_P_CHAR_LBN 12 -#define FRF_CZ_SRAM_PERR_INT_P_CHAR_WIDTH 1 -#define FRF_BB_PCI_BUSERR_INT_CHAR_LBN 11 -#define FRF_BB_PCI_BUSERR_INT_CHAR_WIDTH 1 -#define FRF_CZ_MBU_PERR_INT_CHAR_LBN 11 -#define FRF_CZ_MBU_PERR_INT_CHAR_WIDTH 1 -#define FRF_BZ_SRAM_OOB_INT_CHAR_LBN 10 -#define FRF_BZ_SRAM_OOB_INT_CHAR_WIDTH 1 -#define FRF_BZ_BUFID_DC_OOB_INT_CHAR_LBN 9 -#define FRF_BZ_BUFID_DC_OOB_INT_CHAR_WIDTH 1 -#define FRF_BZ_MEM_PERR_INT_CHAR_LBN 8 -#define FRF_BZ_MEM_PERR_INT_CHAR_WIDTH 1 -#define FRF_BZ_RBUF_OWN_INT_CHAR_LBN 7 -#define FRF_BZ_RBUF_OWN_INT_CHAR_WIDTH 1 -#define FRF_BZ_TBUF_OWN_INT_CHAR_LBN 6 -#define FRF_BZ_TBUF_OWN_INT_CHAR_WIDTH 1 -#define FRF_BZ_RDESCQ_OWN_INT_CHAR_LBN 5 -#define FRF_BZ_RDESCQ_OWN_INT_CHAR_WIDTH 1 -#define FRF_BZ_TDESCQ_OWN_INT_CHAR_LBN 4 -#define FRF_BZ_TDESCQ_OWN_INT_CHAR_WIDTH 1 -#define FRF_BZ_EVQ_OWN_INT_CHAR_LBN 3 -#define FRF_BZ_EVQ_OWN_INT_CHAR_WIDTH 1 -#define FRF_BZ_EVF_OFLO_INT_CHAR_LBN 2 -#define FRF_BZ_EVF_OFLO_INT_CHAR_WIDTH 1 -#define FRF_BZ_ILL_ADR_INT_CHAR_LBN 1 -#define FRF_BZ_ILL_ADR_INT_CHAR_WIDTH 1 -#define FRF_BZ_SRM_PERR_INT_CHAR_LBN 0 -#define FRF_BZ_SRM_PERR_INT_CHAR_WIDTH 1 - -/* DP_CTRL_REG: Datapath control register */ -#define FR_BZ_DP_CTRL 0x00000250 -#define FRF_BZ_FLS_EVQ_ID_LBN 0 -#define FRF_BZ_FLS_EVQ_ID_WIDTH 12 - -/* MEM_STAT_REG: Memory status register */ -#define FR_AZ_MEM_STAT 0x00000260 -#define FRF_AB_MEM_PERR_VEC_LBN 53 -#define FRF_AB_MEM_PERR_VEC_WIDTH 38 -#define FRF_AB_MBIST_CORR_LBN 38 -#define FRF_AB_MBIST_CORR_WIDTH 15 -#define FRF_AB_MBIST_ERR_LBN 0 -#define FRF_AB_MBIST_ERR_WIDTH 40 -#define FRF_CZ_MEM_PERR_VEC_LBN 0 -#define FRF_CZ_MEM_PERR_VEC_WIDTH 35 - -/* CS_DEBUG_REG: Debug register */ -#define FR_AZ_CS_DEBUG 0x00000270 -#define FRF_AB_GLB_DEBUG2_SEL_LBN 50 -#define FRF_AB_GLB_DEBUG2_SEL_WIDTH 3 -#define FRF_AB_DEBUG_BLK_SEL2_LBN 47 -#define FRF_AB_DEBUG_BLK_SEL2_WIDTH 3 -#define FRF_AB_DEBUG_BLK_SEL1_LBN 44 -#define FRF_AB_DEBUG_BLK_SEL1_WIDTH 3 -#define FRF_AB_DEBUG_BLK_SEL0_LBN 41 -#define FRF_AB_DEBUG_BLK_SEL0_WIDTH 3 -#define FRF_CZ_CS_PORT_NUM_LBN 40 -#define FRF_CZ_CS_PORT_NUM_WIDTH 2 -#define FRF_AB_MISC_DEBUG_ADDR_LBN 36 -#define FRF_AB_MISC_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_SERDES_DEBUG_ADDR_LBN 31 -#define FRF_AB_SERDES_DEBUG_ADDR_WIDTH 5 -#define FRF_CZ_CS_PORT_FPE_LBN 1 -#define FRF_CZ_CS_PORT_FPE_WIDTH 35 -#define FRF_AB_EM_DEBUG_ADDR_LBN 26 -#define FRF_AB_EM_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_SR_DEBUG_ADDR_LBN 21 -#define FRF_AB_SR_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_EV_DEBUG_ADDR_LBN 16 -#define FRF_AB_EV_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_RX_DEBUG_ADDR_LBN 11 -#define FRF_AB_RX_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_TX_DEBUG_ADDR_LBN 6 -#define FRF_AB_TX_DEBUG_ADDR_WIDTH 5 -#define FRF_AB_CS_BIU_DEBUG_ADDR_LBN 1 -#define FRF_AB_CS_BIU_DEBUG_ADDR_WIDTH 5 -#define FRF_AZ_CS_DEBUG_EN_LBN 0 -#define FRF_AZ_CS_DEBUG_EN_WIDTH 1 - -/* DRIVER_REG: Driver scratch register [0-7] */ -#define FR_AZ_DRIVER 0x00000280 -#define FR_AZ_DRIVER_STEP 16 -#define FR_AZ_DRIVER_ROWS 8 -#define FRF_AZ_DRIVER_DW0_LBN 0 -#define FRF_AZ_DRIVER_DW0_WIDTH 32 - -/* ALTERA_BUILD_REG: Altera build register */ -#define FR_AZ_ALTERA_BUILD 0x00000300 -#define FRF_AZ_ALTERA_BUILD_VER_LBN 0 -#define FRF_AZ_ALTERA_BUILD_VER_WIDTH 32 - -/* CSR_SPARE_REG: Spare register */ -#define FR_AZ_CSR_SPARE 0x00000310 -#define FRF_AB_MEM_PERR_EN_LBN 64 -#define FRF_AB_MEM_PERR_EN_WIDTH 38 -#define FRF_CZ_MEM_PERR_EN_LBN 64 -#define FRF_CZ_MEM_PERR_EN_WIDTH 35 -#define FRF_AB_MEM_PERR_EN_TX_DATA_LBN 72 -#define FRF_AB_MEM_PERR_EN_TX_DATA_WIDTH 2 -#define FRF_AZ_CSR_SPARE_BITS_LBN 0 -#define FRF_AZ_CSR_SPARE_BITS_WIDTH 32 - -/* PCIE_SD_CTL0123_REG: PCIE SerDes control register 0 to 3 */ -#define FR_AB_PCIE_SD_CTL0123 0x00000320 -#define FRF_AB_PCIE_TESTSIG_H_LBN 96 -#define FRF_AB_PCIE_TESTSIG_H_WIDTH 19 -#define FRF_AB_PCIE_TESTSIG_L_LBN 64 -#define FRF_AB_PCIE_TESTSIG_L_WIDTH 19 -#define FRF_AB_PCIE_OFFSET_LBN 56 -#define FRF_AB_PCIE_OFFSET_WIDTH 8 -#define FRF_AB_PCIE_OFFSETEN_H_LBN 55 -#define FRF_AB_PCIE_OFFSETEN_H_WIDTH 1 -#define FRF_AB_PCIE_OFFSETEN_L_LBN 54 -#define FRF_AB_PCIE_OFFSETEN_L_WIDTH 1 -#define FRF_AB_PCIE_HIVMODE_H_LBN 53 -#define FRF_AB_PCIE_HIVMODE_H_WIDTH 1 -#define FRF_AB_PCIE_HIVMODE_L_LBN 52 -#define FRF_AB_PCIE_HIVMODE_L_WIDTH 1 -#define FRF_AB_PCIE_PARRESET_H_LBN 51 -#define FRF_AB_PCIE_PARRESET_H_WIDTH 1 -#define FRF_AB_PCIE_PARRESET_L_LBN 50 -#define FRF_AB_PCIE_PARRESET_L_WIDTH 1 -#define FRF_AB_PCIE_LPBKWDRV_H_LBN 49 -#define FRF_AB_PCIE_LPBKWDRV_H_WIDTH 1 -#define FRF_AB_PCIE_LPBKWDRV_L_LBN 48 -#define FRF_AB_PCIE_LPBKWDRV_L_WIDTH 1 -#define FRF_AB_PCIE_LPBK_LBN 40 -#define FRF_AB_PCIE_LPBK_WIDTH 8 -#define FRF_AB_PCIE_PARLPBK_LBN 32 -#define FRF_AB_PCIE_PARLPBK_WIDTH 8 -#define FRF_AB_PCIE_RXTERMADJ_H_LBN 30 -#define FRF_AB_PCIE_RXTERMADJ_H_WIDTH 2 -#define FRF_AB_PCIE_RXTERMADJ_L_LBN 28 -#define FRF_AB_PCIE_RXTERMADJ_L_WIDTH 2 -#define FFE_AB_PCIE_RXTERMADJ_MIN15PCNT 3 -#define FFE_AB_PCIE_RXTERMADJ_PL10PCNT 2 -#define FFE_AB_PCIE_RXTERMADJ_MIN17PCNT 1 -#define FFE_AB_PCIE_RXTERMADJ_NOMNL 0 -#define FRF_AB_PCIE_TXTERMADJ_H_LBN 26 -#define FRF_AB_PCIE_TXTERMADJ_H_WIDTH 2 -#define FRF_AB_PCIE_TXTERMADJ_L_LBN 24 -#define FRF_AB_PCIE_TXTERMADJ_L_WIDTH 2 -#define FFE_AB_PCIE_TXTERMADJ_MIN15PCNT 3 -#define FFE_AB_PCIE_TXTERMADJ_PL10PCNT 2 -#define FFE_AB_PCIE_TXTERMADJ_MIN17PCNT 1 -#define FFE_AB_PCIE_TXTERMADJ_NOMNL 0 -#define FRF_AB_PCIE_RXEQCTL_H_LBN 18 -#define FRF_AB_PCIE_RXEQCTL_H_WIDTH 2 -#define FRF_AB_PCIE_RXEQCTL_L_LBN 16 -#define FRF_AB_PCIE_RXEQCTL_L_WIDTH 2 -#define FFE_AB_PCIE_RXEQCTL_OFF_ALT 3 -#define FFE_AB_PCIE_RXEQCTL_OFF 2 -#define FFE_AB_PCIE_RXEQCTL_MIN 1 -#define FFE_AB_PCIE_RXEQCTL_MAX 0 -#define FRF_AB_PCIE_HIDRV_LBN 8 -#define FRF_AB_PCIE_HIDRV_WIDTH 8 -#define FRF_AB_PCIE_LODRV_LBN 0 -#define FRF_AB_PCIE_LODRV_WIDTH 8 - -/* PCIE_SD_CTL45_REG: PCIE SerDes control register 4 and 5 */ -#define FR_AB_PCIE_SD_CTL45 0x00000330 -#define FRF_AB_PCIE_DTX7_LBN 60 -#define FRF_AB_PCIE_DTX7_WIDTH 4 -#define FRF_AB_PCIE_DTX6_LBN 56 -#define FRF_AB_PCIE_DTX6_WIDTH 4 -#define FRF_AB_PCIE_DTX5_LBN 52 -#define FRF_AB_PCIE_DTX5_WIDTH 4 -#define FRF_AB_PCIE_DTX4_LBN 48 -#define FRF_AB_PCIE_DTX4_WIDTH 4 -#define FRF_AB_PCIE_DTX3_LBN 44 -#define FRF_AB_PCIE_DTX3_WIDTH 4 -#define FRF_AB_PCIE_DTX2_LBN 40 -#define FRF_AB_PCIE_DTX2_WIDTH 4 -#define FRF_AB_PCIE_DTX1_LBN 36 -#define FRF_AB_PCIE_DTX1_WIDTH 4 -#define FRF_AB_PCIE_DTX0_LBN 32 -#define FRF_AB_PCIE_DTX0_WIDTH 4 -#define FRF_AB_PCIE_DEQ7_LBN 28 -#define FRF_AB_PCIE_DEQ7_WIDTH 4 -#define FRF_AB_PCIE_DEQ6_LBN 24 -#define FRF_AB_PCIE_DEQ6_WIDTH 4 -#define FRF_AB_PCIE_DEQ5_LBN 20 -#define FRF_AB_PCIE_DEQ5_WIDTH 4 -#define FRF_AB_PCIE_DEQ4_LBN 16 -#define FRF_AB_PCIE_DEQ4_WIDTH 4 -#define FRF_AB_PCIE_DEQ3_LBN 12 -#define FRF_AB_PCIE_DEQ3_WIDTH 4 -#define FRF_AB_PCIE_DEQ2_LBN 8 -#define FRF_AB_PCIE_DEQ2_WIDTH 4 -#define FRF_AB_PCIE_DEQ1_LBN 4 -#define FRF_AB_PCIE_DEQ1_WIDTH 4 -#define FRF_AB_PCIE_DEQ0_LBN 0 -#define FRF_AB_PCIE_DEQ0_WIDTH 4 - -/* PCIE_PCS_CTL_STAT_REG: PCIE PCS control and status register */ -#define FR_AB_PCIE_PCS_CTL_STAT 0x00000340 -#define FRF_AB_PCIE_PRBSERRCOUNT0_H_LBN 52 -#define FRF_AB_PCIE_PRBSERRCOUNT0_H_WIDTH 4 -#define FRF_AB_PCIE_PRBSERRCOUNT0_L_LBN 48 -#define FRF_AB_PCIE_PRBSERRCOUNT0_L_WIDTH 4 -#define FRF_AB_PCIE_PRBSERR_LBN 40 -#define FRF_AB_PCIE_PRBSERR_WIDTH 8 -#define FRF_AB_PCIE_PRBSERRH0_LBN 32 -#define FRF_AB_PCIE_PRBSERRH0_WIDTH 8 -#define FRF_AB_PCIE_FASTINIT_H_LBN 15 -#define FRF_AB_PCIE_FASTINIT_H_WIDTH 1 -#define FRF_AB_PCIE_FASTINIT_L_LBN 14 -#define FRF_AB_PCIE_FASTINIT_L_WIDTH 1 -#define FRF_AB_PCIE_CTCDISABLE_H_LBN 13 -#define FRF_AB_PCIE_CTCDISABLE_H_WIDTH 1 -#define FRF_AB_PCIE_CTCDISABLE_L_LBN 12 -#define FRF_AB_PCIE_CTCDISABLE_L_WIDTH 1 -#define FRF_AB_PCIE_PRBSSYNC_H_LBN 11 -#define FRF_AB_PCIE_PRBSSYNC_H_WIDTH 1 -#define FRF_AB_PCIE_PRBSSYNC_L_LBN 10 -#define FRF_AB_PCIE_PRBSSYNC_L_WIDTH 1 -#define FRF_AB_PCIE_PRBSERRACK_H_LBN 9 -#define FRF_AB_PCIE_PRBSERRACK_H_WIDTH 1 -#define FRF_AB_PCIE_PRBSERRACK_L_LBN 8 -#define FRF_AB_PCIE_PRBSERRACK_L_WIDTH 1 -#define FRF_AB_PCIE_PRBSSEL_LBN 0 -#define FRF_AB_PCIE_PRBSSEL_WIDTH 8 - -/* DEBUG_DATA_OUT_REG: Live Debug and Debug 2 out ports */ -#define FR_BB_DEBUG_DATA_OUT 0x00000350 -#define FRF_BB_DEBUG2_PORT_LBN 25 -#define FRF_BB_DEBUG2_PORT_WIDTH 15 -#define FRF_BB_DEBUG1_PORT_LBN 0 -#define FRF_BB_DEBUG1_PORT_WIDTH 25 - -/* EVQ_RPTR_REGP0: Event queue read pointer register */ -#define FR_BZ_EVQ_RPTR_P0 0x00000400 -#define FR_BZ_EVQ_RPTR_P0_STEP 8192 -#define FR_BZ_EVQ_RPTR_P0_ROWS 1024 -/* EVQ_RPTR_REG_KER: Event queue read pointer register */ -#define FR_AA_EVQ_RPTR_KER 0x00011b00 -#define FR_AA_EVQ_RPTR_KER_STEP 4 -#define FR_AA_EVQ_RPTR_KER_ROWS 4 -/* EVQ_RPTR_REG: Event queue read pointer register */ -#define FR_BZ_EVQ_RPTR 0x00fa0000 -#define FR_BZ_EVQ_RPTR_STEP 16 -#define FR_BB_EVQ_RPTR_ROWS 4096 -#define FR_CZ_EVQ_RPTR_ROWS 1024 -/* EVQ_RPTR_REGP123: Event queue read pointer register */ -#define FR_BB_EVQ_RPTR_P123 0x01000400 -#define FR_BB_EVQ_RPTR_P123_STEP 8192 -#define FR_BB_EVQ_RPTR_P123_ROWS 3072 -#define FRF_AZ_EVQ_RPTR_VLD_LBN 15 -#define FRF_AZ_EVQ_RPTR_VLD_WIDTH 1 -#define FRF_AZ_EVQ_RPTR_LBN 0 -#define FRF_AZ_EVQ_RPTR_WIDTH 15 - -/* TIMER_COMMAND_REGP0: Timer Command Registers */ -#define FR_BZ_TIMER_COMMAND_P0 0x00000420 -#define FR_BZ_TIMER_COMMAND_P0_STEP 8192 -#define FR_BZ_TIMER_COMMAND_P0_ROWS 1024 -/* TIMER_COMMAND_REG_KER: Timer Command Registers */ -#define FR_AA_TIMER_COMMAND_KER 0x00000420 -#define FR_AA_TIMER_COMMAND_KER_STEP 8192 -#define FR_AA_TIMER_COMMAND_KER_ROWS 4 -/* TIMER_COMMAND_REGP123: Timer Command Registers */ -#define FR_BB_TIMER_COMMAND_P123 0x01000420 -#define FR_BB_TIMER_COMMAND_P123_STEP 8192 -#define FR_BB_TIMER_COMMAND_P123_ROWS 3072 -#define FRF_CZ_TC_TIMER_MODE_LBN 14 -#define FRF_CZ_TC_TIMER_MODE_WIDTH 2 -#define FRF_AB_TC_TIMER_MODE_LBN 12 -#define FRF_AB_TC_TIMER_MODE_WIDTH 2 -#define FRF_CZ_TC_TIMER_VAL_LBN 0 -#define FRF_CZ_TC_TIMER_VAL_WIDTH 14 -#define FRF_AB_TC_TIMER_VAL_LBN 0 -#define FRF_AB_TC_TIMER_VAL_WIDTH 12 - -/* DRV_EV_REG: Driver generated event register */ -#define FR_AZ_DRV_EV 0x00000440 -#define FRF_AZ_DRV_EV_QID_LBN 64 -#define FRF_AZ_DRV_EV_QID_WIDTH 12 -#define FRF_AZ_DRV_EV_DATA_LBN 0 -#define FRF_AZ_DRV_EV_DATA_WIDTH 64 - -/* EVQ_CTL_REG: Event queue control register */ -#define FR_AZ_EVQ_CTL 0x00000450 -#define FRF_CZ_RX_EVQ_WAKEUP_MASK_LBN 15 -#define FRF_CZ_RX_EVQ_WAKEUP_MASK_WIDTH 10 -#define FRF_BB_RX_EVQ_WAKEUP_MASK_LBN 15 -#define FRF_BB_RX_EVQ_WAKEUP_MASK_WIDTH 6 -#define FRF_AZ_EVQ_OWNERR_CTL_LBN 14 -#define FRF_AZ_EVQ_OWNERR_CTL_WIDTH 1 -#define FRF_AZ_EVQ_FIFO_AF_TH_LBN 7 -#define FRF_AZ_EVQ_FIFO_AF_TH_WIDTH 7 -#define FRF_AZ_EVQ_FIFO_NOTAF_TH_LBN 0 -#define FRF_AZ_EVQ_FIFO_NOTAF_TH_WIDTH 7 - -/* EVQ_CNT1_REG: Event counter 1 register */ -#define FR_AZ_EVQ_CNT1 0x00000460 -#define FRF_AZ_EVQ_CNT_PRE_FIFO_LBN 120 -#define FRF_AZ_EVQ_CNT_PRE_FIFO_WIDTH 7 -#define FRF_AZ_EVQ_CNT_TOBIU_LBN 100 -#define FRF_AZ_EVQ_CNT_TOBIU_WIDTH 20 -#define FRF_AZ_EVQ_TX_REQ_CNT_LBN 80 -#define FRF_AZ_EVQ_TX_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_RX_REQ_CNT_LBN 60 -#define FRF_AZ_EVQ_RX_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_EM_REQ_CNT_LBN 40 -#define FRF_AZ_EVQ_EM_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_CSR_REQ_CNT_LBN 20 -#define FRF_AZ_EVQ_CSR_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_ERR_REQ_CNT_LBN 0 -#define FRF_AZ_EVQ_ERR_REQ_CNT_WIDTH 20 - -/* EVQ_CNT2_REG: Event counter 2 register */ -#define FR_AZ_EVQ_CNT2 0x00000470 -#define FRF_AZ_EVQ_UPD_REQ_CNT_LBN 104 -#define FRF_AZ_EVQ_UPD_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_CLR_REQ_CNT_LBN 84 -#define FRF_AZ_EVQ_CLR_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_RDY_CNT_LBN 80 -#define FRF_AZ_EVQ_RDY_CNT_WIDTH 4 -#define FRF_AZ_EVQ_WU_REQ_CNT_LBN 60 -#define FRF_AZ_EVQ_WU_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_WET_REQ_CNT_LBN 40 -#define FRF_AZ_EVQ_WET_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_INIT_REQ_CNT_LBN 20 -#define FRF_AZ_EVQ_INIT_REQ_CNT_WIDTH 20 -#define FRF_AZ_EVQ_TM_REQ_CNT_LBN 0 -#define FRF_AZ_EVQ_TM_REQ_CNT_WIDTH 20 - -/* USR_EV_REG: Event mailbox register */ -#define FR_CZ_USR_EV 0x00000540 -#define FR_CZ_USR_EV_STEP 8192 -#define FR_CZ_USR_EV_ROWS 1024 -#define FRF_CZ_USR_EV_DATA_LBN 0 -#define FRF_CZ_USR_EV_DATA_WIDTH 32 - -/* BUF_TBL_CFG_REG: Buffer table configuration register */ -#define FR_AZ_BUF_TBL_CFG 0x00000600 -#define FRF_AZ_BUF_TBL_MODE_LBN 3 -#define FRF_AZ_BUF_TBL_MODE_WIDTH 1 - -/* SRM_RX_DC_CFG_REG: SRAM receive descriptor cache configuration register */ -#define FR_AZ_SRM_RX_DC_CFG 0x00000610 -#define FRF_AZ_SRM_CLK_TMP_EN_LBN 21 -#define FRF_AZ_SRM_CLK_TMP_EN_WIDTH 1 -#define FRF_AZ_SRM_RX_DC_BASE_ADR_LBN 0 -#define FRF_AZ_SRM_RX_DC_BASE_ADR_WIDTH 21 - -/* SRM_TX_DC_CFG_REG: SRAM transmit descriptor cache configuration register */ -#define FR_AZ_SRM_TX_DC_CFG 0x00000620 -#define FRF_AZ_SRM_TX_DC_BASE_ADR_LBN 0 -#define FRF_AZ_SRM_TX_DC_BASE_ADR_WIDTH 21 - -/* SRM_CFG_REG: SRAM configuration register */ -#define FR_AZ_SRM_CFG 0x00000630 -#define FRF_AZ_SRM_OOB_ADR_INTEN_LBN 5 -#define FRF_AZ_SRM_OOB_ADR_INTEN_WIDTH 1 -#define FRF_AZ_SRM_OOB_BUF_INTEN_LBN 4 -#define FRF_AZ_SRM_OOB_BUF_INTEN_WIDTH 1 -#define FRF_AZ_SRM_INIT_EN_LBN 3 -#define FRF_AZ_SRM_INIT_EN_WIDTH 1 -#define FRF_AZ_SRM_NUM_BANK_LBN 2 -#define FRF_AZ_SRM_NUM_BANK_WIDTH 1 -#define FRF_AZ_SRM_BANK_SIZE_LBN 0 -#define FRF_AZ_SRM_BANK_SIZE_WIDTH 2 - -/* BUF_TBL_UPD_REG: Buffer table update register */ -#define FR_AZ_BUF_TBL_UPD 0x00000650 -#define FRF_AZ_BUF_UPD_CMD_LBN 63 -#define FRF_AZ_BUF_UPD_CMD_WIDTH 1 -#define FRF_AZ_BUF_CLR_CMD_LBN 62 -#define FRF_AZ_BUF_CLR_CMD_WIDTH 1 -#define FRF_AZ_BUF_CLR_END_ID_LBN 32 -#define FRF_AZ_BUF_CLR_END_ID_WIDTH 20 -#define FRF_AZ_BUF_CLR_START_ID_LBN 0 -#define FRF_AZ_BUF_CLR_START_ID_WIDTH 20 - -/* SRM_UPD_EVQ_REG: Buffer table update register */ -#define FR_AZ_SRM_UPD_EVQ 0x00000660 -#define FRF_AZ_SRM_UPD_EVQ_ID_LBN 0 -#define FRF_AZ_SRM_UPD_EVQ_ID_WIDTH 12 - -/* SRAM_PARITY_REG: SRAM parity register. */ -#define FR_AZ_SRAM_PARITY 0x00000670 -#define FRF_CZ_BYPASS_ECC_LBN 3 -#define FRF_CZ_BYPASS_ECC_WIDTH 1 -#define FRF_CZ_SEC_INT_LBN 2 -#define FRF_CZ_SEC_INT_WIDTH 1 -#define FRF_CZ_FORCE_SRAM_DOUBLE_ERR_LBN 1 -#define FRF_CZ_FORCE_SRAM_DOUBLE_ERR_WIDTH 1 -#define FRF_AB_FORCE_SRAM_PERR_LBN 0 -#define FRF_AB_FORCE_SRAM_PERR_WIDTH 1 -#define FRF_CZ_FORCE_SRAM_SINGLE_ERR_LBN 0 -#define FRF_CZ_FORCE_SRAM_SINGLE_ERR_WIDTH 1 - -/* RX_CFG_REG: Receive configuration register */ -#define FR_AZ_RX_CFG 0x00000800 -#define FRF_CZ_RX_MIN_KBUF_SIZE_LBN 72 -#define FRF_CZ_RX_MIN_KBUF_SIZE_WIDTH 14 -#define FRF_CZ_RX_HDR_SPLIT_EN_LBN 71 -#define FRF_CZ_RX_HDR_SPLIT_EN_WIDTH 1 -#define FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_LBN 62 -#define FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH 9 -#define FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_LBN 53 -#define FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH 9 -#define FRF_CZ_RX_PRE_RFF_IPG_LBN 49 -#define FRF_CZ_RX_PRE_RFF_IPG_WIDTH 4 -#define FRF_BZ_RX_TCP_SUP_LBN 48 -#define FRF_BZ_RX_TCP_SUP_WIDTH 1 -#define FRF_BZ_RX_INGR_EN_LBN 47 -#define FRF_BZ_RX_INGR_EN_WIDTH 1 -#define FRF_BZ_RX_IP_HASH_LBN 46 -#define FRF_BZ_RX_IP_HASH_WIDTH 1 -#define FRF_BZ_RX_HASH_ALG_LBN 45 -#define FRF_BZ_RX_HASH_ALG_WIDTH 1 -#define FRF_BZ_RX_HASH_INSRT_HDR_LBN 44 -#define FRF_BZ_RX_HASH_INSRT_HDR_WIDTH 1 -#define FRF_BZ_RX_DESC_PUSH_EN_LBN 43 -#define FRF_BZ_RX_DESC_PUSH_EN_WIDTH 1 -#define FRF_BZ_RX_RDW_PATCH_EN_LBN 42 -#define FRF_BZ_RX_RDW_PATCH_EN_WIDTH 1 -#define FRF_BB_RX_PCI_BURST_SIZE_LBN 39 -#define FRF_BB_RX_PCI_BURST_SIZE_WIDTH 3 -#define FRF_BZ_RX_OWNERR_CTL_LBN 38 -#define FRF_BZ_RX_OWNERR_CTL_WIDTH 1 -#define FRF_BZ_RX_XON_TX_TH_LBN 33 -#define FRF_BZ_RX_XON_TX_TH_WIDTH 5 -#define FRF_AA_RX_DESC_PUSH_EN_LBN 35 -#define FRF_AA_RX_DESC_PUSH_EN_WIDTH 1 -#define FRF_AA_RX_RDW_PATCH_EN_LBN 34 -#define FRF_AA_RX_RDW_PATCH_EN_WIDTH 1 -#define FRF_AA_RX_PCI_BURST_SIZE_LBN 31 -#define FRF_AA_RX_PCI_BURST_SIZE_WIDTH 3 -#define FRF_BZ_RX_XOFF_TX_TH_LBN 28 -#define FRF_BZ_RX_XOFF_TX_TH_WIDTH 5 -#define FRF_AA_RX_OWNERR_CTL_LBN 30 -#define FRF_AA_RX_OWNERR_CTL_WIDTH 1 -#define FRF_AA_RX_XON_TX_TH_LBN 25 -#define FRF_AA_RX_XON_TX_TH_WIDTH 5 -#define FRF_BZ_RX_USR_BUF_SIZE_LBN 19 -#define FRF_BZ_RX_USR_BUF_SIZE_WIDTH 9 -#define FRF_AA_RX_XOFF_TX_TH_LBN 20 -#define FRF_AA_RX_XOFF_TX_TH_WIDTH 5 -#define FRF_AA_RX_USR_BUF_SIZE_LBN 11 -#define FRF_AA_RX_USR_BUF_SIZE_WIDTH 9 -#define FRF_BZ_RX_XON_MAC_TH_LBN 10 -#define FRF_BZ_RX_XON_MAC_TH_WIDTH 9 -#define FRF_AA_RX_XON_MAC_TH_LBN 6 -#define FRF_AA_RX_XON_MAC_TH_WIDTH 5 -#define FRF_BZ_RX_XOFF_MAC_TH_LBN 1 -#define FRF_BZ_RX_XOFF_MAC_TH_WIDTH 9 -#define FRF_AA_RX_XOFF_MAC_TH_LBN 1 -#define FRF_AA_RX_XOFF_MAC_TH_WIDTH 5 -#define FRF_AZ_RX_XOFF_MAC_EN_LBN 0 -#define FRF_AZ_RX_XOFF_MAC_EN_WIDTH 1 - -/* RX_FILTER_CTL_REG: Receive filter control registers */ -#define FR_BZ_RX_FILTER_CTL 0x00000810 -#define FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_LBN 94 -#define FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_WIDTH 8 -#define FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_LBN 86 -#define FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_WIDTH 8 -#define FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_LBN 85 -#define FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_WIDTH 1 -#define FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_LBN 69 -#define FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_WIDTH 16 -#define FRF_CZ_MULTICAST_NOMATCH_Q_ID_LBN 57 -#define FRF_CZ_MULTICAST_NOMATCH_Q_ID_WIDTH 12 -#define FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_LBN 56 -#define FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_WIDTH 1 -#define FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_LBN 55 -#define FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_WIDTH 1 -#define FRF_CZ_UNICAST_NOMATCH_Q_ID_LBN 43 -#define FRF_CZ_UNICAST_NOMATCH_Q_ID_WIDTH 12 -#define FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_LBN 42 -#define FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_WIDTH 1 -#define FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_LBN 41 -#define FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_WIDTH 1 -#define FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_LBN 40 -#define FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_WIDTH 1 -#define FRF_BZ_UDP_FULL_SRCH_LIMIT_LBN 32 -#define FRF_BZ_UDP_FULL_SRCH_LIMIT_WIDTH 8 -#define FRF_BZ_NUM_KER_LBN 24 -#define FRF_BZ_NUM_KER_WIDTH 2 -#define FRF_BZ_UDP_WILD_SRCH_LIMIT_LBN 16 -#define FRF_BZ_UDP_WILD_SRCH_LIMIT_WIDTH 8 -#define FRF_BZ_TCP_WILD_SRCH_LIMIT_LBN 8 -#define FRF_BZ_TCP_WILD_SRCH_LIMIT_WIDTH 8 -#define FRF_BZ_TCP_FULL_SRCH_LIMIT_LBN 0 -#define FRF_BZ_TCP_FULL_SRCH_LIMIT_WIDTH 8 - -/* RX_FLUSH_DESCQ_REG: Receive flush descriptor queue register */ -#define FR_AZ_RX_FLUSH_DESCQ 0x00000820 -#define FRF_AZ_RX_FLUSH_DESCQ_CMD_LBN 24 -#define FRF_AZ_RX_FLUSH_DESCQ_CMD_WIDTH 1 -#define FRF_AZ_RX_FLUSH_DESCQ_LBN 0 -#define FRF_AZ_RX_FLUSH_DESCQ_WIDTH 12 - -/* RX_DESC_UPD_REGP0: Receive descriptor update register. */ -#define FR_BZ_RX_DESC_UPD_P0 0x00000830 -#define FR_BZ_RX_DESC_UPD_P0_STEP 8192 -#define FR_BZ_RX_DESC_UPD_P0_ROWS 1024 -/* RX_DESC_UPD_REG_KER: Receive descriptor update register. */ -#define FR_AA_RX_DESC_UPD_KER 0x00000830 -#define FR_AA_RX_DESC_UPD_KER_STEP 8192 -#define FR_AA_RX_DESC_UPD_KER_ROWS 4 -/* RX_DESC_UPD_REGP123: Receive descriptor update register. */ -#define FR_BB_RX_DESC_UPD_P123 0x01000830 -#define FR_BB_RX_DESC_UPD_P123_STEP 8192 -#define FR_BB_RX_DESC_UPD_P123_ROWS 3072 -#define FRF_AZ_RX_DESC_WPTR_LBN 96 -#define FRF_AZ_RX_DESC_WPTR_WIDTH 12 -#define FRF_AZ_RX_DESC_PUSH_CMD_LBN 95 -#define FRF_AZ_RX_DESC_PUSH_CMD_WIDTH 1 -#define FRF_AZ_RX_DESC_LBN 0 -#define FRF_AZ_RX_DESC_WIDTH 64 - -/* RX_DC_CFG_REG: Receive descriptor cache configuration register */ -#define FR_AZ_RX_DC_CFG 0x00000840 -#define FRF_AB_RX_MAX_PF_LBN 2 -#define FRF_AB_RX_MAX_PF_WIDTH 2 -#define FRF_AZ_RX_DC_SIZE_LBN 0 -#define FRF_AZ_RX_DC_SIZE_WIDTH 2 -#define FFE_AZ_RX_DC_SIZE_64 3 -#define FFE_AZ_RX_DC_SIZE_32 2 -#define FFE_AZ_RX_DC_SIZE_16 1 -#define FFE_AZ_RX_DC_SIZE_8 0 - -/* RX_DC_PF_WM_REG: Receive descriptor cache pre-fetch watermark register */ -#define FR_AZ_RX_DC_PF_WM 0x00000850 -#define FRF_AZ_RX_DC_PF_HWM_LBN 6 -#define FRF_AZ_RX_DC_PF_HWM_WIDTH 6 -#define FRF_AZ_RX_DC_PF_LWM_LBN 0 -#define FRF_AZ_RX_DC_PF_LWM_WIDTH 6 - -/* RX_RSS_TKEY_REG: RSS Toeplitz hash key */ -#define FR_BZ_RX_RSS_TKEY 0x00000860 -#define FRF_BZ_RX_RSS_TKEY_HI_LBN 64 -#define FRF_BZ_RX_RSS_TKEY_HI_WIDTH 64 -#define FRF_BZ_RX_RSS_TKEY_LO_LBN 0 -#define FRF_BZ_RX_RSS_TKEY_LO_WIDTH 64 - -/* RX_NODESC_DROP_REG: Receive dropped packet counter register */ -#define FR_AZ_RX_NODESC_DROP 0x00000880 -#define FRF_CZ_RX_NODESC_DROP_CNT_LBN 0 -#define FRF_CZ_RX_NODESC_DROP_CNT_WIDTH 32 -#define FRF_AB_RX_NODESC_DROP_CNT_LBN 0 -#define FRF_AB_RX_NODESC_DROP_CNT_WIDTH 16 - -/* RX_SELF_RST_REG: Receive self reset register */ -#define FR_AA_RX_SELF_RST 0x00000890 -#define FRF_AA_RX_ISCSI_DIS_LBN 17 -#define FRF_AA_RX_ISCSI_DIS_WIDTH 1 -#define FRF_AA_RX_SW_RST_REG_LBN 16 -#define FRF_AA_RX_SW_RST_REG_WIDTH 1 -#define FRF_AA_RX_NODESC_WAIT_DIS_LBN 9 -#define FRF_AA_RX_NODESC_WAIT_DIS_WIDTH 1 -#define FRF_AA_RX_SELF_RST_EN_LBN 8 -#define FRF_AA_RX_SELF_RST_EN_WIDTH 1 -#define FRF_AA_RX_MAX_PF_LAT_LBN 4 -#define FRF_AA_RX_MAX_PF_LAT_WIDTH 4 -#define FRF_AA_RX_MAX_LU_LAT_LBN 0 -#define FRF_AA_RX_MAX_LU_LAT_WIDTH 4 - -/* RX_DEBUG_REG: undocumented register */ -#define FR_AZ_RX_DEBUG 0x000008a0 -#define FRF_AZ_RX_DEBUG_LBN 0 -#define FRF_AZ_RX_DEBUG_WIDTH 64 - -/* RX_PUSH_DROP_REG: Receive descriptor push dropped counter register */ -#define FR_AZ_RX_PUSH_DROP 0x000008b0 -#define FRF_AZ_RX_PUSH_DROP_CNT_LBN 0 -#define FRF_AZ_RX_PUSH_DROP_CNT_WIDTH 32 - -/* RX_RSS_IPV6_REG1: IPv6 RSS Toeplitz hash key low bytes */ -#define FR_CZ_RX_RSS_IPV6_REG1 0x000008d0 -#define FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN 0 -#define FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH 128 - -/* RX_RSS_IPV6_REG2: IPv6 RSS Toeplitz hash key middle bytes */ -#define FR_CZ_RX_RSS_IPV6_REG2 0x000008e0 -#define FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN 0 -#define FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH 128 - -/* RX_RSS_IPV6_REG3: IPv6 RSS Toeplitz hash key upper bytes and IPv6 RSS settings */ -#define FR_CZ_RX_RSS_IPV6_REG3 0x000008f0 -#define FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_LBN 66 -#define FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_WIDTH 1 -#define FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_LBN 65 -#define FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_WIDTH 1 -#define FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_LBN 64 -#define FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_WIDTH 1 -#define FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN 0 -#define FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH 64 - -/* TX_FLUSH_DESCQ_REG: Transmit flush descriptor queue register */ -#define FR_AZ_TX_FLUSH_DESCQ 0x00000a00 -#define FRF_AZ_TX_FLUSH_DESCQ_CMD_LBN 12 -#define FRF_AZ_TX_FLUSH_DESCQ_CMD_WIDTH 1 -#define FRF_AZ_TX_FLUSH_DESCQ_LBN 0 -#define FRF_AZ_TX_FLUSH_DESCQ_WIDTH 12 - -/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */ -#define FR_BZ_TX_DESC_UPD_P0 0x00000a10 -#define FR_BZ_TX_DESC_UPD_P0_STEP 8192 -#define FR_BZ_TX_DESC_UPD_P0_ROWS 1024 -/* TX_DESC_UPD_REG_KER: Transmit descriptor update register. */ -#define FR_AA_TX_DESC_UPD_KER 0x00000a10 -#define FR_AA_TX_DESC_UPD_KER_STEP 8192 -#define FR_AA_TX_DESC_UPD_KER_ROWS 8 -/* TX_DESC_UPD_REGP123: Transmit descriptor update register. */ -#define FR_BB_TX_DESC_UPD_P123 0x01000a10 -#define FR_BB_TX_DESC_UPD_P123_STEP 8192 -#define FR_BB_TX_DESC_UPD_P123_ROWS 3072 -#define FRF_AZ_TX_DESC_WPTR_LBN 96 -#define FRF_AZ_TX_DESC_WPTR_WIDTH 12 -#define FRF_AZ_TX_DESC_PUSH_CMD_LBN 95 -#define FRF_AZ_TX_DESC_PUSH_CMD_WIDTH 1 -#define FRF_AZ_TX_DESC_LBN 0 -#define FRF_AZ_TX_DESC_WIDTH 95 - -/* TX_DC_CFG_REG: Transmit descriptor cache configuration register */ -#define FR_AZ_TX_DC_CFG 0x00000a20 -#define FRF_AZ_TX_DC_SIZE_LBN 0 -#define FRF_AZ_TX_DC_SIZE_WIDTH 2 -#define FFE_AZ_TX_DC_SIZE_32 2 -#define FFE_AZ_TX_DC_SIZE_16 1 -#define FFE_AZ_TX_DC_SIZE_8 0 - -/* TX_CHKSM_CFG_REG: Transmit checksum configuration register */ -#define FR_AA_TX_CHKSM_CFG 0x00000a30 -#define FRF_AA_TX_Q_CHKSM_DIS_96_127_LBN 96 -#define FRF_AA_TX_Q_CHKSM_DIS_96_127_WIDTH 32 -#define FRF_AA_TX_Q_CHKSM_DIS_64_95_LBN 64 -#define FRF_AA_TX_Q_CHKSM_DIS_64_95_WIDTH 32 -#define FRF_AA_TX_Q_CHKSM_DIS_32_63_LBN 32 -#define FRF_AA_TX_Q_CHKSM_DIS_32_63_WIDTH 32 -#define FRF_AA_TX_Q_CHKSM_DIS_0_31_LBN 0 -#define FRF_AA_TX_Q_CHKSM_DIS_0_31_WIDTH 32 - -/* TX_CFG_REG: Transmit configuration register */ -#define FR_AZ_TX_CFG 0x00000a50 -#define FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_LBN 114 -#define FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_WIDTH 8 -#define FRF_CZ_TX_FILTER_TEST_MODE_BIT_LBN 113 -#define FRF_CZ_TX_FILTER_TEST_MODE_BIT_WIDTH 1 -#define FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_LBN 105 -#define FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_LBN 97 -#define FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_LBN 89 -#define FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_LBN 81 -#define FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_LBN 73 -#define FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_LBN 65 -#define FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8 -#define FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_LBN 64 -#define FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_WIDTH 1 -#define FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_LBN 48 -#define FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_WIDTH 16 -#define FRF_CZ_TX_FILTER_EN_BIT_LBN 47 -#define FRF_CZ_TX_FILTER_EN_BIT_WIDTH 1 -#define FRF_AZ_TX_IP_ID_P0_OFS_LBN 16 -#define FRF_AZ_TX_IP_ID_P0_OFS_WIDTH 15 -#define FRF_AZ_TX_NO_EOP_DISC_EN_LBN 5 -#define FRF_AZ_TX_NO_EOP_DISC_EN_WIDTH 1 -#define FRF_AZ_TX_P1_PRI_EN_LBN 4 -#define FRF_AZ_TX_P1_PRI_EN_WIDTH 1 -#define FRF_AZ_TX_OWNERR_CTL_LBN 2 -#define FRF_AZ_TX_OWNERR_CTL_WIDTH 1 -#define FRF_AA_TX_NON_IP_DROP_DIS_LBN 1 -#define FRF_AA_TX_NON_IP_DROP_DIS_WIDTH 1 -#define FRF_AZ_TX_IP_ID_REP_EN_LBN 0 -#define FRF_AZ_TX_IP_ID_REP_EN_WIDTH 1 - -/* TX_PUSH_DROP_REG: Transmit push dropped register */ -#define FR_AZ_TX_PUSH_DROP 0x00000a60 -#define FRF_AZ_TX_PUSH_DROP_CNT_LBN 0 -#define FRF_AZ_TX_PUSH_DROP_CNT_WIDTH 32 - -/* TX_RESERVED_REG: Transmit configuration register */ -#define FR_AZ_TX_RESERVED 0x00000a80 -#define FRF_AZ_TX_EVT_CNT_LBN 121 -#define FRF_AZ_TX_EVT_CNT_WIDTH 7 -#define FRF_AZ_TX_PREF_AGE_CNT_LBN 119 -#define FRF_AZ_TX_PREF_AGE_CNT_WIDTH 2 -#define FRF_AZ_TX_RD_COMP_TMR_LBN 96 -#define FRF_AZ_TX_RD_COMP_TMR_WIDTH 23 -#define FRF_AZ_TX_PUSH_EN_LBN 89 -#define FRF_AZ_TX_PUSH_EN_WIDTH 1 -#define FRF_AZ_TX_PUSH_CHK_DIS_LBN 88 -#define FRF_AZ_TX_PUSH_CHK_DIS_WIDTH 1 -#define FRF_AZ_TX_D_FF_FULL_P0_LBN 85 -#define FRF_AZ_TX_D_FF_FULL_P0_WIDTH 1 -#define FRF_AZ_TX_DMAR_ST_P0_LBN 81 -#define FRF_AZ_TX_DMAR_ST_P0_WIDTH 1 -#define FRF_AZ_TX_DMAQ_ST_LBN 78 -#define FRF_AZ_TX_DMAQ_ST_WIDTH 1 -#define FRF_AZ_TX_RX_SPACER_LBN 64 -#define FRF_AZ_TX_RX_SPACER_WIDTH 8 -#define FRF_AZ_TX_DROP_ABORT_EN_LBN 60 -#define FRF_AZ_TX_DROP_ABORT_EN_WIDTH 1 -#define FRF_AZ_TX_SOFT_EVT_EN_LBN 59 -#define FRF_AZ_TX_SOFT_EVT_EN_WIDTH 1 -#define FRF_AZ_TX_PS_EVT_DIS_LBN 58 -#define FRF_AZ_TX_PS_EVT_DIS_WIDTH 1 -#define FRF_AZ_TX_RX_SPACER_EN_LBN 57 -#define FRF_AZ_TX_RX_SPACER_EN_WIDTH 1 -#define FRF_AZ_TX_XP_TIMER_LBN 52 -#define FRF_AZ_TX_XP_TIMER_WIDTH 5 -#define FRF_AZ_TX_PREF_SPACER_LBN 44 -#define FRF_AZ_TX_PREF_SPACER_WIDTH 8 -#define FRF_AZ_TX_PREF_WD_TMR_LBN 22 -#define FRF_AZ_TX_PREF_WD_TMR_WIDTH 22 -#define FRF_AZ_TX_ONLY1TAG_LBN 21 -#define FRF_AZ_TX_ONLY1TAG_WIDTH 1 -#define FRF_AZ_TX_PREF_THRESHOLD_LBN 19 -#define FRF_AZ_TX_PREF_THRESHOLD_WIDTH 2 -#define FRF_AZ_TX_ONE_PKT_PER_Q_LBN 18 -#define FRF_AZ_TX_ONE_PKT_PER_Q_WIDTH 1 -#define FRF_AZ_TX_DIS_NON_IP_EV_LBN 17 -#define FRF_AZ_TX_DIS_NON_IP_EV_WIDTH 1 -#define FRF_AA_TX_DMA_FF_THR_LBN 16 -#define FRF_AA_TX_DMA_FF_THR_WIDTH 1 -#define FRF_AZ_TX_DMA_SPACER_LBN 8 -#define FRF_AZ_TX_DMA_SPACER_WIDTH 8 -#define FRF_AA_TX_TCP_DIS_LBN 7 -#define FRF_AA_TX_TCP_DIS_WIDTH 1 -#define FRF_BZ_TX_FLUSH_MIN_LEN_EN_LBN 7 -#define FRF_BZ_TX_FLUSH_MIN_LEN_EN_WIDTH 1 -#define FRF_AA_TX_IP_DIS_LBN 6 -#define FRF_AA_TX_IP_DIS_WIDTH 1 -#define FRF_AZ_TX_MAX_CPL_LBN 2 -#define FRF_AZ_TX_MAX_CPL_WIDTH 2 -#define FFE_AZ_TX_MAX_CPL_16 3 -#define FFE_AZ_TX_MAX_CPL_8 2 -#define FFE_AZ_TX_MAX_CPL_4 1 -#define FFE_AZ_TX_MAX_CPL_NOLIMIT 0 -#define FRF_AZ_TX_MAX_PREF_LBN 0 -#define FRF_AZ_TX_MAX_PREF_WIDTH 2 -#define FFE_AZ_TX_MAX_PREF_32 3 -#define FFE_AZ_TX_MAX_PREF_16 2 -#define FFE_AZ_TX_MAX_PREF_8 1 -#define FFE_AZ_TX_MAX_PREF_OFF 0 - -/* TX_PACE_REG: Transmit pace control register */ -#define FR_BZ_TX_PACE 0x00000a90 -#define FRF_BZ_TX_PACE_SB_NOT_AF_LBN 19 -#define FRF_BZ_TX_PACE_SB_NOT_AF_WIDTH 10 -#define FRF_BZ_TX_PACE_SB_AF_LBN 9 -#define FRF_BZ_TX_PACE_SB_AF_WIDTH 10 -#define FRF_BZ_TX_PACE_FB_BASE_LBN 5 -#define FRF_BZ_TX_PACE_FB_BASE_WIDTH 4 -#define FRF_BZ_TX_PACE_BIN_TH_LBN 0 -#define FRF_BZ_TX_PACE_BIN_TH_WIDTH 5 - -/* TX_PACE_DROP_QID_REG: PACE Drop QID Counter */ -#define FR_BZ_TX_PACE_DROP_QID 0x00000aa0 -#define FRF_BZ_TX_PACE_QID_DRP_CNT_LBN 0 -#define FRF_BZ_TX_PACE_QID_DRP_CNT_WIDTH 16 - -/* TX_VLAN_REG: Transmit VLAN tag register */ -#define FR_BB_TX_VLAN 0x00000ae0 -#define FRF_BB_TX_VLAN_EN_LBN 127 -#define FRF_BB_TX_VLAN_EN_WIDTH 1 -#define FRF_BB_TX_VLAN7_PORT1_EN_LBN 125 -#define FRF_BB_TX_VLAN7_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN7_PORT0_EN_LBN 124 -#define FRF_BB_TX_VLAN7_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN7_LBN 112 -#define FRF_BB_TX_VLAN7_WIDTH 12 -#define FRF_BB_TX_VLAN6_PORT1_EN_LBN 109 -#define FRF_BB_TX_VLAN6_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN6_PORT0_EN_LBN 108 -#define FRF_BB_TX_VLAN6_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN6_LBN 96 -#define FRF_BB_TX_VLAN6_WIDTH 12 -#define FRF_BB_TX_VLAN5_PORT1_EN_LBN 93 -#define FRF_BB_TX_VLAN5_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN5_PORT0_EN_LBN 92 -#define FRF_BB_TX_VLAN5_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN5_LBN 80 -#define FRF_BB_TX_VLAN5_WIDTH 12 -#define FRF_BB_TX_VLAN4_PORT1_EN_LBN 77 -#define FRF_BB_TX_VLAN4_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN4_PORT0_EN_LBN 76 -#define FRF_BB_TX_VLAN4_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN4_LBN 64 -#define FRF_BB_TX_VLAN4_WIDTH 12 -#define FRF_BB_TX_VLAN3_PORT1_EN_LBN 61 -#define FRF_BB_TX_VLAN3_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN3_PORT0_EN_LBN 60 -#define FRF_BB_TX_VLAN3_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN3_LBN 48 -#define FRF_BB_TX_VLAN3_WIDTH 12 -#define FRF_BB_TX_VLAN2_PORT1_EN_LBN 45 -#define FRF_BB_TX_VLAN2_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN2_PORT0_EN_LBN 44 -#define FRF_BB_TX_VLAN2_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN2_LBN 32 -#define FRF_BB_TX_VLAN2_WIDTH 12 -#define FRF_BB_TX_VLAN1_PORT1_EN_LBN 29 -#define FRF_BB_TX_VLAN1_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN1_PORT0_EN_LBN 28 -#define FRF_BB_TX_VLAN1_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN1_LBN 16 -#define FRF_BB_TX_VLAN1_WIDTH 12 -#define FRF_BB_TX_VLAN0_PORT1_EN_LBN 13 -#define FRF_BB_TX_VLAN0_PORT1_EN_WIDTH 1 -#define FRF_BB_TX_VLAN0_PORT0_EN_LBN 12 -#define FRF_BB_TX_VLAN0_PORT0_EN_WIDTH 1 -#define FRF_BB_TX_VLAN0_LBN 0 -#define FRF_BB_TX_VLAN0_WIDTH 12 - -/* TX_IPFIL_PORTEN_REG: Transmit filter control register */ -#define FR_BZ_TX_IPFIL_PORTEN 0x00000af0 -#define FRF_BZ_TX_MADR0_FIL_EN_LBN 64 -#define FRF_BZ_TX_MADR0_FIL_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL31_PORT_EN_LBN 62 -#define FRF_BB_TX_IPFIL31_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL30_PORT_EN_LBN 60 -#define FRF_BB_TX_IPFIL30_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL29_PORT_EN_LBN 58 -#define FRF_BB_TX_IPFIL29_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL28_PORT_EN_LBN 56 -#define FRF_BB_TX_IPFIL28_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL27_PORT_EN_LBN 54 -#define FRF_BB_TX_IPFIL27_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL26_PORT_EN_LBN 52 -#define FRF_BB_TX_IPFIL26_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL25_PORT_EN_LBN 50 -#define FRF_BB_TX_IPFIL25_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL24_PORT_EN_LBN 48 -#define FRF_BB_TX_IPFIL24_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL23_PORT_EN_LBN 46 -#define FRF_BB_TX_IPFIL23_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL22_PORT_EN_LBN 44 -#define FRF_BB_TX_IPFIL22_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL21_PORT_EN_LBN 42 -#define FRF_BB_TX_IPFIL21_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL20_PORT_EN_LBN 40 -#define FRF_BB_TX_IPFIL20_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL19_PORT_EN_LBN 38 -#define FRF_BB_TX_IPFIL19_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL18_PORT_EN_LBN 36 -#define FRF_BB_TX_IPFIL18_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL17_PORT_EN_LBN 34 -#define FRF_BB_TX_IPFIL17_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL16_PORT_EN_LBN 32 -#define FRF_BB_TX_IPFIL16_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL15_PORT_EN_LBN 30 -#define FRF_BB_TX_IPFIL15_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL14_PORT_EN_LBN 28 -#define FRF_BB_TX_IPFIL14_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL13_PORT_EN_LBN 26 -#define FRF_BB_TX_IPFIL13_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL12_PORT_EN_LBN 24 -#define FRF_BB_TX_IPFIL12_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL11_PORT_EN_LBN 22 -#define FRF_BB_TX_IPFIL11_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL10_PORT_EN_LBN 20 -#define FRF_BB_TX_IPFIL10_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL9_PORT_EN_LBN 18 -#define FRF_BB_TX_IPFIL9_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL8_PORT_EN_LBN 16 -#define FRF_BB_TX_IPFIL8_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL7_PORT_EN_LBN 14 -#define FRF_BB_TX_IPFIL7_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL6_PORT_EN_LBN 12 -#define FRF_BB_TX_IPFIL6_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL5_PORT_EN_LBN 10 -#define FRF_BB_TX_IPFIL5_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL4_PORT_EN_LBN 8 -#define FRF_BB_TX_IPFIL4_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL3_PORT_EN_LBN 6 -#define FRF_BB_TX_IPFIL3_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL2_PORT_EN_LBN 4 -#define FRF_BB_TX_IPFIL2_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL1_PORT_EN_LBN 2 -#define FRF_BB_TX_IPFIL1_PORT_EN_WIDTH 1 -#define FRF_BB_TX_IPFIL0_PORT_EN_LBN 0 -#define FRF_BB_TX_IPFIL0_PORT_EN_WIDTH 1 - -/* TX_IPFIL_TBL: Transmit IP source address filter table */ -#define FR_BB_TX_IPFIL_TBL 0x00000b00 -#define FR_BB_TX_IPFIL_TBL_STEP 16 -#define FR_BB_TX_IPFIL_TBL_ROWS 16 -#define FRF_BB_TX_IPFIL_MASK_1_LBN 96 -#define FRF_BB_TX_IPFIL_MASK_1_WIDTH 32 -#define FRF_BB_TX_IP_SRC_ADR_1_LBN 64 -#define FRF_BB_TX_IP_SRC_ADR_1_WIDTH 32 -#define FRF_BB_TX_IPFIL_MASK_0_LBN 32 -#define FRF_BB_TX_IPFIL_MASK_0_WIDTH 32 -#define FRF_BB_TX_IP_SRC_ADR_0_LBN 0 -#define FRF_BB_TX_IP_SRC_ADR_0_WIDTH 32 - -/* MD_TXD_REG: PHY management transmit data register */ -#define FR_AB_MD_TXD 0x00000c00 -#define FRF_AB_MD_TXD_LBN 0 -#define FRF_AB_MD_TXD_WIDTH 16 - -/* MD_RXD_REG: PHY management receive data register */ -#define FR_AB_MD_RXD 0x00000c10 -#define FRF_AB_MD_RXD_LBN 0 -#define FRF_AB_MD_RXD_WIDTH 16 - -/* MD_CS_REG: PHY management configuration & status register */ -#define FR_AB_MD_CS 0x00000c20 -#define FRF_AB_MD_RD_EN_CMD_LBN 15 -#define FRF_AB_MD_RD_EN_CMD_WIDTH 1 -#define FRF_AB_MD_WR_EN_CMD_LBN 14 -#define FRF_AB_MD_WR_EN_CMD_WIDTH 1 -#define FRF_AB_MD_ADDR_CMD_LBN 13 -#define FRF_AB_MD_ADDR_CMD_WIDTH 1 -#define FRF_AB_MD_PT_LBN 7 -#define FRF_AB_MD_PT_WIDTH 3 -#define FRF_AB_MD_PL_LBN 6 -#define FRF_AB_MD_PL_WIDTH 1 -#define FRF_AB_MD_INT_CLR_LBN 5 -#define FRF_AB_MD_INT_CLR_WIDTH 1 -#define FRF_AB_MD_GC_LBN 4 -#define FRF_AB_MD_GC_WIDTH 1 -#define FRF_AB_MD_PRSP_LBN 3 -#define FRF_AB_MD_PRSP_WIDTH 1 -#define FRF_AB_MD_RIC_LBN 2 -#define FRF_AB_MD_RIC_WIDTH 1 -#define FRF_AB_MD_RDC_LBN 1 -#define FRF_AB_MD_RDC_WIDTH 1 -#define FRF_AB_MD_WRC_LBN 0 -#define FRF_AB_MD_WRC_WIDTH 1 - -/* MD_PHY_ADR_REG: PHY management PHY address register */ -#define FR_AB_MD_PHY_ADR 0x00000c30 -#define FRF_AB_MD_PHY_ADR_LBN 0 -#define FRF_AB_MD_PHY_ADR_WIDTH 16 - -/* MD_ID_REG: PHY management ID register */ -#define FR_AB_MD_ID 0x00000c40 -#define FRF_AB_MD_PRT_ADR_LBN 11 -#define FRF_AB_MD_PRT_ADR_WIDTH 5 -#define FRF_AB_MD_DEV_ADR_LBN 6 -#define FRF_AB_MD_DEV_ADR_WIDTH 5 - -/* MD_STAT_REG: PHY management status & mask register */ -#define FR_AB_MD_STAT 0x00000c50 -#define FRF_AB_MD_PINT_LBN 4 -#define FRF_AB_MD_PINT_WIDTH 1 -#define FRF_AB_MD_DONE_LBN 3 -#define FRF_AB_MD_DONE_WIDTH 1 -#define FRF_AB_MD_BSERR_LBN 2 -#define FRF_AB_MD_BSERR_WIDTH 1 -#define FRF_AB_MD_LNFL_LBN 1 -#define FRF_AB_MD_LNFL_WIDTH 1 -#define FRF_AB_MD_BSY_LBN 0 -#define FRF_AB_MD_BSY_WIDTH 1 - -/* MAC_STAT_DMA_REG: Port MAC statistical counter DMA register */ -#define FR_AB_MAC_STAT_DMA 0x00000c60 -#define FRF_AB_MAC_STAT_DMA_CMD_LBN 48 -#define FRF_AB_MAC_STAT_DMA_CMD_WIDTH 1 -#define FRF_AB_MAC_STAT_DMA_ADR_LBN 0 -#define FRF_AB_MAC_STAT_DMA_ADR_WIDTH 48 - -/* MAC_CTRL_REG: Port MAC control register */ -#define FR_AB_MAC_CTRL 0x00000c80 -#define FRF_AB_MAC_XOFF_VAL_LBN 16 -#define FRF_AB_MAC_XOFF_VAL_WIDTH 16 -#define FRF_BB_TXFIFO_DRAIN_EN_LBN 7 -#define FRF_BB_TXFIFO_DRAIN_EN_WIDTH 1 -#define FRF_AB_MAC_XG_DISTXCRC_LBN 5 -#define FRF_AB_MAC_XG_DISTXCRC_WIDTH 1 -#define FRF_AB_MAC_BCAD_ACPT_LBN 4 -#define FRF_AB_MAC_BCAD_ACPT_WIDTH 1 -#define FRF_AB_MAC_UC_PROM_LBN 3 -#define FRF_AB_MAC_UC_PROM_WIDTH 1 -#define FRF_AB_MAC_LINK_STATUS_LBN 2 -#define FRF_AB_MAC_LINK_STATUS_WIDTH 1 -#define FRF_AB_MAC_SPEED_LBN 0 -#define FRF_AB_MAC_SPEED_WIDTH 2 -#define FFE_AB_MAC_SPEED_10G 3 -#define FFE_AB_MAC_SPEED_1G 2 -#define FFE_AB_MAC_SPEED_100M 1 -#define FFE_AB_MAC_SPEED_10M 0 - -/* GEN_MODE_REG: General Purpose mode register (external interrupt mask) */ -#define FR_BB_GEN_MODE 0x00000c90 -#define FRF_BB_XFP_PHY_INT_POL_SEL_LBN 3 -#define FRF_BB_XFP_PHY_INT_POL_SEL_WIDTH 1 -#define FRF_BB_XG_PHY_INT_POL_SEL_LBN 2 -#define FRF_BB_XG_PHY_INT_POL_SEL_WIDTH 1 -#define FRF_BB_XFP_PHY_INT_MASK_LBN 1 -#define FRF_BB_XFP_PHY_INT_MASK_WIDTH 1 -#define FRF_BB_XG_PHY_INT_MASK_LBN 0 -#define FRF_BB_XG_PHY_INT_MASK_WIDTH 1 - -/* MAC_MC_HASH_REG0: Multicast address hash table */ -#define FR_AB_MAC_MC_HASH_REG0 0x00000ca0 -#define FRF_AB_MAC_MCAST_HASH0_LBN 0 -#define FRF_AB_MAC_MCAST_HASH0_WIDTH 128 - -/* MAC_MC_HASH_REG1: Multicast address hash table */ -#define FR_AB_MAC_MC_HASH_REG1 0x00000cb0 -#define FRF_AB_MAC_MCAST_HASH1_LBN 0 -#define FRF_AB_MAC_MCAST_HASH1_WIDTH 128 - -/* GM_CFG1_REG: GMAC configuration register 1 */ -#define FR_AB_GM_CFG1 0x00000e00 -#define FRF_AB_GM_SW_RST_LBN 31 -#define FRF_AB_GM_SW_RST_WIDTH 1 -#define FRF_AB_GM_SIM_RST_LBN 30 -#define FRF_AB_GM_SIM_RST_WIDTH 1 -#define FRF_AB_GM_RST_RX_MAC_CTL_LBN 19 -#define FRF_AB_GM_RST_RX_MAC_CTL_WIDTH 1 -#define FRF_AB_GM_RST_TX_MAC_CTL_LBN 18 -#define FRF_AB_GM_RST_TX_MAC_CTL_WIDTH 1 -#define FRF_AB_GM_RST_RX_FUNC_LBN 17 -#define FRF_AB_GM_RST_RX_FUNC_WIDTH 1 -#define FRF_AB_GM_RST_TX_FUNC_LBN 16 -#define FRF_AB_GM_RST_TX_FUNC_WIDTH 1 -#define FRF_AB_GM_LOOP_LBN 8 -#define FRF_AB_GM_LOOP_WIDTH 1 -#define FRF_AB_GM_RX_FC_EN_LBN 5 -#define FRF_AB_GM_RX_FC_EN_WIDTH 1 -#define FRF_AB_GM_TX_FC_EN_LBN 4 -#define FRF_AB_GM_TX_FC_EN_WIDTH 1 -#define FRF_AB_GM_SYNC_RXEN_LBN 3 -#define FRF_AB_GM_SYNC_RXEN_WIDTH 1 -#define FRF_AB_GM_RX_EN_LBN 2 -#define FRF_AB_GM_RX_EN_WIDTH 1 -#define FRF_AB_GM_SYNC_TXEN_LBN 1 -#define FRF_AB_GM_SYNC_TXEN_WIDTH 1 -#define FRF_AB_GM_TX_EN_LBN 0 -#define FRF_AB_GM_TX_EN_WIDTH 1 - -/* GM_CFG2_REG: GMAC configuration register 2 */ -#define FR_AB_GM_CFG2 0x00000e10 -#define FRF_AB_GM_PAMBL_LEN_LBN 12 -#define FRF_AB_GM_PAMBL_LEN_WIDTH 4 -#define FRF_AB_GM_IF_MODE_LBN 8 -#define FRF_AB_GM_IF_MODE_WIDTH 2 -#define FFE_AB_IF_MODE_BYTE_MODE 2 -#define FFE_AB_IF_MODE_NIBBLE_MODE 1 -#define FRF_AB_GM_HUGE_FRM_EN_LBN 5 -#define FRF_AB_GM_HUGE_FRM_EN_WIDTH 1 -#define FRF_AB_GM_LEN_CHK_LBN 4 -#define FRF_AB_GM_LEN_CHK_WIDTH 1 -#define FRF_AB_GM_PAD_CRC_EN_LBN 2 -#define FRF_AB_GM_PAD_CRC_EN_WIDTH 1 -#define FRF_AB_GM_CRC_EN_LBN 1 -#define FRF_AB_GM_CRC_EN_WIDTH 1 -#define FRF_AB_GM_FD_LBN 0 -#define FRF_AB_GM_FD_WIDTH 1 - -/* GM_IPG_REG: GMAC IPG register */ -#define FR_AB_GM_IPG 0x00000e20 -#define FRF_AB_GM_NONB2B_IPG1_LBN 24 -#define FRF_AB_GM_NONB2B_IPG1_WIDTH 7 -#define FRF_AB_GM_NONB2B_IPG2_LBN 16 -#define FRF_AB_GM_NONB2B_IPG2_WIDTH 7 -#define FRF_AB_GM_MIN_IPG_ENF_LBN 8 -#define FRF_AB_GM_MIN_IPG_ENF_WIDTH 8 -#define FRF_AB_GM_B2B_IPG_LBN 0 -#define FRF_AB_GM_B2B_IPG_WIDTH 7 - -/* GM_HD_REG: GMAC half duplex register */ -#define FR_AB_GM_HD 0x00000e30 -#define FRF_AB_GM_ALT_BOFF_VAL_LBN 20 -#define FRF_AB_GM_ALT_BOFF_VAL_WIDTH 4 -#define FRF_AB_GM_ALT_BOFF_EN_LBN 19 -#define FRF_AB_GM_ALT_BOFF_EN_WIDTH 1 -#define FRF_AB_GM_BP_NO_BOFF_LBN 18 -#define FRF_AB_GM_BP_NO_BOFF_WIDTH 1 -#define FRF_AB_GM_DIS_BOFF_LBN 17 -#define FRF_AB_GM_DIS_BOFF_WIDTH 1 -#define FRF_AB_GM_EXDEF_TX_EN_LBN 16 -#define FRF_AB_GM_EXDEF_TX_EN_WIDTH 1 -#define FRF_AB_GM_RTRY_LIMIT_LBN 12 -#define FRF_AB_GM_RTRY_LIMIT_WIDTH 4 -#define FRF_AB_GM_COL_WIN_LBN 0 -#define FRF_AB_GM_COL_WIN_WIDTH 10 - -/* GM_MAX_FLEN_REG: GMAC maximum frame length register */ -#define FR_AB_GM_MAX_FLEN 0x00000e40 -#define FRF_AB_GM_MAX_FLEN_LBN 0 -#define FRF_AB_GM_MAX_FLEN_WIDTH 16 - -/* GM_TEST_REG: GMAC test register */ -#define FR_AB_GM_TEST 0x00000e70 -#define FRF_AB_GM_MAX_BOFF_LBN 3 -#define FRF_AB_GM_MAX_BOFF_WIDTH 1 -#define FRF_AB_GM_REG_TX_FLOW_EN_LBN 2 -#define FRF_AB_GM_REG_TX_FLOW_EN_WIDTH 1 -#define FRF_AB_GM_TEST_PAUSE_LBN 1 -#define FRF_AB_GM_TEST_PAUSE_WIDTH 1 -#define FRF_AB_GM_SHORT_SLOT_LBN 0 -#define FRF_AB_GM_SHORT_SLOT_WIDTH 1 - -/* GM_ADR1_REG: GMAC station address register 1 */ -#define FR_AB_GM_ADR1 0x00000f00 -#define FRF_AB_GM_ADR_B0_LBN 24 -#define FRF_AB_GM_ADR_B0_WIDTH 8 -#define FRF_AB_GM_ADR_B1_LBN 16 -#define FRF_AB_GM_ADR_B1_WIDTH 8 -#define FRF_AB_GM_ADR_B2_LBN 8 -#define FRF_AB_GM_ADR_B2_WIDTH 8 -#define FRF_AB_GM_ADR_B3_LBN 0 -#define FRF_AB_GM_ADR_B3_WIDTH 8 - -/* GM_ADR2_REG: GMAC station address register 2 */ -#define FR_AB_GM_ADR2 0x00000f10 -#define FRF_AB_GM_ADR_B4_LBN 24 -#define FRF_AB_GM_ADR_B4_WIDTH 8 -#define FRF_AB_GM_ADR_B5_LBN 16 -#define FRF_AB_GM_ADR_B5_WIDTH 8 - -/* GMF_CFG0_REG: GMAC FIFO configuration register 0 */ -#define FR_AB_GMF_CFG0 0x00000f20 -#define FRF_AB_GMF_FTFENRPLY_LBN 20 -#define FRF_AB_GMF_FTFENRPLY_WIDTH 1 -#define FRF_AB_GMF_STFENRPLY_LBN 19 -#define FRF_AB_GMF_STFENRPLY_WIDTH 1 -#define FRF_AB_GMF_FRFENRPLY_LBN 18 -#define FRF_AB_GMF_FRFENRPLY_WIDTH 1 -#define FRF_AB_GMF_SRFENRPLY_LBN 17 -#define FRF_AB_GMF_SRFENRPLY_WIDTH 1 -#define FRF_AB_GMF_WTMENRPLY_LBN 16 -#define FRF_AB_GMF_WTMENRPLY_WIDTH 1 -#define FRF_AB_GMF_FTFENREQ_LBN 12 -#define FRF_AB_GMF_FTFENREQ_WIDTH 1 -#define FRF_AB_GMF_STFENREQ_LBN 11 -#define FRF_AB_GMF_STFENREQ_WIDTH 1 -#define FRF_AB_GMF_FRFENREQ_LBN 10 -#define FRF_AB_GMF_FRFENREQ_WIDTH 1 -#define FRF_AB_GMF_SRFENREQ_LBN 9 -#define FRF_AB_GMF_SRFENREQ_WIDTH 1 -#define FRF_AB_GMF_WTMENREQ_LBN 8 -#define FRF_AB_GMF_WTMENREQ_WIDTH 1 -#define FRF_AB_GMF_HSTRSTFT_LBN 4 -#define FRF_AB_GMF_HSTRSTFT_WIDTH 1 -#define FRF_AB_GMF_HSTRSTST_LBN 3 -#define FRF_AB_GMF_HSTRSTST_WIDTH 1 -#define FRF_AB_GMF_HSTRSTFR_LBN 2 -#define FRF_AB_GMF_HSTRSTFR_WIDTH 1 -#define FRF_AB_GMF_HSTRSTSR_LBN 1 -#define FRF_AB_GMF_HSTRSTSR_WIDTH 1 -#define FRF_AB_GMF_HSTRSTWT_LBN 0 -#define FRF_AB_GMF_HSTRSTWT_WIDTH 1 - -/* GMF_CFG1_REG: GMAC FIFO configuration register 1 */ -#define FR_AB_GMF_CFG1 0x00000f30 -#define FRF_AB_GMF_CFGFRTH_LBN 16 -#define FRF_AB_GMF_CFGFRTH_WIDTH 5 -#define FRF_AB_GMF_CFGXOFFRTX_LBN 0 -#define FRF_AB_GMF_CFGXOFFRTX_WIDTH 16 - -/* GMF_CFG2_REG: GMAC FIFO configuration register 2 */ -#define FR_AB_GMF_CFG2 0x00000f40 -#define FRF_AB_GMF_CFGHWM_LBN 16 -#define FRF_AB_GMF_CFGHWM_WIDTH 6 -#define FRF_AB_GMF_CFGLWM_LBN 0 -#define FRF_AB_GMF_CFGLWM_WIDTH 6 - -/* GMF_CFG3_REG: GMAC FIFO configuration register 3 */ -#define FR_AB_GMF_CFG3 0x00000f50 -#define FRF_AB_GMF_CFGHWMFT_LBN 16 -#define FRF_AB_GMF_CFGHWMFT_WIDTH 6 -#define FRF_AB_GMF_CFGFTTH_LBN 0 -#define FRF_AB_GMF_CFGFTTH_WIDTH 6 - -/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */ -#define FR_AB_GMF_CFG4 0x00000f60 -#define FRF_AB_GMF_HSTFLTRFRM_LBN 0 -#define FRF_AB_GMF_HSTFLTRFRM_WIDTH 18 - -/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */ -#define FR_AB_GMF_CFG5 0x00000f70 -#define FRF_AB_GMF_CFGHDPLX_LBN 22 -#define FRF_AB_GMF_CFGHDPLX_WIDTH 1 -#define FRF_AB_GMF_SRFULL_LBN 21 -#define FRF_AB_GMF_SRFULL_WIDTH 1 -#define FRF_AB_GMF_HSTSRFULLCLR_LBN 20 -#define FRF_AB_GMF_HSTSRFULLCLR_WIDTH 1 -#define FRF_AB_GMF_CFGBYTMODE_LBN 19 -#define FRF_AB_GMF_CFGBYTMODE_WIDTH 1 -#define FRF_AB_GMF_HSTDRPLT64_LBN 18 -#define FRF_AB_GMF_HSTDRPLT64_WIDTH 1 -#define FRF_AB_GMF_HSTFLTRFRMDC_LBN 0 -#define FRF_AB_GMF_HSTFLTRFRMDC_WIDTH 18 - -/* TX_SRC_MAC_TBL: Transmit IP source address filter table */ -#define FR_BB_TX_SRC_MAC_TBL 0x00001000 -#define FR_BB_TX_SRC_MAC_TBL_STEP 16 -#define FR_BB_TX_SRC_MAC_TBL_ROWS 16 -#define FRF_BB_TX_SRC_MAC_ADR_1_LBN 64 -#define FRF_BB_TX_SRC_MAC_ADR_1_WIDTH 48 -#define FRF_BB_TX_SRC_MAC_ADR_0_LBN 0 -#define FRF_BB_TX_SRC_MAC_ADR_0_WIDTH 48 - -/* TX_SRC_MAC_CTL_REG: Transmit MAC source address filter control */ -#define FR_BB_TX_SRC_MAC_CTL 0x00001100 -#define FRF_BB_TX_SRC_DROP_CTR_LBN 16 -#define FRF_BB_TX_SRC_DROP_CTR_WIDTH 16 -#define FRF_BB_TX_SRC_FLTR_EN_LBN 15 -#define FRF_BB_TX_SRC_FLTR_EN_WIDTH 1 -#define FRF_BB_TX_DROP_CTR_CLR_LBN 12 -#define FRF_BB_TX_DROP_CTR_CLR_WIDTH 1 -#define FRF_BB_TX_MAC_QID_SEL_LBN 0 -#define FRF_BB_TX_MAC_QID_SEL_WIDTH 3 - -/* XM_ADR_LO_REG: XGMAC address register low */ -#define FR_AB_XM_ADR_LO 0x00001200 -#define FRF_AB_XM_ADR_LO_LBN 0 -#define FRF_AB_XM_ADR_LO_WIDTH 32 - -/* XM_ADR_HI_REG: XGMAC address register high */ -#define FR_AB_XM_ADR_HI 0x00001210 -#define FRF_AB_XM_ADR_HI_LBN 0 -#define FRF_AB_XM_ADR_HI_WIDTH 16 - -/* XM_GLB_CFG_REG: XGMAC global configuration */ -#define FR_AB_XM_GLB_CFG 0x00001220 -#define FRF_AB_XM_RMTFLT_GEN_LBN 17 -#define FRF_AB_XM_RMTFLT_GEN_WIDTH 1 -#define FRF_AB_XM_DEBUG_MODE_LBN 16 -#define FRF_AB_XM_DEBUG_MODE_WIDTH 1 -#define FRF_AB_XM_RX_STAT_EN_LBN 11 -#define FRF_AB_XM_RX_STAT_EN_WIDTH 1 -#define FRF_AB_XM_TX_STAT_EN_LBN 10 -#define FRF_AB_XM_TX_STAT_EN_WIDTH 1 -#define FRF_AB_XM_RX_JUMBO_MODE_LBN 6 -#define FRF_AB_XM_RX_JUMBO_MODE_WIDTH 1 -#define FRF_AB_XM_WAN_MODE_LBN 5 -#define FRF_AB_XM_WAN_MODE_WIDTH 1 -#define FRF_AB_XM_INTCLR_MODE_LBN 3 -#define FRF_AB_XM_INTCLR_MODE_WIDTH 1 -#define FRF_AB_XM_CORE_RST_LBN 0 -#define FRF_AB_XM_CORE_RST_WIDTH 1 - -/* XM_TX_CFG_REG: XGMAC transmit configuration */ -#define FR_AB_XM_TX_CFG 0x00001230 -#define FRF_AB_XM_TX_PROG_LBN 24 -#define FRF_AB_XM_TX_PROG_WIDTH 1 -#define FRF_AB_XM_IPG_LBN 16 -#define FRF_AB_XM_IPG_WIDTH 4 -#define FRF_AB_XM_FCNTL_LBN 10 -#define FRF_AB_XM_FCNTL_WIDTH 1 -#define FRF_AB_XM_TXCRC_LBN 8 -#define FRF_AB_XM_TXCRC_WIDTH 1 -#define FRF_AB_XM_EDRC_LBN 6 -#define FRF_AB_XM_EDRC_WIDTH 1 -#define FRF_AB_XM_AUTO_PAD_LBN 5 -#define FRF_AB_XM_AUTO_PAD_WIDTH 1 -#define FRF_AB_XM_TX_PRMBL_LBN 2 -#define FRF_AB_XM_TX_PRMBL_WIDTH 1 -#define FRF_AB_XM_TXEN_LBN 1 -#define FRF_AB_XM_TXEN_WIDTH 1 -#define FRF_AB_XM_TX_RST_LBN 0 -#define FRF_AB_XM_TX_RST_WIDTH 1 - -/* XM_RX_CFG_REG: XGMAC receive configuration */ -#define FR_AB_XM_RX_CFG 0x00001240 -#define FRF_AB_XM_PASS_LENERR_LBN 26 -#define FRF_AB_XM_PASS_LENERR_WIDTH 1 -#define FRF_AB_XM_PASS_CRC_ERR_LBN 25 -#define FRF_AB_XM_PASS_CRC_ERR_WIDTH 1 -#define FRF_AB_XM_PASS_PRMBLE_ERR_LBN 24 -#define FRF_AB_XM_PASS_PRMBLE_ERR_WIDTH 1 -#define FRF_AB_XM_REJ_BCAST_LBN 20 -#define FRF_AB_XM_REJ_BCAST_WIDTH 1 -#define FRF_AB_XM_ACPT_ALL_MCAST_LBN 11 -#define FRF_AB_XM_ACPT_ALL_MCAST_WIDTH 1 -#define FRF_AB_XM_ACPT_ALL_UCAST_LBN 9 -#define FRF_AB_XM_ACPT_ALL_UCAST_WIDTH 1 -#define FRF_AB_XM_AUTO_DEPAD_LBN 8 -#define FRF_AB_XM_AUTO_DEPAD_WIDTH 1 -#define FRF_AB_XM_RXCRC_LBN 3 -#define FRF_AB_XM_RXCRC_WIDTH 1 -#define FRF_AB_XM_RX_PRMBL_LBN 2 -#define FRF_AB_XM_RX_PRMBL_WIDTH 1 -#define FRF_AB_XM_RXEN_LBN 1 -#define FRF_AB_XM_RXEN_WIDTH 1 -#define FRF_AB_XM_RX_RST_LBN 0 -#define FRF_AB_XM_RX_RST_WIDTH 1 - -/* XM_MGT_INT_MASK: documentation to be written for sum_XM_MGT_INT_MASK */ -#define FR_AB_XM_MGT_INT_MASK 0x00001250 -#define FRF_AB_XM_MSK_STA_INTR_LBN 16 -#define FRF_AB_XM_MSK_STA_INTR_WIDTH 1 -#define FRF_AB_XM_MSK_STAT_CNTR_HF_LBN 9 -#define FRF_AB_XM_MSK_STAT_CNTR_HF_WIDTH 1 -#define FRF_AB_XM_MSK_STAT_CNTR_OF_LBN 8 -#define FRF_AB_XM_MSK_STAT_CNTR_OF_WIDTH 1 -#define FRF_AB_XM_MSK_PRMBLE_ERR_LBN 2 -#define FRF_AB_XM_MSK_PRMBLE_ERR_WIDTH 1 -#define FRF_AB_XM_MSK_RMTFLT_LBN 1 -#define FRF_AB_XM_MSK_RMTFLT_WIDTH 1 -#define FRF_AB_XM_MSK_LCLFLT_LBN 0 -#define FRF_AB_XM_MSK_LCLFLT_WIDTH 1 - -/* XM_FC_REG: XGMAC flow control register */ -#define FR_AB_XM_FC 0x00001270 -#define FRF_AB_XM_PAUSE_TIME_LBN 16 -#define FRF_AB_XM_PAUSE_TIME_WIDTH 16 -#define FRF_AB_XM_RX_MAC_STAT_LBN 11 -#define FRF_AB_XM_RX_MAC_STAT_WIDTH 1 -#define FRF_AB_XM_TX_MAC_STAT_LBN 10 -#define FRF_AB_XM_TX_MAC_STAT_WIDTH 1 -#define FRF_AB_XM_MCNTL_PASS_LBN 8 -#define FRF_AB_XM_MCNTL_PASS_WIDTH 2 -#define FRF_AB_XM_REJ_CNTL_UCAST_LBN 6 -#define FRF_AB_XM_REJ_CNTL_UCAST_WIDTH 1 -#define FRF_AB_XM_REJ_CNTL_MCAST_LBN 5 -#define FRF_AB_XM_REJ_CNTL_MCAST_WIDTH 1 -#define FRF_AB_XM_ZPAUSE_LBN 2 -#define FRF_AB_XM_ZPAUSE_WIDTH 1 -#define FRF_AB_XM_XMIT_PAUSE_LBN 1 -#define FRF_AB_XM_XMIT_PAUSE_WIDTH 1 -#define FRF_AB_XM_DIS_FCNTL_LBN 0 -#define FRF_AB_XM_DIS_FCNTL_WIDTH 1 - -/* XM_PAUSE_TIME_REG: XGMAC pause time register */ -#define FR_AB_XM_PAUSE_TIME 0x00001290 -#define FRF_AB_XM_TX_PAUSE_CNT_LBN 16 -#define FRF_AB_XM_TX_PAUSE_CNT_WIDTH 16 -#define FRF_AB_XM_RX_PAUSE_CNT_LBN 0 -#define FRF_AB_XM_RX_PAUSE_CNT_WIDTH 16 - -/* XM_TX_PARAM_REG: XGMAC transmit parameter register */ -#define FR_AB_XM_TX_PARAM 0x000012d0 -#define FRF_AB_XM_TX_JUMBO_MODE_LBN 31 -#define FRF_AB_XM_TX_JUMBO_MODE_WIDTH 1 -#define FRF_AB_XM_MAX_TX_FRM_SIZE_HI_LBN 19 -#define FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH 11 -#define FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN 16 -#define FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH 3 -#define FRF_AB_XM_PAD_CHAR_LBN 0 -#define FRF_AB_XM_PAD_CHAR_WIDTH 8 - -/* XM_RX_PARAM_REG: XGMAC receive parameter register */ -#define FR_AB_XM_RX_PARAM 0x000012e0 -#define FRF_AB_XM_MAX_RX_FRM_SIZE_HI_LBN 3 -#define FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH 11 -#define FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN 0 -#define FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH 3 - -/* XM_MGT_INT_MSK_REG: XGMAC management interrupt mask register */ -#define FR_AB_XM_MGT_INT_MSK 0x000012f0 -#define FRF_AB_XM_STAT_CNTR_OF_LBN 9 -#define FRF_AB_XM_STAT_CNTR_OF_WIDTH 1 -#define FRF_AB_XM_STAT_CNTR_HF_LBN 8 -#define FRF_AB_XM_STAT_CNTR_HF_WIDTH 1 -#define FRF_AB_XM_PRMBLE_ERR_LBN 2 -#define FRF_AB_XM_PRMBLE_ERR_WIDTH 1 -#define FRF_AB_XM_RMTFLT_LBN 1 -#define FRF_AB_XM_RMTFLT_WIDTH 1 -#define FRF_AB_XM_LCLFLT_LBN 0 -#define FRF_AB_XM_LCLFLT_WIDTH 1 - -/* XX_PWR_RST_REG: XGXS/XAUI powerdown/reset register */ -#define FR_AB_XX_PWR_RST 0x00001300 -#define FRF_AB_XX_PWRDND_SIG_LBN 31 -#define FRF_AB_XX_PWRDND_SIG_WIDTH 1 -#define FRF_AB_XX_PWRDNC_SIG_LBN 30 -#define FRF_AB_XX_PWRDNC_SIG_WIDTH 1 -#define FRF_AB_XX_PWRDNB_SIG_LBN 29 -#define FRF_AB_XX_PWRDNB_SIG_WIDTH 1 -#define FRF_AB_XX_PWRDNA_SIG_LBN 28 -#define FRF_AB_XX_PWRDNA_SIG_WIDTH 1 -#define FRF_AB_XX_SIM_MODE_LBN 27 -#define FRF_AB_XX_SIM_MODE_WIDTH 1 -#define FRF_AB_XX_RSTPLLCD_SIG_LBN 25 -#define FRF_AB_XX_RSTPLLCD_SIG_WIDTH 1 -#define FRF_AB_XX_RSTPLLAB_SIG_LBN 24 -#define FRF_AB_XX_RSTPLLAB_SIG_WIDTH 1 -#define FRF_AB_XX_RESETD_SIG_LBN 23 -#define FRF_AB_XX_RESETD_SIG_WIDTH 1 -#define FRF_AB_XX_RESETC_SIG_LBN 22 -#define FRF_AB_XX_RESETC_SIG_WIDTH 1 -#define FRF_AB_XX_RESETB_SIG_LBN 21 -#define FRF_AB_XX_RESETB_SIG_WIDTH 1 -#define FRF_AB_XX_RESETA_SIG_LBN 20 -#define FRF_AB_XX_RESETA_SIG_WIDTH 1 -#define FRF_AB_XX_RSTXGXSRX_SIG_LBN 18 -#define FRF_AB_XX_RSTXGXSRX_SIG_WIDTH 1 -#define FRF_AB_XX_RSTXGXSTX_SIG_LBN 17 -#define FRF_AB_XX_RSTXGXSTX_SIG_WIDTH 1 -#define FRF_AB_XX_SD_RST_ACT_LBN 16 -#define FRF_AB_XX_SD_RST_ACT_WIDTH 1 -#define FRF_AB_XX_PWRDND_EN_LBN 15 -#define FRF_AB_XX_PWRDND_EN_WIDTH 1 -#define FRF_AB_XX_PWRDNC_EN_LBN 14 -#define FRF_AB_XX_PWRDNC_EN_WIDTH 1 -#define FRF_AB_XX_PWRDNB_EN_LBN 13 -#define FRF_AB_XX_PWRDNB_EN_WIDTH 1 -#define FRF_AB_XX_PWRDNA_EN_LBN 12 -#define FRF_AB_XX_PWRDNA_EN_WIDTH 1 -#define FRF_AB_XX_RSTPLLCD_EN_LBN 9 -#define FRF_AB_XX_RSTPLLCD_EN_WIDTH 1 -#define FRF_AB_XX_RSTPLLAB_EN_LBN 8 -#define FRF_AB_XX_RSTPLLAB_EN_WIDTH 1 -#define FRF_AB_XX_RESETD_EN_LBN 7 -#define FRF_AB_XX_RESETD_EN_WIDTH 1 -#define FRF_AB_XX_RESETC_EN_LBN 6 -#define FRF_AB_XX_RESETC_EN_WIDTH 1 -#define FRF_AB_XX_RESETB_EN_LBN 5 -#define FRF_AB_XX_RESETB_EN_WIDTH 1 -#define FRF_AB_XX_RESETA_EN_LBN 4 -#define FRF_AB_XX_RESETA_EN_WIDTH 1 -#define FRF_AB_XX_RSTXGXSRX_EN_LBN 2 -#define FRF_AB_XX_RSTXGXSRX_EN_WIDTH 1 -#define FRF_AB_XX_RSTXGXSTX_EN_LBN 1 -#define FRF_AB_XX_RSTXGXSTX_EN_WIDTH 1 -#define FRF_AB_XX_RST_XX_EN_LBN 0 -#define FRF_AB_XX_RST_XX_EN_WIDTH 1 - -/* XX_SD_CTL_REG: XGXS/XAUI powerdown/reset control register */ -#define FR_AB_XX_SD_CTL 0x00001310 -#define FRF_AB_XX_TERMADJ1_LBN 17 -#define FRF_AB_XX_TERMADJ1_WIDTH 1 -#define FRF_AB_XX_TERMADJ0_LBN 16 -#define FRF_AB_XX_TERMADJ0_WIDTH 1 -#define FRF_AB_XX_HIDRVD_LBN 15 -#define FRF_AB_XX_HIDRVD_WIDTH 1 -#define FRF_AB_XX_LODRVD_LBN 14 -#define FRF_AB_XX_LODRVD_WIDTH 1 -#define FRF_AB_XX_HIDRVC_LBN 13 -#define FRF_AB_XX_HIDRVC_WIDTH 1 -#define FRF_AB_XX_LODRVC_LBN 12 -#define FRF_AB_XX_LODRVC_WIDTH 1 -#define FRF_AB_XX_HIDRVB_LBN 11 -#define FRF_AB_XX_HIDRVB_WIDTH 1 -#define FRF_AB_XX_LODRVB_LBN 10 -#define FRF_AB_XX_LODRVB_WIDTH 1 -#define FRF_AB_XX_HIDRVA_LBN 9 -#define FRF_AB_XX_HIDRVA_WIDTH 1 -#define FRF_AB_XX_LODRVA_LBN 8 -#define FRF_AB_XX_LODRVA_WIDTH 1 -#define FRF_AB_XX_LPBKD_LBN 3 -#define FRF_AB_XX_LPBKD_WIDTH 1 -#define FRF_AB_XX_LPBKC_LBN 2 -#define FRF_AB_XX_LPBKC_WIDTH 1 -#define FRF_AB_XX_LPBKB_LBN 1 -#define FRF_AB_XX_LPBKB_WIDTH 1 -#define FRF_AB_XX_LPBKA_LBN 0 -#define FRF_AB_XX_LPBKA_WIDTH 1 - -/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */ -#define FR_AB_XX_TXDRV_CTL 0x00001320 -#define FRF_AB_XX_DEQD_LBN 28 -#define FRF_AB_XX_DEQD_WIDTH 4 -#define FRF_AB_XX_DEQC_LBN 24 -#define FRF_AB_XX_DEQC_WIDTH 4 -#define FRF_AB_XX_DEQB_LBN 20 -#define FRF_AB_XX_DEQB_WIDTH 4 -#define FRF_AB_XX_DEQA_LBN 16 -#define FRF_AB_XX_DEQA_WIDTH 4 -#define FRF_AB_XX_DTXD_LBN 12 -#define FRF_AB_XX_DTXD_WIDTH 4 -#define FRF_AB_XX_DTXC_LBN 8 -#define FRF_AB_XX_DTXC_WIDTH 4 -#define FRF_AB_XX_DTXB_LBN 4 -#define FRF_AB_XX_DTXB_WIDTH 4 -#define FRF_AB_XX_DTXA_LBN 0 -#define FRF_AB_XX_DTXA_WIDTH 4 - -/* XX_PRBS_CTL_REG: documentation to be written for sum_XX_PRBS_CTL_REG */ -#define FR_AB_XX_PRBS_CTL 0x00001330 -#define FRF_AB_XX_CH3_RX_PRBS_SEL_LBN 30 -#define FRF_AB_XX_CH3_RX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH3_RX_PRBS_INV_LBN 29 -#define FRF_AB_XX_CH3_RX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH3_RX_PRBS_CHKEN_LBN 28 -#define FRF_AB_XX_CH3_RX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH2_RX_PRBS_SEL_LBN 26 -#define FRF_AB_XX_CH2_RX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH2_RX_PRBS_INV_LBN 25 -#define FRF_AB_XX_CH2_RX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH2_RX_PRBS_CHKEN_LBN 24 -#define FRF_AB_XX_CH2_RX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH1_RX_PRBS_SEL_LBN 22 -#define FRF_AB_XX_CH1_RX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH1_RX_PRBS_INV_LBN 21 -#define FRF_AB_XX_CH1_RX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH1_RX_PRBS_CHKEN_LBN 20 -#define FRF_AB_XX_CH1_RX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH0_RX_PRBS_SEL_LBN 18 -#define FRF_AB_XX_CH0_RX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH0_RX_PRBS_INV_LBN 17 -#define FRF_AB_XX_CH0_RX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH0_RX_PRBS_CHKEN_LBN 16 -#define FRF_AB_XX_CH0_RX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH3_TX_PRBS_SEL_LBN 14 -#define FRF_AB_XX_CH3_TX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH3_TX_PRBS_INV_LBN 13 -#define FRF_AB_XX_CH3_TX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH3_TX_PRBS_CHKEN_LBN 12 -#define FRF_AB_XX_CH3_TX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH2_TX_PRBS_SEL_LBN 10 -#define FRF_AB_XX_CH2_TX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH2_TX_PRBS_INV_LBN 9 -#define FRF_AB_XX_CH2_TX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH2_TX_PRBS_CHKEN_LBN 8 -#define FRF_AB_XX_CH2_TX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH1_TX_PRBS_SEL_LBN 6 -#define FRF_AB_XX_CH1_TX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH1_TX_PRBS_INV_LBN 5 -#define FRF_AB_XX_CH1_TX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH1_TX_PRBS_CHKEN_LBN 4 -#define FRF_AB_XX_CH1_TX_PRBS_CHKEN_WIDTH 1 -#define FRF_AB_XX_CH0_TX_PRBS_SEL_LBN 2 -#define FRF_AB_XX_CH0_TX_PRBS_SEL_WIDTH 2 -#define FRF_AB_XX_CH0_TX_PRBS_INV_LBN 1 -#define FRF_AB_XX_CH0_TX_PRBS_INV_WIDTH 1 -#define FRF_AB_XX_CH0_TX_PRBS_CHKEN_LBN 0 -#define FRF_AB_XX_CH0_TX_PRBS_CHKEN_WIDTH 1 - -/* XX_PRBS_CHK_REG: documentation to be written for sum_XX_PRBS_CHK_REG */ -#define FR_AB_XX_PRBS_CHK 0x00001340 -#define FRF_AB_XX_REV_LB_EN_LBN 16 -#define FRF_AB_XX_REV_LB_EN_WIDTH 1 -#define FRF_AB_XX_CH3_DEG_DET_LBN 15 -#define FRF_AB_XX_CH3_DEG_DET_WIDTH 1 -#define FRF_AB_XX_CH3_LFSR_LOCK_IND_LBN 14 -#define FRF_AB_XX_CH3_LFSR_LOCK_IND_WIDTH 1 -#define FRF_AB_XX_CH3_PRBS_FRUN_LBN 13 -#define FRF_AB_XX_CH3_PRBS_FRUN_WIDTH 1 -#define FRF_AB_XX_CH3_ERR_CHK_LBN 12 -#define FRF_AB_XX_CH3_ERR_CHK_WIDTH 1 -#define FRF_AB_XX_CH2_DEG_DET_LBN 11 -#define FRF_AB_XX_CH2_DEG_DET_WIDTH 1 -#define FRF_AB_XX_CH2_LFSR_LOCK_IND_LBN 10 -#define FRF_AB_XX_CH2_LFSR_LOCK_IND_WIDTH 1 -#define FRF_AB_XX_CH2_PRBS_FRUN_LBN 9 -#define FRF_AB_XX_CH2_PRBS_FRUN_WIDTH 1 -#define FRF_AB_XX_CH2_ERR_CHK_LBN 8 -#define FRF_AB_XX_CH2_ERR_CHK_WIDTH 1 -#define FRF_AB_XX_CH1_DEG_DET_LBN 7 -#define FRF_AB_XX_CH1_DEG_DET_WIDTH 1 -#define FRF_AB_XX_CH1_LFSR_LOCK_IND_LBN 6 -#define FRF_AB_XX_CH1_LFSR_LOCK_IND_WIDTH 1 -#define FRF_AB_XX_CH1_PRBS_FRUN_LBN 5 -#define FRF_AB_XX_CH1_PRBS_FRUN_WIDTH 1 -#define FRF_AB_XX_CH1_ERR_CHK_LBN 4 -#define FRF_AB_XX_CH1_ERR_CHK_WIDTH 1 -#define FRF_AB_XX_CH0_DEG_DET_LBN 3 -#define FRF_AB_XX_CH0_DEG_DET_WIDTH 1 -#define FRF_AB_XX_CH0_LFSR_LOCK_IND_LBN 2 -#define FRF_AB_XX_CH0_LFSR_LOCK_IND_WIDTH 1 -#define FRF_AB_XX_CH0_PRBS_FRUN_LBN 1 -#define FRF_AB_XX_CH0_PRBS_FRUN_WIDTH 1 -#define FRF_AB_XX_CH0_ERR_CHK_LBN 0 -#define FRF_AB_XX_CH0_ERR_CHK_WIDTH 1 - -/* XX_PRBS_ERR_REG: documentation to be written for sum_XX_PRBS_ERR_REG */ -#define FR_AB_XX_PRBS_ERR 0x00001350 -#define FRF_AB_XX_CH3_PRBS_ERR_CNT_LBN 24 -#define FRF_AB_XX_CH3_PRBS_ERR_CNT_WIDTH 8 -#define FRF_AB_XX_CH2_PRBS_ERR_CNT_LBN 16 -#define FRF_AB_XX_CH2_PRBS_ERR_CNT_WIDTH 8 -#define FRF_AB_XX_CH1_PRBS_ERR_CNT_LBN 8 -#define FRF_AB_XX_CH1_PRBS_ERR_CNT_WIDTH 8 -#define FRF_AB_XX_CH0_PRBS_ERR_CNT_LBN 0 -#define FRF_AB_XX_CH0_PRBS_ERR_CNT_WIDTH 8 - -/* XX_CORE_STAT_REG: XAUI XGXS core status register */ -#define FR_AB_XX_CORE_STAT 0x00001360 -#define FRF_AB_XX_FORCE_SIG3_LBN 31 -#define FRF_AB_XX_FORCE_SIG3_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG3_VAL_LBN 30 -#define FRF_AB_XX_FORCE_SIG3_VAL_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG2_LBN 29 -#define FRF_AB_XX_FORCE_SIG2_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG2_VAL_LBN 28 -#define FRF_AB_XX_FORCE_SIG2_VAL_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG1_LBN 27 -#define FRF_AB_XX_FORCE_SIG1_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG1_VAL_LBN 26 -#define FRF_AB_XX_FORCE_SIG1_VAL_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG0_LBN 25 -#define FRF_AB_XX_FORCE_SIG0_WIDTH 1 -#define FRF_AB_XX_FORCE_SIG0_VAL_LBN 24 -#define FRF_AB_XX_FORCE_SIG0_VAL_WIDTH 1 -#define FRF_AB_XX_XGXS_LB_EN_LBN 23 -#define FRF_AB_XX_XGXS_LB_EN_WIDTH 1 -#define FRF_AB_XX_XGMII_LB_EN_LBN 22 -#define FRF_AB_XX_XGMII_LB_EN_WIDTH 1 -#define FRF_AB_XX_MATCH_FAULT_LBN 21 -#define FRF_AB_XX_MATCH_FAULT_WIDTH 1 -#define FRF_AB_XX_ALIGN_DONE_LBN 20 -#define FRF_AB_XX_ALIGN_DONE_WIDTH 1 -#define FRF_AB_XX_SYNC_STAT3_LBN 19 -#define FRF_AB_XX_SYNC_STAT3_WIDTH 1 -#define FRF_AB_XX_SYNC_STAT2_LBN 18 -#define FRF_AB_XX_SYNC_STAT2_WIDTH 1 -#define FRF_AB_XX_SYNC_STAT1_LBN 17 -#define FRF_AB_XX_SYNC_STAT1_WIDTH 1 -#define FRF_AB_XX_SYNC_STAT0_LBN 16 -#define FRF_AB_XX_SYNC_STAT0_WIDTH 1 -#define FRF_AB_XX_COMMA_DET_CH3_LBN 15 -#define FRF_AB_XX_COMMA_DET_CH3_WIDTH 1 -#define FRF_AB_XX_COMMA_DET_CH2_LBN 14 -#define FRF_AB_XX_COMMA_DET_CH2_WIDTH 1 -#define FRF_AB_XX_COMMA_DET_CH1_LBN 13 -#define FRF_AB_XX_COMMA_DET_CH1_WIDTH 1 -#define FRF_AB_XX_COMMA_DET_CH0_LBN 12 -#define FRF_AB_XX_COMMA_DET_CH0_WIDTH 1 -#define FRF_AB_XX_CGRP_ALIGN_CH3_LBN 11 -#define FRF_AB_XX_CGRP_ALIGN_CH3_WIDTH 1 -#define FRF_AB_XX_CGRP_ALIGN_CH2_LBN 10 -#define FRF_AB_XX_CGRP_ALIGN_CH2_WIDTH 1 -#define FRF_AB_XX_CGRP_ALIGN_CH1_LBN 9 -#define FRF_AB_XX_CGRP_ALIGN_CH1_WIDTH 1 -#define FRF_AB_XX_CGRP_ALIGN_CH0_LBN 8 -#define FRF_AB_XX_CGRP_ALIGN_CH0_WIDTH 1 -#define FRF_AB_XX_CHAR_ERR_CH3_LBN 7 -#define FRF_AB_XX_CHAR_ERR_CH3_WIDTH 1 -#define FRF_AB_XX_CHAR_ERR_CH2_LBN 6 -#define FRF_AB_XX_CHAR_ERR_CH2_WIDTH 1 -#define FRF_AB_XX_CHAR_ERR_CH1_LBN 5 -#define FRF_AB_XX_CHAR_ERR_CH1_WIDTH 1 -#define FRF_AB_XX_CHAR_ERR_CH0_LBN 4 -#define FRF_AB_XX_CHAR_ERR_CH0_WIDTH 1 -#define FRF_AB_XX_DISPERR_CH3_LBN 3 -#define FRF_AB_XX_DISPERR_CH3_WIDTH 1 -#define FRF_AB_XX_DISPERR_CH2_LBN 2 -#define FRF_AB_XX_DISPERR_CH2_WIDTH 1 -#define FRF_AB_XX_DISPERR_CH1_LBN 1 -#define FRF_AB_XX_DISPERR_CH1_WIDTH 1 -#define FRF_AB_XX_DISPERR_CH0_LBN 0 -#define FRF_AB_XX_DISPERR_CH0_WIDTH 1 - -/* RX_DESC_PTR_TBL_KER: Receive descriptor pointer table */ -#define FR_AA_RX_DESC_PTR_TBL_KER 0x00011800 -#define FR_AA_RX_DESC_PTR_TBL_KER_STEP 16 -#define FR_AA_RX_DESC_PTR_TBL_KER_ROWS 4 -/* RX_DESC_PTR_TBL: Receive descriptor pointer table */ -#define FR_BZ_RX_DESC_PTR_TBL 0x00f40000 -#define FR_BZ_RX_DESC_PTR_TBL_STEP 16 -#define FR_BB_RX_DESC_PTR_TBL_ROWS 4096 -#define FR_CZ_RX_DESC_PTR_TBL_ROWS 1024 -#define FRF_CZ_RX_HDR_SPLIT_LBN 90 -#define FRF_CZ_RX_HDR_SPLIT_WIDTH 1 -#define FRF_AA_RX_RESET_LBN 89 -#define FRF_AA_RX_RESET_WIDTH 1 -#define FRF_AZ_RX_ISCSI_DDIG_EN_LBN 88 -#define FRF_AZ_RX_ISCSI_DDIG_EN_WIDTH 1 -#define FRF_AZ_RX_ISCSI_HDIG_EN_LBN 87 -#define FRF_AZ_RX_ISCSI_HDIG_EN_WIDTH 1 -#define FRF_AZ_RX_DESC_PREF_ACT_LBN 86 -#define FRF_AZ_RX_DESC_PREF_ACT_WIDTH 1 -#define FRF_AZ_RX_DC_HW_RPTR_LBN 80 -#define FRF_AZ_RX_DC_HW_RPTR_WIDTH 6 -#define FRF_AZ_RX_DESCQ_HW_RPTR_LBN 68 -#define FRF_AZ_RX_DESCQ_HW_RPTR_WIDTH 12 -#define FRF_AZ_RX_DESCQ_SW_WPTR_LBN 56 -#define FRF_AZ_RX_DESCQ_SW_WPTR_WIDTH 12 -#define FRF_AZ_RX_DESCQ_BUF_BASE_ID_LBN 36 -#define FRF_AZ_RX_DESCQ_BUF_BASE_ID_WIDTH 20 -#define FRF_AZ_RX_DESCQ_EVQ_ID_LBN 24 -#define FRF_AZ_RX_DESCQ_EVQ_ID_WIDTH 12 -#define FRF_AZ_RX_DESCQ_OWNER_ID_LBN 10 -#define FRF_AZ_RX_DESCQ_OWNER_ID_WIDTH 14 -#define FRF_AZ_RX_DESCQ_LABEL_LBN 5 -#define FRF_AZ_RX_DESCQ_LABEL_WIDTH 5 -#define FRF_AZ_RX_DESCQ_SIZE_LBN 3 -#define FRF_AZ_RX_DESCQ_SIZE_WIDTH 2 -#define FFE_AZ_RX_DESCQ_SIZE_4K 3 -#define FFE_AZ_RX_DESCQ_SIZE_2K 2 -#define FFE_AZ_RX_DESCQ_SIZE_1K 1 -#define FFE_AZ_RX_DESCQ_SIZE_512 0 -#define FRF_AZ_RX_DESCQ_TYPE_LBN 2 -#define FRF_AZ_RX_DESCQ_TYPE_WIDTH 1 -#define FRF_AZ_RX_DESCQ_JUMBO_LBN 1 -#define FRF_AZ_RX_DESCQ_JUMBO_WIDTH 1 -#define FRF_AZ_RX_DESCQ_EN_LBN 0 -#define FRF_AZ_RX_DESCQ_EN_WIDTH 1 - -/* TX_DESC_PTR_TBL_KER: Transmit descriptor pointer */ -#define FR_AA_TX_DESC_PTR_TBL_KER 0x00011900 -#define FR_AA_TX_DESC_PTR_TBL_KER_STEP 16 -#define FR_AA_TX_DESC_PTR_TBL_KER_ROWS 8 -/* TX_DESC_PTR_TBL: Transmit descriptor pointer */ -#define FR_BZ_TX_DESC_PTR_TBL 0x00f50000 -#define FR_BZ_TX_DESC_PTR_TBL_STEP 16 -#define FR_BB_TX_DESC_PTR_TBL_ROWS 4096 -#define FR_CZ_TX_DESC_PTR_TBL_ROWS 1024 -#define FRF_CZ_TX_DPT_Q_MASK_WIDTH_LBN 94 -#define FRF_CZ_TX_DPT_Q_MASK_WIDTH_WIDTH 2 -#define FRF_CZ_TX_DPT_ETH_FILT_EN_LBN 93 -#define FRF_CZ_TX_DPT_ETH_FILT_EN_WIDTH 1 -#define FRF_CZ_TX_DPT_IP_FILT_EN_LBN 92 -#define FRF_CZ_TX_DPT_IP_FILT_EN_WIDTH 1 -#define FRF_BZ_TX_NON_IP_DROP_DIS_LBN 91 -#define FRF_BZ_TX_NON_IP_DROP_DIS_WIDTH 1 -#define FRF_BZ_TX_IP_CHKSM_DIS_LBN 90 -#define FRF_BZ_TX_IP_CHKSM_DIS_WIDTH 1 -#define FRF_BZ_TX_TCP_CHKSM_DIS_LBN 89 -#define FRF_BZ_TX_TCP_CHKSM_DIS_WIDTH 1 -#define FRF_AZ_TX_DESCQ_EN_LBN 88 -#define FRF_AZ_TX_DESCQ_EN_WIDTH 1 -#define FRF_AZ_TX_ISCSI_DDIG_EN_LBN 87 -#define FRF_AZ_TX_ISCSI_DDIG_EN_WIDTH 1 -#define FRF_AZ_TX_ISCSI_HDIG_EN_LBN 86 -#define FRF_AZ_TX_ISCSI_HDIG_EN_WIDTH 1 -#define FRF_AZ_TX_DC_HW_RPTR_LBN 80 -#define FRF_AZ_TX_DC_HW_RPTR_WIDTH 6 -#define FRF_AZ_TX_DESCQ_HW_RPTR_LBN 68 -#define FRF_AZ_TX_DESCQ_HW_RPTR_WIDTH 12 -#define FRF_AZ_TX_DESCQ_SW_WPTR_LBN 56 -#define FRF_AZ_TX_DESCQ_SW_WPTR_WIDTH 12 -#define FRF_AZ_TX_DESCQ_BUF_BASE_ID_LBN 36 -#define FRF_AZ_TX_DESCQ_BUF_BASE_ID_WIDTH 20 -#define FRF_AZ_TX_DESCQ_EVQ_ID_LBN 24 -#define FRF_AZ_TX_DESCQ_EVQ_ID_WIDTH 12 -#define FRF_AZ_TX_DESCQ_OWNER_ID_LBN 10 -#define FRF_AZ_TX_DESCQ_OWNER_ID_WIDTH 14 -#define FRF_AZ_TX_DESCQ_LABEL_LBN 5 -#define FRF_AZ_TX_DESCQ_LABEL_WIDTH 5 -#define FRF_AZ_TX_DESCQ_SIZE_LBN 3 -#define FRF_AZ_TX_DESCQ_SIZE_WIDTH 2 -#define FFE_AZ_TX_DESCQ_SIZE_4K 3 -#define FFE_AZ_TX_DESCQ_SIZE_2K 2 -#define FFE_AZ_TX_DESCQ_SIZE_1K 1 -#define FFE_AZ_TX_DESCQ_SIZE_512 0 -#define FRF_AZ_TX_DESCQ_TYPE_LBN 1 -#define FRF_AZ_TX_DESCQ_TYPE_WIDTH 2 -#define FRF_AZ_TX_DESCQ_FLUSH_LBN 0 -#define FRF_AZ_TX_DESCQ_FLUSH_WIDTH 1 - -/* EVQ_PTR_TBL_KER: Event queue pointer table */ -#define FR_AA_EVQ_PTR_TBL_KER 0x00011a00 -#define FR_AA_EVQ_PTR_TBL_KER_STEP 16 -#define FR_AA_EVQ_PTR_TBL_KER_ROWS 4 -/* EVQ_PTR_TBL: Event queue pointer table */ -#define FR_BZ_EVQ_PTR_TBL 0x00f60000 -#define FR_BZ_EVQ_PTR_TBL_STEP 16 -#define FR_CZ_EVQ_PTR_TBL_ROWS 1024 -#define FR_BB_EVQ_PTR_TBL_ROWS 4096 -#define FRF_BZ_EVQ_RPTR_IGN_LBN 40 -#define FRF_BZ_EVQ_RPTR_IGN_WIDTH 1 -#define FRF_AB_EVQ_WKUP_OR_INT_EN_LBN 39 -#define FRF_AB_EVQ_WKUP_OR_INT_EN_WIDTH 1 -#define FRF_CZ_EVQ_DOS_PROTECT_EN_LBN 39 -#define FRF_CZ_EVQ_DOS_PROTECT_EN_WIDTH 1 -#define FRF_AZ_EVQ_NXT_WPTR_LBN 24 -#define FRF_AZ_EVQ_NXT_WPTR_WIDTH 15 -#define FRF_AZ_EVQ_EN_LBN 23 -#define FRF_AZ_EVQ_EN_WIDTH 1 -#define FRF_AZ_EVQ_SIZE_LBN 20 -#define FRF_AZ_EVQ_SIZE_WIDTH 3 -#define FFE_AZ_EVQ_SIZE_32K 6 -#define FFE_AZ_EVQ_SIZE_16K 5 -#define FFE_AZ_EVQ_SIZE_8K 4 -#define FFE_AZ_EVQ_SIZE_4K 3 -#define FFE_AZ_EVQ_SIZE_2K 2 -#define FFE_AZ_EVQ_SIZE_1K 1 -#define FFE_AZ_EVQ_SIZE_512 0 -#define FRF_AZ_EVQ_BUF_BASE_ID_LBN 0 -#define FRF_AZ_EVQ_BUF_BASE_ID_WIDTH 20 - -/* BUF_HALF_TBL_KER: Buffer table in half buffer table mode direct access by driver */ -#define FR_AA_BUF_HALF_TBL_KER 0x00018000 -#define FR_AA_BUF_HALF_TBL_KER_STEP 8 -#define FR_AA_BUF_HALF_TBL_KER_ROWS 4096 -/* BUF_HALF_TBL: Buffer table in half buffer table mode direct access by driver */ -#define FR_BZ_BUF_HALF_TBL 0x00800000 -#define FR_BZ_BUF_HALF_TBL_STEP 8 -#define FR_CZ_BUF_HALF_TBL_ROWS 147456 -#define FR_BB_BUF_HALF_TBL_ROWS 524288 -#define FRF_AZ_BUF_ADR_HBUF_ODD_LBN 44 -#define FRF_AZ_BUF_ADR_HBUF_ODD_WIDTH 20 -#define FRF_AZ_BUF_OWNER_ID_HBUF_ODD_LBN 32 -#define FRF_AZ_BUF_OWNER_ID_HBUF_ODD_WIDTH 12 -#define FRF_AZ_BUF_ADR_HBUF_EVEN_LBN 12 -#define FRF_AZ_BUF_ADR_HBUF_EVEN_WIDTH 20 -#define FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_LBN 0 -#define FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_WIDTH 12 - -/* BUF_FULL_TBL_KER: Buffer table in full buffer table mode direct access by driver */ -#define FR_AA_BUF_FULL_TBL_KER 0x00018000 -#define FR_AA_BUF_FULL_TBL_KER_STEP 8 -#define FR_AA_BUF_FULL_TBL_KER_ROWS 4096 -/* BUF_FULL_TBL: Buffer table in full buffer table mode direct access by driver */ -#define FR_BZ_BUF_FULL_TBL 0x00800000 -#define FR_BZ_BUF_FULL_TBL_STEP 8 -#define FR_CZ_BUF_FULL_TBL_ROWS 147456 -#define FR_BB_BUF_FULL_TBL_ROWS 917504 -#define FRF_AZ_BUF_FULL_UNUSED_LBN 51 -#define FRF_AZ_BUF_FULL_UNUSED_WIDTH 13 -#define FRF_AZ_IP_DAT_BUF_SIZE_LBN 50 -#define FRF_AZ_IP_DAT_BUF_SIZE_WIDTH 1 -#define FRF_AZ_BUF_ADR_REGION_LBN 48 -#define FRF_AZ_BUF_ADR_REGION_WIDTH 2 -#define FFE_AZ_BUF_ADR_REGN3 3 -#define FFE_AZ_BUF_ADR_REGN2 2 -#define FFE_AZ_BUF_ADR_REGN1 1 -#define FFE_AZ_BUF_ADR_REGN0 0 -#define FRF_AZ_BUF_ADR_FBUF_LBN 14 -#define FRF_AZ_BUF_ADR_FBUF_WIDTH 34 -#define FRF_AZ_BUF_OWNER_ID_FBUF_LBN 0 -#define FRF_AZ_BUF_OWNER_ID_FBUF_WIDTH 14 - -/* RX_FILTER_TBL0: TCP/IPv4 Receive filter table */ -#define FR_BZ_RX_FILTER_TBL0 0x00f00000 -#define FR_BZ_RX_FILTER_TBL0_STEP 32 -#define FR_BZ_RX_FILTER_TBL0_ROWS 8192 -/* RX_FILTER_TBL1: TCP/IPv4 Receive filter table */ -#define FR_BB_RX_FILTER_TBL1 0x00f00010 -#define FR_BB_RX_FILTER_TBL1_STEP 32 -#define FR_BB_RX_FILTER_TBL1_ROWS 8192 -#define FRF_BZ_RSS_EN_LBN 110 -#define FRF_BZ_RSS_EN_WIDTH 1 -#define FRF_BZ_SCATTER_EN_LBN 109 -#define FRF_BZ_SCATTER_EN_WIDTH 1 -#define FRF_BZ_TCP_UDP_LBN 108 -#define FRF_BZ_TCP_UDP_WIDTH 1 -#define FRF_BZ_RXQ_ID_LBN 96 -#define FRF_BZ_RXQ_ID_WIDTH 12 -#define FRF_BZ_DEST_IP_LBN 64 -#define FRF_BZ_DEST_IP_WIDTH 32 -#define FRF_BZ_DEST_PORT_TCP_LBN 48 -#define FRF_BZ_DEST_PORT_TCP_WIDTH 16 -#define FRF_BZ_SRC_IP_LBN 16 -#define FRF_BZ_SRC_IP_WIDTH 32 -#define FRF_BZ_SRC_TCP_DEST_UDP_LBN 0 -#define FRF_BZ_SRC_TCP_DEST_UDP_WIDTH 16 - -/* RX_MAC_FILTER_TBL0: Receive Ethernet filter table */ -#define FR_CZ_RX_MAC_FILTER_TBL0 0x00f00010 -#define FR_CZ_RX_MAC_FILTER_TBL0_STEP 32 -#define FR_CZ_RX_MAC_FILTER_TBL0_ROWS 512 -#define FRF_CZ_RMFT_RSS_EN_LBN 75 -#define FRF_CZ_RMFT_RSS_EN_WIDTH 1 -#define FRF_CZ_RMFT_SCATTER_EN_LBN 74 -#define FRF_CZ_RMFT_SCATTER_EN_WIDTH 1 -#define FRF_CZ_RMFT_IP_OVERRIDE_LBN 73 -#define FRF_CZ_RMFT_IP_OVERRIDE_WIDTH 1 -#define FRF_CZ_RMFT_RXQ_ID_LBN 61 -#define FRF_CZ_RMFT_RXQ_ID_WIDTH 12 -#define FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60 -#define FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1 -#define FRF_CZ_RMFT_DEST_MAC_LBN 12 -#define FRF_CZ_RMFT_DEST_MAC_WIDTH 48 -#define FRF_CZ_RMFT_VLAN_ID_LBN 0 -#define FRF_CZ_RMFT_VLAN_ID_WIDTH 12 - -/* TIMER_TBL: Timer table */ -#define FR_BZ_TIMER_TBL 0x00f70000 -#define FR_BZ_TIMER_TBL_STEP 16 -#define FR_CZ_TIMER_TBL_ROWS 1024 -#define FR_BB_TIMER_TBL_ROWS 4096 -#define FRF_CZ_TIMER_Q_EN_LBN 33 -#define FRF_CZ_TIMER_Q_EN_WIDTH 1 -#define FRF_CZ_INT_ARMD_LBN 32 -#define FRF_CZ_INT_ARMD_WIDTH 1 -#define FRF_CZ_INT_PEND_LBN 31 -#define FRF_CZ_INT_PEND_WIDTH 1 -#define FRF_CZ_HOST_NOTIFY_MODE_LBN 30 -#define FRF_CZ_HOST_NOTIFY_MODE_WIDTH 1 -#define FRF_CZ_RELOAD_TIMER_VAL_LBN 16 -#define FRF_CZ_RELOAD_TIMER_VAL_WIDTH 14 -#define FRF_CZ_TIMER_MODE_LBN 14 -#define FRF_CZ_TIMER_MODE_WIDTH 2 -#define FFE_CZ_TIMER_MODE_INT_HLDOFF 3 -#define FFE_CZ_TIMER_MODE_TRIG_START 2 -#define FFE_CZ_TIMER_MODE_IMMED_START 1 -#define FFE_CZ_TIMER_MODE_DIS 0 -#define FRF_BB_TIMER_MODE_LBN 12 -#define FRF_BB_TIMER_MODE_WIDTH 2 -#define FFE_BB_TIMER_MODE_INT_HLDOFF 2 -#define FFE_BB_TIMER_MODE_TRIG_START 2 -#define FFE_BB_TIMER_MODE_IMMED_START 1 -#define FFE_BB_TIMER_MODE_DIS 0 -#define FRF_CZ_TIMER_VAL_LBN 0 -#define FRF_CZ_TIMER_VAL_WIDTH 14 -#define FRF_BB_TIMER_VAL_LBN 0 -#define FRF_BB_TIMER_VAL_WIDTH 12 - -/* TX_PACE_TBL: Transmit pacing table */ -#define FR_BZ_TX_PACE_TBL 0x00f80000 -#define FR_BZ_TX_PACE_TBL_STEP 16 -#define FR_CZ_TX_PACE_TBL_ROWS 1024 -#define FR_BB_TX_PACE_TBL_ROWS 4096 -#define FRF_BZ_TX_PACE_LBN 0 -#define FRF_BZ_TX_PACE_WIDTH 5 - -/* RX_INDIRECTION_TBL: RX Indirection Table */ -#define FR_BZ_RX_INDIRECTION_TBL 0x00fb0000 -#define FR_BZ_RX_INDIRECTION_TBL_STEP 16 -#define FR_BZ_RX_INDIRECTION_TBL_ROWS 128 -#define FRF_BZ_IT_QUEUE_LBN 0 -#define FRF_BZ_IT_QUEUE_WIDTH 6 - -/* TX_FILTER_TBL0: TCP/IPv4 Transmit filter table */ -#define FR_CZ_TX_FILTER_TBL0 0x00fc0000 -#define FR_CZ_TX_FILTER_TBL0_STEP 16 -#define FR_CZ_TX_FILTER_TBL0_ROWS 8192 -#define FRF_CZ_TIFT_TCP_UDP_LBN 108 -#define FRF_CZ_TIFT_TCP_UDP_WIDTH 1 -#define FRF_CZ_TIFT_TXQ_ID_LBN 96 -#define FRF_CZ_TIFT_TXQ_ID_WIDTH 12 -#define FRF_CZ_TIFT_DEST_IP_LBN 64 -#define FRF_CZ_TIFT_DEST_IP_WIDTH 32 -#define FRF_CZ_TIFT_DEST_PORT_TCP_LBN 48 -#define FRF_CZ_TIFT_DEST_PORT_TCP_WIDTH 16 -#define FRF_CZ_TIFT_SRC_IP_LBN 16 -#define FRF_CZ_TIFT_SRC_IP_WIDTH 32 -#define FRF_CZ_TIFT_SRC_TCP_DEST_UDP_LBN 0 -#define FRF_CZ_TIFT_SRC_TCP_DEST_UDP_WIDTH 16 - -/* TX_MAC_FILTER_TBL0: Transmit Ethernet filter table */ -#define FR_CZ_TX_MAC_FILTER_TBL0 0x00fe0000 -#define FR_CZ_TX_MAC_FILTER_TBL0_STEP 16 -#define FR_CZ_TX_MAC_FILTER_TBL0_ROWS 512 -#define FRF_CZ_TMFT_TXQ_ID_LBN 61 -#define FRF_CZ_TMFT_TXQ_ID_WIDTH 12 -#define FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60 -#define FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1 -#define FRF_CZ_TMFT_SRC_MAC_LBN 12 -#define FRF_CZ_TMFT_SRC_MAC_WIDTH 48 -#define FRF_CZ_TMFT_VLAN_ID_LBN 0 -#define FRF_CZ_TMFT_VLAN_ID_WIDTH 12 - -/* MC_TREG_SMEM: MC Shared Memory */ -#define FR_CZ_MC_TREG_SMEM 0x00ff0000 -#define FR_CZ_MC_TREG_SMEM_STEP 4 -#define FR_CZ_MC_TREG_SMEM_ROWS 512 -#define FRF_CZ_MC_TREG_SMEM_ROW_LBN 0 -#define FRF_CZ_MC_TREG_SMEM_ROW_WIDTH 32 - -/* MSIX_VECTOR_TABLE: MSIX Vector Table */ -#define FR_BB_MSIX_VECTOR_TABLE 0x00ff0000 -#define FR_BZ_MSIX_VECTOR_TABLE_STEP 16 -#define FR_BB_MSIX_VECTOR_TABLE_ROWS 64 -/* MSIX_VECTOR_TABLE: MSIX Vector Table */ -#define FR_CZ_MSIX_VECTOR_TABLE 0x00000000 -/* FR_BZ_MSIX_VECTOR_TABLE_STEP 16 */ -#define FR_CZ_MSIX_VECTOR_TABLE_ROWS 1024 -#define FRF_BZ_MSIX_VECTOR_RESERVED_LBN 97 -#define FRF_BZ_MSIX_VECTOR_RESERVED_WIDTH 31 -#define FRF_BZ_MSIX_VECTOR_MASK_LBN 96 -#define FRF_BZ_MSIX_VECTOR_MASK_WIDTH 1 -#define FRF_BZ_MSIX_MESSAGE_DATA_LBN 64 -#define FRF_BZ_MSIX_MESSAGE_DATA_WIDTH 32 -#define FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_LBN 32 -#define FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_WIDTH 32 -#define FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_LBN 0 -#define FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_WIDTH 32 - -/* MSIX_PBA_TABLE: MSIX Pending Bit Array */ -#define FR_BB_MSIX_PBA_TABLE 0x00ff2000 -#define FR_BZ_MSIX_PBA_TABLE_STEP 4 -#define FR_BB_MSIX_PBA_TABLE_ROWS 2 -/* MSIX_PBA_TABLE: MSIX Pending Bit Array */ -#define FR_CZ_MSIX_PBA_TABLE 0x00008000 -/* FR_BZ_MSIX_PBA_TABLE_STEP 4 */ -#define FR_CZ_MSIX_PBA_TABLE_ROWS 32 -#define FRF_BZ_MSIX_PBA_PEND_DWORD_LBN 0 -#define FRF_BZ_MSIX_PBA_PEND_DWORD_WIDTH 32 - -/* SRM_DBG_REG: SRAM debug access */ -#define FR_BZ_SRM_DBG 0x03000000 -#define FR_BZ_SRM_DBG_STEP 8 -#define FR_CZ_SRM_DBG_ROWS 262144 -#define FR_BB_SRM_DBG_ROWS 2097152 -#define FRF_BZ_SRM_DBG_LBN 0 -#define FRF_BZ_SRM_DBG_WIDTH 64 - -/* TB_MSIX_PBA_TABLE: MSIX Pending Bit Array */ -#define FR_CZ_TB_MSIX_PBA_TABLE 0x00008000 -#define FR_CZ_TB_MSIX_PBA_TABLE_STEP 4 -#define FR_CZ_TB_MSIX_PBA_TABLE_ROWS 1024 -#define FRF_CZ_TB_MSIX_PBA_PEND_DWORD_LBN 0 -#define FRF_CZ_TB_MSIX_PBA_PEND_DWORD_WIDTH 32 - -/* DRIVER_EV */ -#define FSF_AZ_DRIVER_EV_SUBCODE_LBN 56 -#define FSF_AZ_DRIVER_EV_SUBCODE_WIDTH 4 -#define FSE_BZ_TX_DSC_ERROR_EV 15 -#define FSE_BZ_RX_DSC_ERROR_EV 14 -#define FSE_AA_RX_RECOVER_EV 11 -#define FSE_AZ_TIMER_EV 10 -#define FSE_AZ_TX_PKT_NON_TCP_UDP 9 -#define FSE_AZ_WAKE_UP_EV 6 -#define FSE_AZ_SRM_UPD_DONE_EV 5 -#define FSE_AB_EVQ_NOT_EN_EV 3 -#define FSE_AZ_EVQ_INIT_DONE_EV 2 -#define FSE_AZ_RX_DESCQ_FLS_DONE_EV 1 -#define FSE_AZ_TX_DESCQ_FLS_DONE_EV 0 -#define FSF_AZ_DRIVER_EV_SUBDATA_LBN 0 -#define FSF_AZ_DRIVER_EV_SUBDATA_WIDTH 14 - -/* EVENT_ENTRY */ -#define FSF_AZ_EV_CODE_LBN 60 -#define FSF_AZ_EV_CODE_WIDTH 4 -#define FSE_CZ_EV_CODE_MCDI_EV 12 -#define FSE_CZ_EV_CODE_USER_EV 8 -#define FSE_AZ_EV_CODE_DRV_GEN_EV 7 -#define FSE_AZ_EV_CODE_GLOBAL_EV 6 -#define FSE_AZ_EV_CODE_DRIVER_EV 5 -#define FSE_AZ_EV_CODE_TX_EV 2 -#define FSE_AZ_EV_CODE_RX_EV 0 -#define FSF_AZ_EV_DATA_LBN 0 -#define FSF_AZ_EV_DATA_WIDTH 60 - -/* GLOBAL_EV */ -#define FSF_BB_GLB_EV_RX_RECOVERY_LBN 12 -#define FSF_BB_GLB_EV_RX_RECOVERY_WIDTH 1 -#define FSF_AA_GLB_EV_RX_RECOVERY_LBN 11 -#define FSF_AA_GLB_EV_RX_RECOVERY_WIDTH 1 -#define FSF_BB_GLB_EV_XG_MGT_INTR_LBN 11 -#define FSF_BB_GLB_EV_XG_MGT_INTR_WIDTH 1 -#define FSF_AB_GLB_EV_XFP_PHY0_INTR_LBN 10 -#define FSF_AB_GLB_EV_XFP_PHY0_INTR_WIDTH 1 -#define FSF_AB_GLB_EV_XG_PHY0_INTR_LBN 9 -#define FSF_AB_GLB_EV_XG_PHY0_INTR_WIDTH 1 -#define FSF_AB_GLB_EV_G_PHY0_INTR_LBN 7 -#define FSF_AB_GLB_EV_G_PHY0_INTR_WIDTH 1 - -/* LEGACY_INT_VEC */ -#define FSF_AZ_NET_IVEC_FATAL_INT_LBN 64 -#define FSF_AZ_NET_IVEC_FATAL_INT_WIDTH 1 -#define FSF_AZ_NET_IVEC_INT_Q_LBN 40 -#define FSF_AZ_NET_IVEC_INT_Q_WIDTH 4 -#define FSF_AZ_NET_IVEC_INT_FLAG_LBN 32 -#define FSF_AZ_NET_IVEC_INT_FLAG_WIDTH 1 -#define FSF_AZ_NET_IVEC_EVQ_FIFO_HF_LBN 1 -#define FSF_AZ_NET_IVEC_EVQ_FIFO_HF_WIDTH 1 -#define FSF_AZ_NET_IVEC_EVQ_FIFO_AF_LBN 0 -#define FSF_AZ_NET_IVEC_EVQ_FIFO_AF_WIDTH 1 - -/* MC_XGMAC_FLTR_RULE_DEF */ -#define FSF_CZ_MC_XFRC_MODE_LBN 416 -#define FSF_CZ_MC_XFRC_MODE_WIDTH 1 -#define FSE_CZ_MC_XFRC_MODE_LAYERED 1 -#define FSE_CZ_MC_XFRC_MODE_SIMPLE 0 -#define FSF_CZ_MC_XFRC_HASH_LBN 384 -#define FSF_CZ_MC_XFRC_HASH_WIDTH 32 -#define FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_LBN 256 -#define FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_WIDTH 128 -#define FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_LBN 128 -#define FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_WIDTH 128 -#define FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_LBN 0 -#define FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_WIDTH 128 - -/* RX_EV */ -#define FSF_CZ_RX_EV_PKT_NOT_PARSED_LBN 58 -#define FSF_CZ_RX_EV_PKT_NOT_PARSED_WIDTH 1 -#define FSF_CZ_RX_EV_IPV6_PKT_LBN 57 -#define FSF_CZ_RX_EV_IPV6_PKT_WIDTH 1 -#define FSF_AZ_RX_EV_PKT_OK_LBN 56 -#define FSF_AZ_RX_EV_PKT_OK_WIDTH 1 -#define FSF_AZ_RX_EV_PAUSE_FRM_ERR_LBN 55 -#define FSF_AZ_RX_EV_PAUSE_FRM_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_LBN 54 -#define FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_IP_FRAG_ERR_LBN 53 -#define FSF_AZ_RX_EV_IP_FRAG_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_LBN 52 -#define FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51 -#define FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_ETH_CRC_ERR_LBN 50 -#define FSF_AZ_RX_EV_ETH_CRC_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_FRM_TRUNC_LBN 49 -#define FSF_AZ_RX_EV_FRM_TRUNC_WIDTH 1 -#define FSF_AA_RX_EV_DRIB_NIB_LBN 49 -#define FSF_AA_RX_EV_DRIB_NIB_WIDTH 1 -#define FSF_AZ_RX_EV_TOBE_DISC_LBN 47 -#define FSF_AZ_RX_EV_TOBE_DISC_WIDTH 1 -#define FSF_AZ_RX_EV_PKT_TYPE_LBN 44 -#define FSF_AZ_RX_EV_PKT_TYPE_WIDTH 3 -#define FSE_AZ_RX_EV_PKT_TYPE_VLAN_JUMBO 5 -#define FSE_AZ_RX_EV_PKT_TYPE_VLAN_LLC 4 -#define FSE_AZ_RX_EV_PKT_TYPE_VLAN 3 -#define FSE_AZ_RX_EV_PKT_TYPE_JUMBO 2 -#define FSE_AZ_RX_EV_PKT_TYPE_LLC 1 -#define FSE_AZ_RX_EV_PKT_TYPE_ETH 0 -#define FSF_AZ_RX_EV_HDR_TYPE_LBN 42 -#define FSF_AZ_RX_EV_HDR_TYPE_WIDTH 2 -#define FSE_AZ_RX_EV_HDR_TYPE_OTHER 3 -#define FSE_AB_RX_EV_HDR_TYPE_IPV4_OTHER 2 -#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER 2 -#define FSE_AB_RX_EV_HDR_TYPE_IPV4_UDP 1 -#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP 1 -#define FSE_AB_RX_EV_HDR_TYPE_IPV4_TCP 0 -#define FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP 0 -#define FSF_AZ_RX_EV_DESC_Q_EMPTY_LBN 41 -#define FSF_AZ_RX_EV_DESC_Q_EMPTY_WIDTH 1 -#define FSF_AZ_RX_EV_MCAST_HASH_MATCH_LBN 40 -#define FSF_AZ_RX_EV_MCAST_HASH_MATCH_WIDTH 1 -#define FSF_AZ_RX_EV_MCAST_PKT_LBN 39 -#define FSF_AZ_RX_EV_MCAST_PKT_WIDTH 1 -#define FSF_AA_RX_EV_RECOVERY_FLAG_LBN 37 -#define FSF_AA_RX_EV_RECOVERY_FLAG_WIDTH 1 -#define FSF_AZ_RX_EV_Q_LABEL_LBN 32 -#define FSF_AZ_RX_EV_Q_LABEL_WIDTH 5 -#define FSF_AZ_RX_EV_JUMBO_CONT_LBN 31 -#define FSF_AZ_RX_EV_JUMBO_CONT_WIDTH 1 -#define FSF_AZ_RX_EV_PORT_LBN 30 -#define FSF_AZ_RX_EV_PORT_WIDTH 1 -#define FSF_AZ_RX_EV_BYTE_CNT_LBN 16 -#define FSF_AZ_RX_EV_BYTE_CNT_WIDTH 14 -#define FSF_AZ_RX_EV_SOP_LBN 15 -#define FSF_AZ_RX_EV_SOP_WIDTH 1 -#define FSF_AZ_RX_EV_ISCSI_PKT_OK_LBN 14 -#define FSF_AZ_RX_EV_ISCSI_PKT_OK_WIDTH 1 -#define FSF_AZ_RX_EV_ISCSI_DDIG_ERR_LBN 13 -#define FSF_AZ_RX_EV_ISCSI_DDIG_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_ISCSI_HDIG_ERR_LBN 12 -#define FSF_AZ_RX_EV_ISCSI_HDIG_ERR_WIDTH 1 -#define FSF_AZ_RX_EV_DESC_PTR_LBN 0 -#define FSF_AZ_RX_EV_DESC_PTR_WIDTH 12 - -/* RX_KER_DESC */ -#define FSF_AZ_RX_KER_BUF_SIZE_LBN 48 -#define FSF_AZ_RX_KER_BUF_SIZE_WIDTH 14 -#define FSF_AZ_RX_KER_BUF_REGION_LBN 46 -#define FSF_AZ_RX_KER_BUF_REGION_WIDTH 2 -#define FSF_AZ_RX_KER_BUF_ADDR_LBN 0 -#define FSF_AZ_RX_KER_BUF_ADDR_WIDTH 46 - -/* RX_USER_DESC */ -#define FSF_AZ_RX_USER_2BYTE_OFFSET_LBN 20 -#define FSF_AZ_RX_USER_2BYTE_OFFSET_WIDTH 12 -#define FSF_AZ_RX_USER_BUF_ID_LBN 0 -#define FSF_AZ_RX_USER_BUF_ID_WIDTH 20 - -/* TX_EV */ -#define FSF_AZ_TX_EV_PKT_ERR_LBN 38 -#define FSF_AZ_TX_EV_PKT_ERR_WIDTH 1 -#define FSF_AZ_TX_EV_PKT_TOO_BIG_LBN 37 -#define FSF_AZ_TX_EV_PKT_TOO_BIG_WIDTH 1 -#define FSF_AZ_TX_EV_Q_LABEL_LBN 32 -#define FSF_AZ_TX_EV_Q_LABEL_WIDTH 5 -#define FSF_AZ_TX_EV_PORT_LBN 16 -#define FSF_AZ_TX_EV_PORT_WIDTH 1 -#define FSF_AZ_TX_EV_WQ_FF_FULL_LBN 15 -#define FSF_AZ_TX_EV_WQ_FF_FULL_WIDTH 1 -#define FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_LBN 14 -#define FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_WIDTH 1 -#define FSF_AZ_TX_EV_COMP_LBN 12 -#define FSF_AZ_TX_EV_COMP_WIDTH 1 -#define FSF_AZ_TX_EV_DESC_PTR_LBN 0 -#define FSF_AZ_TX_EV_DESC_PTR_WIDTH 12 - -/* TX_KER_DESC */ -#define FSF_AZ_TX_KER_CONT_LBN 62 -#define FSF_AZ_TX_KER_CONT_WIDTH 1 -#define FSF_AZ_TX_KER_BYTE_COUNT_LBN 48 -#define FSF_AZ_TX_KER_BYTE_COUNT_WIDTH 14 -#define FSF_AZ_TX_KER_BUF_REGION_LBN 46 -#define FSF_AZ_TX_KER_BUF_REGION_WIDTH 2 -#define FSF_AZ_TX_KER_BUF_ADDR_LBN 0 -#define FSF_AZ_TX_KER_BUF_ADDR_WIDTH 46 - -/* TX_USER_DESC */ -#define FSF_AZ_TX_USER_SW_EV_EN_LBN 48 -#define FSF_AZ_TX_USER_SW_EV_EN_WIDTH 1 -#define FSF_AZ_TX_USER_CONT_LBN 46 -#define FSF_AZ_TX_USER_CONT_WIDTH 1 -#define FSF_AZ_TX_USER_BYTE_CNT_LBN 33 -#define FSF_AZ_TX_USER_BYTE_CNT_WIDTH 13 -#define FSF_AZ_TX_USER_BUF_ID_LBN 13 -#define FSF_AZ_TX_USER_BUF_ID_WIDTH 20 -#define FSF_AZ_TX_USER_BYTE_OFS_LBN 0 -#define FSF_AZ_TX_USER_BYTE_OFS_WIDTH 13 - -/* USER_EV */ -#define FSF_CZ_USER_QID_LBN 32 -#define FSF_CZ_USER_QID_WIDTH 10 -#define FSF_CZ_USER_EV_REG_VALUE_LBN 0 -#define FSF_CZ_USER_EV_REG_VALUE_WIDTH 32 - -/************************************************************************** - * - * Falcon B0 PCIe core indirect registers - * - ************************************************************************** - */ - -#define FPCR_BB_PCIE_DEVICE_CTRL_STAT 0x68 - -#define FPCR_BB_PCIE_LINK_CTRL_STAT 0x70 - -#define FPCR_BB_ACK_RPL_TIMER 0x700 -#define FPCRF_BB_ACK_TL_LBN 0 -#define FPCRF_BB_ACK_TL_WIDTH 16 -#define FPCRF_BB_RPL_TL_LBN 16 -#define FPCRF_BB_RPL_TL_WIDTH 16 - -#define FPCR_BB_ACK_FREQ 0x70C -#define FPCRF_BB_ACK_FREQ_LBN 0 -#define FPCRF_BB_ACK_FREQ_WIDTH 7 - -/************************************************************************** - * - * Pseudo-registers and fields - * - ************************************************************************** - */ - -/* Interrupt acknowledge work-around register (A0/A1 only) */ -#define FR_AA_WORK_AROUND_BROKEN_PCI_READS 0x0070 - -/* EE_SPI_HCMD_REG: SPI host command register */ -/* Values for the EE_SPI_HCMD_SF_SEL register field */ -#define FFE_AB_SPI_DEVICE_EEPROM 0 -#define FFE_AB_SPI_DEVICE_FLASH 1 - -/* NIC_STAT_REG: NIC status register */ -#define FRF_AB_STRAP_10G_LBN 2 -#define FRF_AB_STRAP_10G_WIDTH 1 -#define FRF_AA_STRAP_PCIE_LBN 0 -#define FRF_AA_STRAP_PCIE_WIDTH 1 - -/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */ -#define FRF_AZ_FATAL_INTR_LBN 0 -#define FRF_AZ_FATAL_INTR_WIDTH 12 - -/* SRM_CFG_REG: SRAM configuration register */ -/* We treat the number of SRAM banks and bank size as a single field */ -#define FRF_AZ_SRM_NB_SZ_LBN FRF_AZ_SRM_BANK_SIZE_LBN -#define FRF_AZ_SRM_NB_SZ_WIDTH \ - (FRF_AZ_SRM_BANK_SIZE_WIDTH + FRF_AZ_SRM_NUM_BANK_WIDTH) -#define FFE_AB_SRM_NB1_SZ2M 0 -#define FFE_AB_SRM_NB1_SZ4M 1 -#define FFE_AB_SRM_NB1_SZ8M 2 -#define FFE_AB_SRM_NB_SZ_DEF 3 -#define FFE_AB_SRM_NB2_SZ4M 4 -#define FFE_AB_SRM_NB2_SZ8M 5 -#define FFE_AB_SRM_NB2_SZ16M 6 -#define FFE_AB_SRM_NB_SZ_RES 7 - -/* RX_DESC_UPD_REGP0: Receive descriptor update register. */ -/* We write just the last dword of these registers */ -#define FR_AZ_RX_DESC_UPD_DWORD_P0 \ - (BUILD_BUG_ON_ZERO(FR_AA_RX_DESC_UPD_KER != FR_BZ_RX_DESC_UPD_P0) + \ - FR_BZ_RX_DESC_UPD_P0 + 3 * 4) -#define FRF_AZ_RX_DESC_WPTR_DWORD_LBN (FRF_AZ_RX_DESC_WPTR_LBN - 3 * 32) -#define FRF_AZ_RX_DESC_WPTR_DWORD_WIDTH FRF_AZ_RX_DESC_WPTR_WIDTH - -/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */ -#define FR_AZ_TX_DESC_UPD_DWORD_P0 \ - (BUILD_BUG_ON_ZERO(FR_AA_TX_DESC_UPD_KER != FR_BZ_TX_DESC_UPD_P0) + \ - FR_BZ_TX_DESC_UPD_P0 + 3 * 4) -#define FRF_AZ_TX_DESC_WPTR_DWORD_LBN (FRF_AZ_TX_DESC_WPTR_LBN - 3 * 32) -#define FRF_AZ_TX_DESC_WPTR_DWORD_WIDTH FRF_AZ_TX_DESC_WPTR_WIDTH - -/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */ -#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_LBN 12 -#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_WIDTH 1 - -/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */ -#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_LBN 12 -#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1 - -/* XM_TX_PARAM_REG: XGMAC transmit parameter register */ -#define FRF_AB_XM_MAX_TX_FRM_SIZE_LBN FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN -#define FRF_AB_XM_MAX_TX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH + \ - FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH) - -/* XM_RX_PARAM_REG: XGMAC receive parameter register */ -#define FRF_AB_XM_MAX_RX_FRM_SIZE_LBN FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN -#define FRF_AB_XM_MAX_RX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH + \ - FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH) - -/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */ -/* Default values */ -#define FFE_AB_XX_TXDRV_DEQ_DEF 0xe /* deq=.6 */ -#define FFE_AB_XX_TXDRV_DTX_DEF 0x5 /* 1.25 */ -#define FFE_AB_XX_SD_CTL_DRV_DEF 0 /* 20mA */ - -/* XX_CORE_STAT_REG: XAUI XGXS core status register */ -/* XGXS all-lanes status fields */ -#define FRF_AB_XX_SYNC_STAT_LBN FRF_AB_XX_SYNC_STAT0_LBN -#define FRF_AB_XX_SYNC_STAT_WIDTH 4 -#define FRF_AB_XX_COMMA_DET_LBN FRF_AB_XX_COMMA_DET_CH0_LBN -#define FRF_AB_XX_COMMA_DET_WIDTH 4 -#define FRF_AB_XX_CHAR_ERR_LBN FRF_AB_XX_CHAR_ERR_CH0_LBN -#define FRF_AB_XX_CHAR_ERR_WIDTH 4 -#define FRF_AB_XX_DISPERR_LBN FRF_AB_XX_DISPERR_CH0_LBN -#define FRF_AB_XX_DISPERR_WIDTH 4 -#define FFE_AB_XX_STAT_ALL_LANES 0xf -#define FRF_AB_XX_FORCE_SIG_LBN FRF_AB_XX_FORCE_SIG0_VAL_LBN -#define FRF_AB_XX_FORCE_SIG_WIDTH 8 -#define FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff - -/* RX_MAC_FILTER_TBL0 */ -/* RMFT_DEST_MAC is wider than 32 bits */ -#define FRF_CZ_RMFT_DEST_MAC_LO_LBN FRF_CZ_RMFT_DEST_MAC_LBN -#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32 -#define FRF_CZ_RMFT_DEST_MAC_HI_LBN (FRF_CZ_RMFT_DEST_MAC_LBN + 32) -#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH (FRF_CZ_RMFT_DEST_MAC_WIDTH - 32) - -/* TX_MAC_FILTER_TBL0 */ -/* TMFT_SRC_MAC is wider than 32 bits */ -#define FRF_CZ_TMFT_SRC_MAC_LO_LBN FRF_CZ_TMFT_SRC_MAC_LBN -#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32 -#define FRF_CZ_TMFT_SRC_MAC_HI_LBN (FRF_CZ_TMFT_SRC_MAC_LBN + 32) -#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH (FRF_CZ_TMFT_SRC_MAC_WIDTH - 32) - -/* TX_PACE_TBL */ -/* Values >20 are documented as reserved, but will result in a queue going - * into the fast bin with a pace value of zero. */ -#define FFE_BZ_TX_PACE_OFF 0 -#define FFE_BZ_TX_PACE_RESERVED 21 - -/* DRIVER_EV */ -/* Sub-fields of an RX flush completion event */ -#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12 -#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1 -#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_LBN 0 -#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_WIDTH 12 - -/* EVENT_ENTRY */ -/* Magic number field for event test */ -#define FSF_AZ_DRV_GEN_EV_MAGIC_LBN 0 -#define FSF_AZ_DRV_GEN_EV_MAGIC_WIDTH 32 - -/* RX packet prefix */ -#define FS_BZ_RX_PREFIX_HASH_OFST 12 -#define FS_BZ_RX_PREFIX_SIZE 16 - -#endif /* EFX_FARCH_REGS_H */ diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index a7f2c31071e8..86cfd4713b11 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -10,7 +10,6 @@ #include "net_driver.h" #include "nic.h" #include "io.h" -#include "farch_regs.h" #include "mcdi_pcol.h" /************************************************************************** diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index a7a22b019794..b64a68a51050 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -237,7 +237,7 @@ struct efx_tx_buffer { * Normally this will equal @write_count, but as option descriptors * don't produce completion events, they won't update this. * Filled in iff @efx->type->option_descriptors; only used for PIO. - * Thus, this is written and used on EF10, and neither on farch. + * Thus, this is only written and used on EF10. * @old_read_count: The value of read_count when last checked. * This is here for performance reasons. The xmit path will * only get the up-to-date value of read_count if this @@ -1288,8 +1288,7 @@ struct efx_udp_tunnel { * @set_wol: Push WoL configuration to the NIC * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) * @get_fec_stats: Get standard FEC statistics. - * @test_chip: Test registers. May use efx_farch_test_registers(), and is - * expected to reset the NIC. + * @test_chip: Test registers. This is expected to reset the NIC. * @test_nvram: Test validity of NVRAM contents * @mcdi_request: Send an MCDI request with the given header and SDU. * The SDU length may be any value from 0 up to the protocol- diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 63e2394382bb..7e057741425f 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -17,7 +17,6 @@ #include "efx.h" #include "nic.h" #include "ef10_regs.h" -#include "farch_regs.h" #include "io.h" #include "workarounds.h" #include "mcdi_pcol.h" @@ -172,10 +171,6 @@ void efx_nic_fini_interrupt(struct efx_nic *efx) /* Register dump */ -#define REGISTER_REVISION_FA 1 -#define REGISTER_REVISION_FB 2 -#define REGISTER_REVISION_FC 3 -#define REGISTER_REVISION_FZ 3 /* last Falcon arch revision */ #define REGISTER_REVISION_ED 4 #define REGISTER_REVISION_EZ 4 /* latest EF10 revision */ @@ -189,117 +184,9 @@ struct efx_nic_reg { REGISTER_REVISION_ ## arch ## min_rev, \ REGISTER_REVISION_ ## arch ## max_rev \ } -#define REGISTER_AA(name) REGISTER(name, F, A, A) -#define REGISTER_AB(name) REGISTER(name, F, A, B) -#define REGISTER_AZ(name) REGISTER(name, F, A, Z) -#define REGISTER_BB(name) REGISTER(name, F, B, B) -#define REGISTER_BZ(name) REGISTER(name, F, B, Z) -#define REGISTER_CZ(name) REGISTER(name, F, C, Z) #define REGISTER_DZ(name) REGISTER(name, E, D, Z) static const struct efx_nic_reg efx_nic_regs[] = { - REGISTER_AZ(ADR_REGION), - REGISTER_AZ(INT_EN_KER), - REGISTER_BZ(INT_EN_CHAR), - REGISTER_AZ(INT_ADR_KER), - REGISTER_BZ(INT_ADR_CHAR), - /* INT_ACK_KER is WO */ - /* INT_ISR0 is RC */ - REGISTER_AZ(HW_INIT), - REGISTER_CZ(USR_EV_CFG), - REGISTER_AB(EE_SPI_HCMD), - REGISTER_AB(EE_SPI_HADR), - REGISTER_AB(EE_SPI_HDATA), - REGISTER_AB(EE_BASE_PAGE), - REGISTER_AB(EE_VPD_CFG0), - /* EE_VPD_SW_CNTL and EE_VPD_SW_DATA are not used */ - /* PMBX_DBG_IADDR and PBMX_DBG_IDATA are indirect */ - /* PCIE_CORE_INDIRECT is indirect */ - REGISTER_AB(NIC_STAT), - REGISTER_AB(GPIO_CTL), - REGISTER_AB(GLB_CTL), - /* FATAL_INTR_KER and FATAL_INTR_CHAR are partly RC */ - REGISTER_BZ(DP_CTRL), - REGISTER_AZ(MEM_STAT), - REGISTER_AZ(CS_DEBUG), - REGISTER_AZ(ALTERA_BUILD), - REGISTER_AZ(CSR_SPARE), - REGISTER_AB(PCIE_SD_CTL0123), - REGISTER_AB(PCIE_SD_CTL45), - REGISTER_AB(PCIE_PCS_CTL_STAT), - /* DEBUG_DATA_OUT is not used */ - /* DRV_EV is WO */ - REGISTER_AZ(EVQ_CTL), - REGISTER_AZ(EVQ_CNT1), - REGISTER_AZ(EVQ_CNT2), - REGISTER_AZ(BUF_TBL_CFG), - REGISTER_AZ(SRM_RX_DC_CFG), - REGISTER_AZ(SRM_TX_DC_CFG), - REGISTER_AZ(SRM_CFG), - /* BUF_TBL_UPD is WO */ - REGISTER_AZ(SRM_UPD_EVQ), - REGISTER_AZ(SRAM_PARITY), - REGISTER_AZ(RX_CFG), - REGISTER_BZ(RX_FILTER_CTL), - /* RX_FLUSH_DESCQ is WO */ - REGISTER_AZ(RX_DC_CFG), - REGISTER_AZ(RX_DC_PF_WM), - REGISTER_BZ(RX_RSS_TKEY), - /* RX_NODESC_DROP is RC */ - REGISTER_AA(RX_SELF_RST), - /* RX_DEBUG, RX_PUSH_DROP are not used */ - REGISTER_CZ(RX_RSS_IPV6_REG1), - REGISTER_CZ(RX_RSS_IPV6_REG2), - REGISTER_CZ(RX_RSS_IPV6_REG3), - /* TX_FLUSH_DESCQ is WO */ - REGISTER_AZ(TX_DC_CFG), - REGISTER_AA(TX_CHKSM_CFG), - REGISTER_AZ(TX_CFG), - /* TX_PUSH_DROP is not used */ - REGISTER_AZ(TX_RESERVED), - REGISTER_BZ(TX_PACE), - /* TX_PACE_DROP_QID is RC */ - REGISTER_BB(TX_VLAN), - REGISTER_BZ(TX_IPFIL_PORTEN), - REGISTER_AB(MD_TXD), - REGISTER_AB(MD_RXD), - REGISTER_AB(MD_CS), - REGISTER_AB(MD_PHY_ADR), - REGISTER_AB(MD_ID), - /* MD_STAT is RC */ - REGISTER_AB(MAC_STAT_DMA), - REGISTER_AB(MAC_CTRL), - REGISTER_BB(GEN_MODE), - REGISTER_AB(MAC_MC_HASH_REG0), - REGISTER_AB(MAC_MC_HASH_REG1), - REGISTER_AB(GM_CFG1), - REGISTER_AB(GM_CFG2), - /* GM_IPG and GM_HD are not used */ - REGISTER_AB(GM_MAX_FLEN), - /* GM_TEST is not used */ - REGISTER_AB(GM_ADR1), - REGISTER_AB(GM_ADR2), - REGISTER_AB(GMF_CFG0), - REGISTER_AB(GMF_CFG1), - REGISTER_AB(GMF_CFG2), - REGISTER_AB(GMF_CFG3), - REGISTER_AB(GMF_CFG4), - REGISTER_AB(GMF_CFG5), - REGISTER_BB(TX_SRC_MAC_CTL), - REGISTER_AB(XM_ADR_LO), - REGISTER_AB(XM_ADR_HI), - REGISTER_AB(XM_GLB_CFG), - REGISTER_AB(XM_TX_CFG), - REGISTER_AB(XM_RX_CFG), - REGISTER_AB(XM_MGT_INT_MASK), - REGISTER_AB(XM_FC), - REGISTER_AB(XM_PAUSE_TIME), - REGISTER_AB(XM_TX_PARAM), - REGISTER_AB(XM_RX_PARAM), - /* XM_MGT_INT_MSK (note no 'A') is RC */ - REGISTER_AB(XX_PWR_RST), - REGISTER_AB(XX_SD_CTL), - REGISTER_AB(XX_TXDRV_CTL), /* XX_PRBS_CTL, XX_PRBS_CHK and XX_PRBS_ERR are not used */ /* XX_CORE_STAT is partly RC */ REGISTER_DZ(BIU_HW_REV_ID), @@ -325,49 +212,9 @@ struct efx_nic_reg_table { arch, min_rev, max_rev, \ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _STEP, \ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _ROWS) -#define REGISTER_TABLE_AA(name) REGISTER_TABLE(name, F, A, A) -#define REGISTER_TABLE_AZ(name) REGISTER_TABLE(name, F, A, Z) -#define REGISTER_TABLE_BB(name) REGISTER_TABLE(name, F, B, B) -#define REGISTER_TABLE_BZ(name) REGISTER_TABLE(name, F, B, Z) -#define REGISTER_TABLE_BB_CZ(name) \ - REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, B, B, \ - FR_BZ_ ## name ## _STEP, \ - FR_BB_ ## name ## _ROWS), \ - REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, C, Z, \ - FR_BZ_ ## name ## _STEP, \ - FR_CZ_ ## name ## _ROWS) -#define REGISTER_TABLE_CZ(name) REGISTER_TABLE(name, F, C, Z) #define REGISTER_TABLE_DZ(name) REGISTER_TABLE(name, E, D, Z) static const struct efx_nic_reg_table efx_nic_reg_tables[] = { - /* DRIVER is not used */ - /* EVQ_RPTR, TIMER_COMMAND, USR_EV and {RX,TX}_DESC_UPD are WO */ - REGISTER_TABLE_BB(TX_IPFIL_TBL), - REGISTER_TABLE_BB(TX_SRC_MAC_TBL), - REGISTER_TABLE_AA(RX_DESC_PTR_TBL_KER), - REGISTER_TABLE_BB_CZ(RX_DESC_PTR_TBL), - REGISTER_TABLE_AA(TX_DESC_PTR_TBL_KER), - REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL), - REGISTER_TABLE_AA(EVQ_PTR_TBL_KER), - REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL), - /* We can't reasonably read all of the buffer table (up to 8MB!). - * However this driver will only use a few entries. Reading - * 1K entries allows for some expansion of queue count and - * size before we need to change the version. */ - REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL_KER, FR_AA_BUF_FULL_TBL_KER, - F, A, A, 8, 1024), - REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL, - F, B, Z, 8, 1024), - REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0), - REGISTER_TABLE_BB_CZ(TIMER_TBL), - REGISTER_TABLE_BB_CZ(TX_PACE_TBL), - REGISTER_TABLE_BZ(RX_INDIRECTION_TBL), - /* TX_FILTER_TBL0 is huge and not used by this driver */ - REGISTER_TABLE_CZ(TX_MAC_FILTER_TBL0), - REGISTER_TABLE_CZ(MC_TREG_SMEM), - /* MSIX_PBA_TABLE is not mapped */ - /* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */ - REGISTER_TABLE_BZ(RX_FILTER_TBL0), REGISTER_TABLE_DZ(BIU_MC_SFT_STATUS), }; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 251868235ae4..bd17962436ba 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -11,8 +11,6 @@ #include "nic_common.h" #include "efx.h" -u32 efx_farch_fpga_ver(struct efx_nic *efx); - enum { PHY_TYPE_NONE = 0, PHY_TYPE_TXC43128 = 1, @@ -304,89 +302,8 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb, extern const struct efx_nic_type efx_hunt_a0_nic_type; extern const struct efx_nic_type efx_hunt_a0_vf_nic_type; -int falcon_probe_board(struct efx_nic *efx, u16 revision_info); - -/* Falcon/Siena queue operations */ -int efx_farch_tx_probe(struct efx_tx_queue *tx_queue); -void efx_farch_tx_init(struct efx_tx_queue *tx_queue); -void efx_farch_tx_fini(struct efx_tx_queue *tx_queue); -void efx_farch_tx_remove(struct efx_tx_queue *tx_queue); -void efx_farch_tx_write(struct efx_tx_queue *tx_queue); -unsigned int efx_farch_tx_limit_len(struct efx_tx_queue *tx_queue, - dma_addr_t dma_addr, unsigned int len); -int efx_farch_rx_probe(struct efx_rx_queue *rx_queue); -void efx_farch_rx_init(struct efx_rx_queue *rx_queue); -void efx_farch_rx_fini(struct efx_rx_queue *rx_queue); -void efx_farch_rx_remove(struct efx_rx_queue *rx_queue); -void efx_farch_rx_write(struct efx_rx_queue *rx_queue); -void efx_farch_rx_defer_refill(struct efx_rx_queue *rx_queue); -int efx_farch_ev_probe(struct efx_channel *channel); -int efx_farch_ev_init(struct efx_channel *channel); -void efx_farch_ev_fini(struct efx_channel *channel); -void efx_farch_ev_remove(struct efx_channel *channel); -int efx_farch_ev_process(struct efx_channel *channel, int quota); -void efx_farch_ev_read_ack(struct efx_channel *channel); -void efx_farch_ev_test_generate(struct efx_channel *channel); - -/* Falcon/Siena filter operations */ -int efx_farch_filter_table_probe(struct efx_nic *efx); -void efx_farch_filter_table_restore(struct efx_nic *efx); -void efx_farch_filter_table_remove(struct efx_nic *efx); -void efx_farch_filter_update_rx_scatter(struct efx_nic *efx); -s32 efx_farch_filter_insert(struct efx_nic *efx, struct efx_filter_spec *spec, - bool replace); -int efx_farch_filter_remove_safe(struct efx_nic *efx, - enum efx_filter_priority priority, - u32 filter_id); -int efx_farch_filter_get_safe(struct efx_nic *efx, - enum efx_filter_priority priority, u32 filter_id, - struct efx_filter_spec *); -int efx_farch_filter_clear_rx(struct efx_nic *efx, - enum efx_filter_priority priority); -u32 efx_farch_filter_count_rx_used(struct efx_nic *efx, - enum efx_filter_priority priority); -u32 efx_farch_filter_get_rx_id_limit(struct efx_nic *efx); -s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx, - enum efx_filter_priority priority, u32 *buf, - u32 size); -#ifdef CONFIG_RFS_ACCEL -bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id, - unsigned int index); -#endif -void efx_farch_filter_sync_rx_mode(struct efx_nic *efx); - -/* Falcon/Siena interrupts */ -void efx_farch_irq_enable_master(struct efx_nic *efx); -int efx_farch_irq_test_generate(struct efx_nic *efx); -void efx_farch_irq_disable_master(struct efx_nic *efx); -irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id); -irqreturn_t efx_farch_legacy_interrupt(int irq, void *dev_id); -irqreturn_t efx_farch_fatal_interrupt(struct efx_nic *efx); - /* Global Resources */ void siena_prepare_flush(struct efx_nic *efx); -int efx_farch_fini_dmaq(struct efx_nic *efx); -void efx_farch_finish_flr(struct efx_nic *efx); void siena_finish_flush(struct efx_nic *efx); -void falcon_start_nic_stats(struct efx_nic *efx); -void falcon_stop_nic_stats(struct efx_nic *efx); -int falcon_reset_xaui(struct efx_nic *efx); -void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw); -void efx_farch_init_common(struct efx_nic *efx); -void efx_farch_rx_push_indir_table(struct efx_nic *efx); -void efx_farch_rx_pull_indir_table(struct efx_nic *efx); - -/* Tests */ -struct efx_farch_register_test { - unsigned address; - efx_oword_t mask; -}; - -int efx_farch_test_registers(struct efx_nic *efx, - const struct efx_farch_register_test *regs, - size_t n_regs); - -void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq, - efx_qword_t *event); #endif /* EFX_NIC_H */ diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 0c40571133cb..9c17cd24c549 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -43,7 +43,6 @@ #include "mcdi.h" #include "mcdi_pcol.h" #include "io.h" -#include "farch_regs.h" #include "tx.h" #include "nic.h" /* indirectly includes ptp.h */ #include "efx_channels.h" -- cgit From e714e5b24413e725cbb5148e605c4fa352693523 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:40:48 +0100 Subject: sfc: Remove siena_nic_data and stats These are no longer used, and the two Siena specific functions are no longer present in sfc.ko. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/nic.h | 95 ------------------------------------------ 1 file changed, 95 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index bd17962436ba..1db64fc6e909 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -23,97 +23,6 @@ enum { PHY_TYPE_SFT9001B = 10, }; -enum { - SIENA_STAT_tx_bytes = GENERIC_STAT_COUNT, - SIENA_STAT_tx_good_bytes, - SIENA_STAT_tx_bad_bytes, - SIENA_STAT_tx_packets, - SIENA_STAT_tx_bad, - SIENA_STAT_tx_pause, - SIENA_STAT_tx_control, - SIENA_STAT_tx_unicast, - SIENA_STAT_tx_multicast, - SIENA_STAT_tx_broadcast, - SIENA_STAT_tx_lt64, - SIENA_STAT_tx_64, - SIENA_STAT_tx_65_to_127, - SIENA_STAT_tx_128_to_255, - SIENA_STAT_tx_256_to_511, - SIENA_STAT_tx_512_to_1023, - SIENA_STAT_tx_1024_to_15xx, - SIENA_STAT_tx_15xx_to_jumbo, - SIENA_STAT_tx_gtjumbo, - SIENA_STAT_tx_collision, - SIENA_STAT_tx_single_collision, - SIENA_STAT_tx_multiple_collision, - SIENA_STAT_tx_excessive_collision, - SIENA_STAT_tx_deferred, - SIENA_STAT_tx_late_collision, - SIENA_STAT_tx_excessive_deferred, - SIENA_STAT_tx_non_tcpudp, - SIENA_STAT_tx_mac_src_error, - SIENA_STAT_tx_ip_src_error, - SIENA_STAT_rx_bytes, - SIENA_STAT_rx_good_bytes, - SIENA_STAT_rx_bad_bytes, - SIENA_STAT_rx_packets, - SIENA_STAT_rx_good, - SIENA_STAT_rx_bad, - SIENA_STAT_rx_pause, - SIENA_STAT_rx_control, - SIENA_STAT_rx_unicast, - SIENA_STAT_rx_multicast, - SIENA_STAT_rx_broadcast, - SIENA_STAT_rx_lt64, - SIENA_STAT_rx_64, - SIENA_STAT_rx_65_to_127, - SIENA_STAT_rx_128_to_255, - SIENA_STAT_rx_256_to_511, - SIENA_STAT_rx_512_to_1023, - SIENA_STAT_rx_1024_to_15xx, - SIENA_STAT_rx_15xx_to_jumbo, - SIENA_STAT_rx_gtjumbo, - SIENA_STAT_rx_bad_gtjumbo, - SIENA_STAT_rx_overflow, - SIENA_STAT_rx_false_carrier, - SIENA_STAT_rx_symbol_error, - SIENA_STAT_rx_align_error, - SIENA_STAT_rx_length_error, - SIENA_STAT_rx_internal_error, - SIENA_STAT_rx_nodesc_drop_cnt, - SIENA_STAT_COUNT -}; - -/** - * struct siena_nic_data - Siena NIC state - * @efx: Pointer back to main interface structure - * @wol_filter_id: Wake-on-LAN packet filter id - * @stats: Hardware statistics - * @vf: Array of &struct siena_vf objects - * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. - * @vfdi_status: Common VFDI status page to be dmad to VF address space. - * @local_addr_list: List of local addresses. Protected by %local_lock. - * @local_page_list: List of DMA addressable pages used to broadcast - * %local_addr_list. Protected by %local_lock. - * @local_lock: Mutex protecting %local_addr_list and %local_page_list. - * @peer_work: Work item to broadcast peer addresses to VMs. - */ -struct siena_nic_data { - struct efx_nic *efx; - int wol_filter_id; - u64 stats[SIENA_STAT_COUNT]; -#ifdef CONFIG_SFC_SRIOV - struct siena_vf *vf; - struct efx_channel *vfdi_channel; - unsigned vf_buftbl_base; - struct efx_buffer vfdi_status; - struct list_head local_addr_list; - struct list_head local_page_list; - struct mutex local_lock; - struct work_struct peer_work; -#endif -}; - enum { EF10_STAT_port_tx_bytes = GENERIC_STAT_COUNT, EF10_STAT_port_tx_packets, @@ -302,8 +211,4 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb, extern const struct efx_nic_type efx_hunt_a0_nic_type; extern const struct efx_nic_type efx_hunt_a0_vf_nic_type; -/* Global Resources */ -void siena_prepare_flush(struct efx_nic *efx); -void siena_finish_flush(struct efx_nic *efx); - #endif /* EFX_NIC_H */ -- cgit From f294c1f7bfbdc7fb86ca177e9fe592d830820299 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:40:54 +0100 Subject: sfc: Remove support for siena high priority queue This also removes TC support code, since that was never supported for EF10. TC support for EF100 is not handled from efx.c. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 1 - drivers/net/ethernet/sfc/efx.h | 2 -- drivers/net/ethernet/sfc/net_driver.h | 4 +--- drivers/net/ethernet/sfc/tx.c | 45 +---------------------------------- 4 files changed, 2 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index d670a319b379..19f4b4d0b851 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -605,7 +605,6 @@ static const struct net_device_ops efx_netdev_ops = { #endif .ndo_get_phys_port_id = efx_get_phys_port_id, .ndo_get_phys_port_name = efx_get_phys_port_name, - .ndo_setup_tc = efx_setup_tc, #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = efx_filter_rfs, #endif diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 4239c7ece123..48d3623735ba 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -30,8 +30,6 @@ static inline netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct tx_queue, skb); } void efx_xmit_done_single(struct efx_tx_queue *tx_queue); -int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type, - void *type_data); extern unsigned int efx_piobuf_size; /* RX */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index b64a68a51050..25013caaeefb 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -67,9 +67,7 @@ #define EFX_MAX_CORE_TX_QUEUES (EFX_MAX_TX_TC * EFX_MAX_CHANNELS) #define EFX_TXQ_TYPE_OUTER_CSUM 1 /* Outer checksum offload */ #define EFX_TXQ_TYPE_INNER_CSUM 2 /* Inner checksum offload */ -#define EFX_TXQ_TYPE_HIGHPRI 4 /* High-priority (for TC) */ -#define EFX_TXQ_TYPES 8 -/* HIGHPRI is Siena-only, and INNER_CSUM is EF10, so no need for both */ +#define EFX_TXQ_TYPES 4 #define EFX_MAX_TXQ_PER_CHANNEL 4 #define EFX_MAX_TX_QUEUES (EFX_MAX_TXQ_PER_CHANNEL * EFX_MAX_CHANNELS) diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 4ed4082836a9..fe2d476028e7 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -517,13 +517,8 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, unsigned index, type; EFX_WARN_ON_PARANOID(!netif_device_present(net_dev)); - index = skb_get_queue_mapping(skb); type = efx_tx_csum_type_skb(skb); - if (index >= efx->n_tx_channels) { - index -= efx->n_tx_channels; - type |= EFX_TXQ_TYPE_HIGHPRI; - } /* PTP "event" packet */ if (unlikely(efx_xmit_with_hwtstamp(skb)) && @@ -603,43 +598,5 @@ void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue) /* Must be inverse of queue lookup in efx_hard_start_xmit() */ tx_queue->core_txq = netdev_get_tx_queue(efx->net_dev, - tx_queue->channel->channel + - ((tx_queue->type & EFX_TXQ_TYPE_HIGHPRI) ? - efx->n_tx_channels : 0)); -} - -int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type, - void *type_data) -{ - struct efx_nic *efx = efx_netdev_priv(net_dev); - struct tc_mqprio_qopt *mqprio = type_data; - unsigned tc, num_tc; - - if (type != TC_SETUP_QDISC_MQPRIO) - return -EOPNOTSUPP; - - /* Only Siena supported highpri queues */ - if (efx_nic_rev(efx) > EFX_REV_SIENA_A0) - return -EOPNOTSUPP; - - num_tc = mqprio->num_tc; - - if (num_tc > EFX_MAX_TX_TC) - return -EINVAL; - - mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; - - if (num_tc == net_dev->num_tc) - return 0; - - for (tc = 0; tc < num_tc; tc++) { - net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels; - net_dev->tc_to_txq[tc].count = efx->n_tx_channels; - } - - net_dev->num_tc = num_tc; - - return netif_set_real_num_tx_queues(net_dev, - max_t(int, num_tc, 1) * - efx->n_tx_channels); + tx_queue->channel->channel); } -- cgit From 958d58bb994092d22c0aaaf81279e6d47e3cda97 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:40:59 +0100 Subject: sfc: Remove EFX_REV_SIENA_A0 The workarounds for bug 8568 and 17213 are no longer needed. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/nic_common.h | 3 +-- drivers/net/ethernet/sfc/workarounds.h | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h index 0cef35c0c559..e35ecbe8842e 100644 --- a/drivers/net/ethernet/sfc/nic_common.h +++ b/drivers/net/ethernet/sfc/nic_common.h @@ -15,11 +15,10 @@ #include "ptp.h" enum { - /* Revisions 0-2 were Falcon A0, A1 and B0 respectively. + /* Revisions 0-3 were Falcon A0, A1, B0 and Siena respectively. * They are not supported by this driver but these revision numbers * form part of the ethtool API for register dumping. */ - EFX_REV_SIENA_A0 = 3, EFX_REV_HUNT_A0 = 4, EFX_REV_EF100 = 5, }; diff --git a/drivers/net/ethernet/sfc/workarounds.h b/drivers/net/ethernet/sfc/workarounds.h index 815be2d20c4b..e10e7f84958d 100644 --- a/drivers/net/ethernet/sfc/workarounds.h +++ b/drivers/net/ethernet/sfc/workarounds.h @@ -12,14 +12,7 @@ * Bug numbers are from Solarflare's Bugzilla. */ -#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0) #define EFX_WORKAROUND_EF10(efx) (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) -#define EFX_WORKAROUND_10G(efx) 1 - -/* Bit-bashed I2C reads cause performance drop */ -#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G -/* Legacy interrupt storm when interrupt fifo fills */ -#define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA /* Lockup when writing event block registers at gen2/gen3 */ #define EFX_EF10_WORKAROUND_35388(efx) \ -- cgit From 1c145a5dc3701018ea5b3ea4ef0d5ae3ec7cbb41 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:05 +0100 Subject: sfc: Remove PTP code for Siena rx_tx_inline is now always true. The special event list is no longer needed, event handling is always inline. Event MCDI_EVENT_CODE_PTP_RX is no longer needed. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mcdi.c | 1 - drivers/net/ethernet/sfc/ptp.c | 226 +--------------------------------------- 2 files changed, 1 insertion(+), 226 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 86cfd4713b11..f7ffaa14fda4 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1357,7 +1357,6 @@ void efx_mcdi_process_event(struct efx_channel *channel, efx->type->sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); break; - case MCDI_EVENT_CODE_PTP_RX: case MCDI_EVENT_CODE_PTP_FAULT: case MCDI_EVENT_CODE_PTP_PPS: efx_ptp_event(efx, event); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 9c17cd24c549..3eab1802f6b0 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -86,9 +86,6 @@ #define PTP_V1_VERSION_LENGTH 2 #define PTP_V1_VERSION_OFFSET 28 -#define PTP_V1_UUID_LENGTH 6 -#define PTP_V1_UUID_OFFSET 50 - #define PTP_V1_SEQUENCE_LENGTH 2 #define PTP_V1_SEQUENCE_OFFSET 58 @@ -100,17 +97,6 @@ #define PTP_V2_VERSION_LENGTH 1 #define PTP_V2_VERSION_OFFSET 29 -#define PTP_V2_UUID_LENGTH 8 -#define PTP_V2_UUID_OFFSET 48 - -/* Although PTP V2 UUIDs are comprised a ClockIdentity (8) and PortNumber (2), - * the MC only captures the last six bytes of the clock identity. These values - * reflect those, not the ones used in the standard. The standard permits - * mapping of V1 UUIDs to V2 UUIDs with these same values. - */ -#define PTP_V2_MC_UUID_LENGTH 6 -#define PTP_V2_MC_UUID_OFFSET 50 - #define PTP_V2_SEQUENCE_LENGTH 2 #define PTP_V2_SEQUENCE_OFFSET 58 @@ -166,14 +152,12 @@ enum ptp_packet_state { /** * struct efx_ptp_match - Matching structure, stored in sk_buff's cb area. - * @words: UUID and (partial) sequence number * @expiry: Time after which the packet should be delivered irrespective of * event arrival. * @state: The state of the packet - whether it is ready for processing or * whether that is of no interest. */ struct efx_ptp_match { - u32 words[DIV_ROUND_UP(PTP_V1_UUID_LENGTH, 4)]; unsigned long expiry; enum ptp_packet_state state; }; @@ -235,15 +219,9 @@ struct efx_ptp_rxfilter { /** * struct efx_ptp_data - Precision Time Protocol (PTP) state * @efx: The NIC context - * @channel: The PTP channel (Siena only) - * @rx_ts_inline: Flag for whether RX timestamps are inline (else they are - * separate events) + * @channel: The PTP channel (for Medford and Medford2) * @rxq: Receive SKB queue (awaiting timestamps) * @txq: Transmit SKB queue - * @evt_list: List of MC receive events awaiting packets - * @evt_free_list: List of free events - * @evt_lock: Lock for manipulating evt_list and evt_free_list - * @rx_evts: Instantiated events (on evt_list and evt_free_list) * @workwq: Work queue for processing pending PTP operations * @work: Work task * @cleanup_work: Work task for periodic cleanup @@ -309,13 +287,8 @@ struct efx_ptp_rxfilter { struct efx_ptp_data { struct efx_nic *efx; struct efx_channel *channel; - bool rx_ts_inline; struct sk_buff_head rxq; struct sk_buff_head txq; - struct list_head evt_list; - struct list_head evt_free_list; - spinlock_t evt_lock; - struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; struct workqueue_struct *workwq; struct work_struct work; struct delayed_work cleanup_work; @@ -464,25 +437,6 @@ size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats) return PTP_STAT_COUNT; } -/* For Siena platforms NIC time is s and ns */ -static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) -{ - struct timespec64 ts = ns_to_timespec64(ns); - *nic_major = (u32)ts.tv_sec; - *nic_minor = ts.tv_nsec; -} - -static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor, - s32 correction) -{ - ktime_t kt = ktime_set(nic_major, nic_minor); - if (correction >= 0) - kt = ktime_add_ns(kt, (u64)correction); - else - kt = ktime_sub_ns(kt, (u64)-correction); - return kt; -} - /* To convert from s27 format to ns we multiply then divide by a power of 2. * For the conversion from ns to s27, the operation is also converted to a * multiply and shift. @@ -696,12 +650,6 @@ static int efx_ptp_get_attributes(struct efx_nic *efx) ptp->nic_time.minor_max = 1 << 27; ptp->nic_time.sync_event_minor_shift = 19; break; - case MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS: - ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; - ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction; - ptp->nic_time.minor_max = 1000000000; - ptp->nic_time.sync_event_minor_shift = 22; - break; case MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_QTR_NANOSECONDS: ptp->ns_to_nic_time = efx_ptp_ns_to_s_qns; ptp->nic_to_kernel_time = efx_ptp_s_qns_to_ktime_correction; @@ -1216,76 +1164,6 @@ fail: return; } -static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) -{ - struct efx_ptp_data *ptp = efx->ptp_data; - struct list_head *cursor; - struct list_head *next; - - if (ptp->rx_ts_inline) - return; - - /* Drop time-expired events */ - spin_lock_bh(&ptp->evt_lock); - list_for_each_safe(cursor, next, &ptp->evt_list) { - struct efx_ptp_event_rx *evt; - - evt = list_entry(cursor, struct efx_ptp_event_rx, - link); - if (time_after(jiffies, evt->expiry)) { - list_move(&evt->link, &ptp->evt_free_list); - netif_warn(efx, hw, efx->net_dev, - "PTP rx event dropped\n"); - } - } - spin_unlock_bh(&ptp->evt_lock); -} - -static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, - struct sk_buff *skb) -{ - struct efx_ptp_data *ptp = efx->ptp_data; - bool evts_waiting; - struct list_head *cursor; - struct list_head *next; - struct efx_ptp_match *match; - enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED; - - WARN_ON_ONCE(ptp->rx_ts_inline); - - spin_lock_bh(&ptp->evt_lock); - evts_waiting = !list_empty(&ptp->evt_list); - spin_unlock_bh(&ptp->evt_lock); - - if (!evts_waiting) - return PTP_PACKET_STATE_UNMATCHED; - - match = (struct efx_ptp_match *)skb->cb; - /* Look for a matching timestamp in the event queue */ - spin_lock_bh(&ptp->evt_lock); - list_for_each_safe(cursor, next, &ptp->evt_list) { - struct efx_ptp_event_rx *evt; - - evt = list_entry(cursor, struct efx_ptp_event_rx, link); - if ((evt->seq0 == match->words[0]) && - (evt->seq1 == match->words[1])) { - struct skb_shared_hwtstamps *timestamps; - - /* Match - add in hardware timestamp */ - timestamps = skb_hwtstamps(skb); - timestamps->hwtstamp = evt->hwtimestamp; - - match->state = PTP_PACKET_STATE_MATCHED; - rc = PTP_PACKET_STATE_MATCHED; - list_move(&evt->link, &ptp->evt_free_list); - break; - } - } - spin_unlock_bh(&ptp->evt_lock); - - return rc; -} - /* Process any queued receive events and corresponding packets * * q is returned with all the packets that are ready for delivery. @@ -1301,9 +1179,6 @@ static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) match = (struct efx_ptp_match *)skb->cb; if (match->state == PTP_PACKET_STATE_MATCH_UNWANTED) { __skb_queue_tail(q, skb); - } else if (efx_ptp_match_rx(efx, skb) == - PTP_PACKET_STATE_MATCHED) { - __skb_queue_tail(q, skb); } else if (time_after(jiffies, match->expiry)) { match->state = PTP_PACKET_STATE_TIMED_OUT; ++ptp->rx_no_timestamp; @@ -1580,8 +1455,6 @@ fail: static int efx_ptp_stop(struct efx_nic *efx) { struct efx_ptp_data *ptp = efx->ptp_data; - struct list_head *cursor; - struct list_head *next; int rc; if (ptp == NULL) @@ -1596,13 +1469,6 @@ static int efx_ptp_stop(struct efx_nic *efx) efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq); skb_queue_purge(&efx->ptp_data->txq); - /* Drop any pending receive events */ - spin_lock_bh(&efx->ptp_data->evt_lock); - list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { - list_move(cursor, &efx->ptp_data->evt_free_list); - } - spin_unlock_bh(&efx->ptp_data->evt_lock); - return rc; } @@ -1642,8 +1508,6 @@ static void efx_ptp_worker(struct work_struct *work) return; } - efx_ptp_drop_time_expired_events(efx); - __skb_queue_head_init(&tempq); efx_ptp_process_events(efx, &tempq); @@ -1692,7 +1556,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) { struct efx_ptp_data *ptp; int rc = 0; - unsigned int pos; if (efx->ptp_data) { efx->ptp_data->channel = channel; @@ -1706,7 +1569,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) ptp->efx = efx; ptp->channel = channel; - ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); if (rc != 0) @@ -1733,12 +1595,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) ptp->config.flags = 0; ptp->config.tx_type = HWTSTAMP_TX_OFF; ptp->config.rx_filter = HWTSTAMP_FILTER_NONE; - INIT_LIST_HEAD(&ptp->evt_list); - INIT_LIST_HEAD(&ptp->evt_free_list); - spin_lock_init(&ptp->evt_lock); - for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) - list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); - INIT_LIST_HEAD(&ptp->rxfilters_mcast); INIT_LIST_HEAD(&ptp->rxfilters_ucast); @@ -1878,7 +1734,6 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) struct efx_nic *efx = channel->efx; struct efx_ptp_data *ptp = efx->ptp_data; struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; - u8 *match_data_012, *match_data_345; unsigned int version; u8 *data; @@ -1894,12 +1749,6 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) if (version != PTP_VERSION_V1) { return false; } - - /* PTP V1 uses all six bytes of the UUID to match the packet - * to the timestamp - */ - match_data_012 = data + PTP_V1_UUID_OFFSET; - match_data_345 = data + PTP_V1_UUID_OFFSET + 3; } else { if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) { return false; @@ -1909,21 +1758,6 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) { return false; } - - /* The original V2 implementation uses bytes 2-7 of - * the UUID to match the packet to the timestamp. This - * discards two of the bytes of the MAC address used - * to create the UUID (SF bug 33070). The PTP V2 - * enhanced mode fixes this issue and uses bytes 0-2 - * and byte 5-7 of the UUID. - */ - match_data_345 = data + PTP_V2_UUID_OFFSET + 5; - if (ptp->mode == MC_CMD_PTP_MODE_V2) { - match_data_012 = data + PTP_V2_UUID_OFFSET + 2; - } else { - match_data_012 = data + PTP_V2_UUID_OFFSET + 0; - BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); - } } /* Does this packet require timestamping? */ @@ -1935,17 +1769,6 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) */ BUILD_BUG_ON(PTP_V1_SEQUENCE_OFFSET != PTP_V2_SEQUENCE_OFFSET); BUILD_BUG_ON(PTP_V1_SEQUENCE_LENGTH != PTP_V2_SEQUENCE_LENGTH); - - /* Extract UUID/Sequence information */ - match->words[0] = (match_data_012[0] | - (match_data_012[1] << 8) | - (match_data_012[2] << 16) | - (match_data_345[0] << 24)); - match->words[1] = (match_data_345[1] | - (match_data_345[2] << 8) | - (data[PTP_V1_SEQUENCE_OFFSET + - PTP_V1_SEQUENCE_LENGTH - 1] << - 16)); } else { match->state = PTP_PACKET_STATE_MATCH_UNWANTED; } @@ -2109,50 +1932,6 @@ static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len) queue_work(ptp->workwq, &ptp->work); } -/* Process a completed receive event. Put it on the event queue and - * start worker thread. This is required because event and their - * correspoding packets may come in either order. - */ -static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) -{ - struct efx_ptp_event_rx *evt = NULL; - - if (WARN_ON_ONCE(ptp->rx_ts_inline)) - return; - - if (ptp->evt_frag_idx != 3) { - ptp_event_failure(efx, 3); - return; - } - - spin_lock_bh(&ptp->evt_lock); - if (!list_empty(&ptp->evt_free_list)) { - evt = list_first_entry(&ptp->evt_free_list, - struct efx_ptp_event_rx, link); - list_del(&evt->link); - - evt->seq0 = EFX_QWORD_FIELD(ptp->evt_frags[2], MCDI_EVENT_DATA); - evt->seq1 = (EFX_QWORD_FIELD(ptp->evt_frags[2], - MCDI_EVENT_SRC) | - (EFX_QWORD_FIELD(ptp->evt_frags[1], - MCDI_EVENT_SRC) << 8) | - (EFX_QWORD_FIELD(ptp->evt_frags[0], - MCDI_EVENT_SRC) << 16)); - evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time( - EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), - EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA), - ptp->ts_corrections.ptp_rx); - evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); - list_add_tail(&evt->link, &ptp->evt_list); - - queue_work(ptp->workwq, &ptp->work); - } else if (net_ratelimit()) { - /* Log a rate-limited warning message. */ - netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); - } - spin_unlock_bh(&ptp->evt_lock); -} - static void ptp_event_fault(struct efx_nic *efx, struct efx_ptp_data *ptp) { int code = EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA); @@ -2199,9 +1978,6 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) if (!MCDI_EVENT_FIELD(*ev, CONT)) { /* Process resulting event */ switch (code) { - case MCDI_EVENT_CODE_PTP_RX: - ptp_event_rx(efx, ptp); - break; case MCDI_EVENT_CODE_PTP_FAULT: ptp_event_fault(efx, ptp); break; -- cgit From a623b3a58a85114d40d4857d1a0d269006a3ae7d Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:10 +0100 Subject: sfc: Remove some NIC type indirections that are no longer needed The special handling for SRIOV reset and FLR is not needed on EF10. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 2 -- drivers/net/ethernet/sfc/ef10_sriov.h | 2 -- drivers/net/ethernet/sfc/efx_common.c | 2 -- drivers/net/ethernet/sfc/mcdi.c | 5 ----- drivers/net/ethernet/sfc/net_driver.h | 8 -------- 5 files changed, 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 8c019f382a7f..fca0cf338510 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -4267,8 +4267,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .sriov_init = efx_ef10_sriov_init, .sriov_fini = efx_ef10_sriov_fini, .sriov_wanted = efx_ef10_sriov_wanted, - .sriov_reset = efx_ef10_sriov_reset, - .sriov_flr = efx_ef10_sriov_flr, .sriov_set_vf_mac = efx_ef10_sriov_set_vf_mac, .sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan, .sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk, diff --git a/drivers/net/ethernet/sfc/ef10_sriov.h b/drivers/net/ethernet/sfc/ef10_sriov.h index 3c703ca878b0..be419c9c5dec 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.h +++ b/drivers/net/ethernet/sfc/ef10_sriov.h @@ -35,9 +35,7 @@ static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs); int efx_ef10_sriov_init(struct efx_nic *efx); -static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} void efx_ef10_sriov_fini(struct efx_nic *efx); -static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {} int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf, const u8 *mac); diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 361687de308d..c8d8f1e9a21a 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -785,8 +785,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) mutex_unlock(&efx->rss_lock); efx->type->filter_table_restore(efx); up_write(&efx->filter_sem); - if (efx->type->sriov_reset) - efx->type->sriov_reset(efx); mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index f7ffaa14fda4..d23da9627338 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1352,11 +1352,6 @@ void efx_mcdi_process_event(struct efx_channel *channel, case MCDI_EVENT_CODE_MAC_STATS_DMA: /* MAC stats are gather lazily. We can ignore this. */ break; - case MCDI_EVENT_CODE_FLR: - if (efx->type->sriov_flr) - efx->type->sriov_flr(efx, - MCDI_EVENT_FIELD(*event, FLR_VF)); - break; case MCDI_EVENT_CODE_PTP_FAULT: case MCDI_EVENT_CODE_PTP_PPS: efx_ptp_event(efx, event); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 25013caaeefb..474ee577bf0f 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1261,10 +1261,6 @@ struct efx_udp_tunnel { * @remove_port: Free resources allocated by probe_port() * @handle_global_event: Handle a "global" event (may be %NULL) * @fini_dmaq: Flush and finalise DMA queues (RX and TX queues) - * @prepare_flush: Prepare the hardware for flushing the DMA queues - * (for Falcon architecture) - * @finish_flush: Clean up after flushing the DMA queues (for Falcon - * architecture) * @prepare_flr: Prepare for an FLR * @finish_flr: Clean up after an FLR * @describe_stats: Describe statistics for ethtool @@ -1411,8 +1407,6 @@ struct efx_nic_type { void (*remove_port)(struct efx_nic *efx); bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); int (*fini_dmaq)(struct efx_nic *efx); - void (*prepare_flush)(struct efx_nic *efx); - void (*finish_flush)(struct efx_nic *efx); void (*prepare_flr)(struct efx_nic *efx); void (*finish_flr)(struct efx_nic *efx); size_t (*describe_stats)(struct efx_nic *efx, u8 *names); @@ -1528,8 +1522,6 @@ struct efx_nic_type { int (*sriov_init)(struct efx_nic *efx); void (*sriov_fini)(struct efx_nic *efx); bool (*sriov_wanted)(struct efx_nic *efx); - void (*sriov_reset)(struct efx_nic *efx); - void (*sriov_flr)(struct efx_nic *efx, unsigned vf_i); int (*sriov_set_vf_mac)(struct efx_nic *efx, int vf_i, const u8 *mac); int (*sriov_set_vf_vlan)(struct efx_nic *efx, int vf_i, u16 vlan, u8 qos); -- cgit From a847431c5ba59c478cfa2aa269854912e774a4a4 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:15 +0100 Subject: sfc: Filter cleanups for Falcon and Siena unicast_filter and multicast_hash are no longer needed. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mcdi_port_common.c | 5 ----- drivers/net/ethernet/sfc/net_driver.h | 18 ------------------ 2 files changed, 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mcdi_port_common.c b/drivers/net/ethernet/sfc/mcdi_port_common.c index 0ab14f3d01d4..76ea26722ca4 100644 --- a/drivers/net/ethernet/sfc/mcdi_port_common.c +++ b/drivers/net/ethernet/sfc/mcdi_port_common.c @@ -1106,11 +1106,6 @@ int efx_mcdi_set_mac(struct efx_nic *efx) MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU, efx_calc_mac_mtu(efx)); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0); - - /* Set simple MAC filter for Siena */ - MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT, - SET_MAC_IN_REJECT_UNCST, efx->unicast_filter); - MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_FLAGS, SET_MAC_IN_FLAG_INCLUDE_FCS, !!(efx->net_dev->features & NETIF_F_RXFCS)); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 474ee577bf0f..6654fbb8f4c0 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -752,18 +752,6 @@ struct efx_hw_stat_desc { u16 offset; }; -/* Number of bits used in a multicast filter hash address */ -#define EFX_MCAST_HASH_BITS 8 - -/* Number of (single-bit) entries in a multicast filter hash */ -#define EFX_MCAST_HASH_ENTRIES (1 << EFX_MCAST_HASH_BITS) - -/* An Efx multicast filter hash */ -union efx_multicast_hash { - u8 byte[EFX_MCAST_HASH_ENTRIES / 8]; - efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8]; -}; - struct vfdi_status; /* The reserved RSS context value */ @@ -955,10 +943,6 @@ struct efx_mae; * see &enum ethtool_fec_config_bits. * @link_state: Current state of the link * @n_link_state_changes: Number of times the link has changed state - * @unicast_filter: Flag for Falcon-arch simple unicast filter. - * Protected by @mac_lock. - * @multicast_hash: Multicast hash table for Falcon-arch. - * Protected by @mac_lock. * @wanted_fc: Wanted flow control flags * @fc_disable: When non-zero flow control is disabled. Typically used to * ensure that network back pressure doesn't delay dma queue flushes. @@ -1137,8 +1121,6 @@ struct efx_nic { struct efx_link_state link_state; unsigned int n_link_state_changes; - bool unicast_filter; - union efx_multicast_hash multicast_hash; u8 wanted_fc; unsigned fc_disable; -- cgit From d73e77153b4db65fccb49e8a6849c496e6f2e9f2 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:21 +0100 Subject: sfc: Remove struct efx_special_buffer The attributes index and entries are no longer needed, so use struct efx_buffer instead. next_buffer_table was also Siena specific. Removed some checkpatch warnings. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/ef100_nic.c | 2 +- drivers/net/ethernet/sfc/ef100_tx.c | 6 +++--- drivers/net/ethernet/sfc/efx_channels.c | 30 +----------------------------- drivers/net/ethernet/sfc/mcdi_functions.c | 24 ++++++++++++------------ drivers/net/ethernet/sfc/net_driver.h | 28 +++------------------------- drivers/net/ethernet/sfc/nic_common.h | 6 +++--- drivers/net/ethernet/sfc/tx_tso.c | 2 +- 8 files changed, 25 insertions(+), 75 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index fca0cf338510..6dfa062feebc 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2209,7 +2209,7 @@ static int efx_ef10_tx_probe(struct efx_tx_queue *tx_queue) /* low two bits of label are what we want for type */ BUILD_BUG_ON((EFX_TXQ_TYPE_OUTER_CSUM | EFX_TXQ_TYPE_INNER_CSUM) != 3); tx_queue->type = tx_queue->label & 3; - return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd.buf, + return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd, (tx_queue->ptr_mask + 1) * sizeof(efx_qword_t), GFP_KERNEL); diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 7adde9639c8a..f3e8ed578c09 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -224,7 +224,7 @@ int efx_ef100_init_datapath_caps(struct efx_nic *efx) static int ef100_ev_probe(struct efx_channel *channel) { /* Allocate an extra descriptor for the QMDA status completion entry */ - return efx_nic_alloc_buffer(channel->efx, &channel->eventq.buf, + return efx_nic_alloc_buffer(channel->efx, &channel->eventq, (channel->eventq_mask + 2) * sizeof(efx_qword_t), GFP_KERNEL); diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c index 849e5555bd12..e6b6be549581 100644 --- a/drivers/net/ethernet/sfc/ef100_tx.c +++ b/drivers/net/ethernet/sfc/ef100_tx.c @@ -23,7 +23,7 @@ int ef100_tx_probe(struct efx_tx_queue *tx_queue) { /* Allocate an extra descriptor for the QMDA status completion entry */ - return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd.buf, + return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd, (tx_queue->ptr_mask + 2) * sizeof(efx_oword_t), GFP_KERNEL); @@ -101,8 +101,8 @@ static bool ef100_tx_can_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb) static efx_oword_t *ef100_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index) { - if (likely(tx_queue->txd.buf.addr)) - return ((efx_oword_t *)tx_queue->txd.buf.addr) + index; + if (likely(tx_queue->txd.addr)) + return ((efx_oword_t *)tx_queue->txd.addr) + index; else return NULL; } diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c index 41b33a75333c..8d2d7ea2ebef 100644 --- a/drivers/net/ethernet/sfc/efx_channels.c +++ b/drivers/net/ethernet/sfc/efx_channels.c @@ -713,9 +713,6 @@ int efx_probe_channels(struct efx_nic *efx) struct efx_channel *channel; int rc; - /* Restart special buffer allocation */ - efx->next_buffer_table = 0; - /* Probe channels in reverse, so that any 'extra' channels * use the start of the buffer table. This allows the traffic * channels to be resized without moving them or wasting the @@ -849,36 +846,14 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel, *ptp_channel = efx_ptp_channel(efx); struct efx_ptp_data *ptp_data = efx->ptp_data; - unsigned int i, next_buffer_table = 0; u32 old_rxq_entries, old_txq_entries; + unsigned int i; int rc, rc2; rc = efx_check_disabled(efx); if (rc) return rc; - /* Not all channels should be reallocated. We must avoid - * reallocating their buffer table entries. - */ - efx_for_each_channel(channel, efx) { - struct efx_rx_queue *rx_queue; - struct efx_tx_queue *tx_queue; - - if (channel->type->copy) - continue; - next_buffer_table = max(next_buffer_table, - channel->eventq.index + - channel->eventq.entries); - efx_for_each_channel_rx_queue(rx_queue, channel) - next_buffer_table = max(next_buffer_table, - rx_queue->rxd.index + - rx_queue->rxd.entries); - efx_for_each_channel_tx_queue(tx_queue, channel) - next_buffer_table = max(next_buffer_table, - tx_queue->txd.index + - tx_queue->txd.entries); - } - efx_device_detach_sync(efx); efx_stop_all(efx); efx_soft_disable_interrupts(efx); @@ -904,9 +879,6 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) for (i = 0; i < efx->n_channels; i++) swap(efx->channel[i], other_channel[i]); - /* Restart buffer table allocation */ - efx->next_buffer_table = next_buffer_table; - for (i = 0; i < efx->n_channels; i++) { channel = efx->channel[i]; if (!channel->type->copy) diff --git a/drivers/net/ethernet/sfc/mcdi_functions.c b/drivers/net/ethernet/sfc/mcdi_functions.c index d3e6d8239f5c..ff8424167384 100644 --- a/drivers/net/ethernet/sfc/mcdi_functions.c +++ b/drivers/net/ethernet/sfc/mcdi_functions.c @@ -62,7 +62,7 @@ int efx_mcdi_alloc_vis(struct efx_nic *efx, unsigned int min_vis, int efx_mcdi_ev_probe(struct efx_channel *channel) { - return efx_nic_alloc_buffer(channel->efx, &channel->eventq.buf, + return efx_nic_alloc_buffer(channel->efx, &channel->eventq, (channel->eventq_mask + 1) * sizeof(efx_qword_t), GFP_KERNEL); @@ -74,14 +74,14 @@ int efx_mcdi_ev_init(struct efx_channel *channel, bool v1_cut_thru, bool v2) MC_CMD_INIT_EVQ_V2_IN_LEN(EFX_MAX_EVQ_SIZE * 8 / EFX_BUF_SIZE)); MCDI_DECLARE_BUF(outbuf, MC_CMD_INIT_EVQ_V2_OUT_LEN); - size_t entries = channel->eventq.buf.len / EFX_BUF_SIZE; + size_t entries = channel->eventq.len / EFX_BUF_SIZE; struct efx_nic *efx = channel->efx; size_t inlen, outlen; dma_addr_t dma_addr; int rc, i; /* Fill event queue with all ones (i.e. empty events) */ - memset(channel->eventq.buf.addr, 0xff, channel->eventq.buf.len); + memset(channel->eventq.addr, 0xff, channel->eventq.len); MCDI_SET_DWORD(inbuf, INIT_EVQ_IN_SIZE, channel->eventq_mask + 1); MCDI_SET_DWORD(inbuf, INIT_EVQ_IN_INSTANCE, channel->channel); @@ -112,7 +112,7 @@ int efx_mcdi_ev_init(struct efx_channel *channel, bool v1_cut_thru, bool v2) INIT_EVQ_IN_FLAG_CUT_THRU, v1_cut_thru); } - dma_addr = channel->eventq.buf.dma_addr; + dma_addr = channel->eventq.dma_addr; for (i = 0; i < entries; ++i) { MCDI_SET_ARRAY_QWORD(inbuf, INIT_EVQ_IN_DMA_ADDR, i, dma_addr); dma_addr += EFX_BUF_SIZE; @@ -134,7 +134,7 @@ int efx_mcdi_ev_init(struct efx_channel *channel, bool v1_cut_thru, bool v2) void efx_mcdi_ev_remove(struct efx_channel *channel) { - efx_nic_free_buffer(channel->efx, &channel->eventq.buf); + efx_nic_free_buffer(channel->efx, &channel->eventq); } void efx_mcdi_ev_fini(struct efx_channel *channel) @@ -166,7 +166,7 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue) EFX_BUF_SIZE)); bool csum_offload = tx_queue->type & EFX_TXQ_TYPE_OUTER_CSUM; bool inner_csum = tx_queue->type & EFX_TXQ_TYPE_INNER_CSUM; - size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE; + size_t entries = tx_queue->txd.len / EFX_BUF_SIZE; struct efx_channel *channel = tx_queue->channel; struct efx_nic *efx = tx_queue->efx; dma_addr_t dma_addr; @@ -182,7 +182,7 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue) MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_OWNER_ID, 0); MCDI_SET_DWORD(inbuf, INIT_TXQ_IN_PORT_ID, efx->vport_id); - dma_addr = tx_queue->txd.buf.dma_addr; + dma_addr = tx_queue->txd.dma_addr; netif_dbg(efx, hw, efx->net_dev, "pushing TXQ %d. %zu entries (%llx)\n", tx_queue->queue, entries, (u64)dma_addr); @@ -240,7 +240,7 @@ fail: void efx_mcdi_tx_remove(struct efx_tx_queue *tx_queue) { - efx_nic_free_buffer(tx_queue->efx, &tx_queue->txd.buf); + efx_nic_free_buffer(tx_queue->efx, &tx_queue->txd); } void efx_mcdi_tx_fini(struct efx_tx_queue *tx_queue) @@ -269,7 +269,7 @@ fail: int efx_mcdi_rx_probe(struct efx_rx_queue *rx_queue) { - return efx_nic_alloc_buffer(rx_queue->efx, &rx_queue->rxd.buf, + return efx_nic_alloc_buffer(rx_queue->efx, &rx_queue->rxd, (rx_queue->ptr_mask + 1) * sizeof(efx_qword_t), GFP_KERNEL); @@ -278,7 +278,7 @@ int efx_mcdi_rx_probe(struct efx_rx_queue *rx_queue) void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue) { struct efx_channel *channel = efx_rx_queue_channel(rx_queue); - size_t entries = rx_queue->rxd.buf.len / EFX_BUF_SIZE; + size_t entries = rx_queue->rxd.len / EFX_BUF_SIZE; MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_RXQ_V4_IN_LEN); struct efx_nic *efx = rx_queue->efx; unsigned int buffer_size; @@ -306,7 +306,7 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue) MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, efx->vport_id); MCDI_SET_DWORD(inbuf, INIT_RXQ_V4_IN_BUFFER_SIZE_BYTES, buffer_size); - dma_addr = rx_queue->rxd.buf.dma_addr; + dma_addr = rx_queue->rxd.dma_addr; netif_dbg(efx, hw, efx->net_dev, "pushing RXQ %d. %zu entries (%llx)\n", efx_rx_queue_index(rx_queue), entries, (u64)dma_addr); @@ -325,7 +325,7 @@ void efx_mcdi_rx_init(struct efx_rx_queue *rx_queue) void efx_mcdi_rx_remove(struct efx_rx_queue *rx_queue) { - efx_nic_free_buffer(rx_queue->efx, &rx_queue->rxd.buf); + efx_nic_free_buffer(rx_queue->efx, &rx_queue->rxd); } void efx_mcdi_rx_fini(struct efx_rx_queue *rx_queue) diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 6654fbb8f4c0..27d86e90a3bb 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -122,26 +122,6 @@ struct efx_buffer { unsigned int len; }; -/** - * struct efx_special_buffer - DMA buffer entered into buffer table - * @buf: Standard &struct efx_buffer - * @index: Buffer index within controller;s buffer table - * @entries: Number of buffer table entries - * - * The NIC has a buffer table that maps buffers of size %EFX_BUF_SIZE. - * Event and descriptor rings are addressed via one or more buffer - * table entries (and so can be physically non-contiguous, although we - * currently do not take advantage of that). On Falcon and Siena we - * have to take care of allocating and initialising the entries - * ourselves. On later hardware this is managed by the firmware and - * @index and @entries are left as 0. - */ -struct efx_special_buffer { - struct efx_buffer buf; - unsigned int index; - unsigned int entries; -}; - /** * struct efx_tx_buffer - buffer state for a TX descriptor * @skb: When @flags & %EFX_TX_BUF_SKB, the associated socket buffer to be @@ -268,7 +248,7 @@ struct efx_tx_queue { struct netdev_queue *core_txq; struct efx_tx_buffer *buffer; struct efx_buffer *cb_page; - struct efx_special_buffer txd; + struct efx_buffer txd; unsigned int ptr_mask; void __iomem *piobuf; unsigned int piobuf_offset; @@ -397,7 +377,7 @@ struct efx_rx_queue { struct efx_nic *efx; int core_index; struct efx_rx_buffer *buffer; - struct efx_special_buffer rxd; + struct efx_buffer rxd; unsigned int ptr_mask; bool refill_enabled; bool flush_pending; @@ -513,7 +493,7 @@ struct efx_channel { #ifdef CONFIG_NET_RX_BUSY_POLL unsigned long busy_poll_state; #endif - struct efx_special_buffer eventq; + struct efx_buffer eventq; unsigned int eventq_mask; unsigned int eventq_read_ptr; int event_test_cpu; @@ -881,7 +861,6 @@ struct efx_mae; * @tx_dc_base: Base qword address in SRAM of TX queue descriptor caches * @rx_dc_base: Base qword address in SRAM of RX queue descriptor caches * @sram_lim_qw: Qword address limit of SRAM - * @next_buffer_table: First available buffer table id * @n_channels: Number of channels in use * @n_rx_channels: Number of channels used for RX (= number of RX queues) * @n_tx_channels: Number of channels used for TX @@ -1046,7 +1025,6 @@ struct efx_nic { unsigned tx_dc_base; unsigned rx_dc_base; unsigned sram_lim_qw; - unsigned next_buffer_table; unsigned int max_channels; unsigned int max_vis; diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h index e35ecbe8842e..47b1c46c069d 100644 --- a/drivers/net/ethernet/sfc/nic_common.h +++ b/drivers/net/ethernet/sfc/nic_common.h @@ -32,7 +32,7 @@ static inline int efx_nic_rev(struct efx_nic *efx) static inline efx_qword_t *efx_event(struct efx_channel *channel, unsigned int index) { - return ((efx_qword_t *) (channel->eventq.buf.addr)) + + return ((efx_qword_t *)(channel->eventq.addr)) + (index & channel->eventq_mask); } @@ -58,7 +58,7 @@ static inline int efx_event_present(efx_qword_t *event) static inline efx_qword_t * efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index) { - return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index; + return ((efx_qword_t *)(tx_queue->txd.addr)) + index; } /* Report whether this TX queue would be empty for the given write_count. @@ -98,7 +98,7 @@ static inline bool efx_nic_may_push_tx_desc(struct efx_tx_queue *tx_queue, static inline efx_qword_t * efx_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index) { - return ((efx_qword_t *) (rx_queue->rxd.buf.addr)) + index; + return ((efx_qword_t *)(rx_queue->rxd.addr)) + index; } /* Alignment of PCIe DMA boundaries (4KB) */ diff --git a/drivers/net/ethernet/sfc/tx_tso.c b/drivers/net/ethernet/sfc/tx_tso.c index d381d8164f07..64a6768f75ea 100644 --- a/drivers/net/ethernet/sfc/tx_tso.c +++ b/drivers/net/ethernet/sfc/tx_tso.c @@ -85,7 +85,7 @@ static inline void prefetch_ptr(struct efx_tx_queue *tx_queue) prefetch(ptr); prefetch(ptr + 0x80); - ptr = (char *) (((efx_qword_t *)tx_queue->txd.buf.addr) + insert_ptr); + ptr = (char *)(((efx_qword_t *)tx_queue->txd.addr) + insert_ptr); prefetch(ptr); prefetch(ptr + 0x80); } -- cgit From ae9d445cd41fc71205f97c4f7710bb90c570cf5e Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:26 +0100 Subject: sfc: Miscellaneous comment removals Remove comments that only apply to Falcon and Siena. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx_common.c | 5 ----- drivers/net/ethernet/sfc/filter.h | 7 ------- drivers/net/ethernet/sfc/nic_common.h | 4 +--- drivers/net/ethernet/sfc/selftest.c | 7 +------ 4 files changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index c8d8f1e9a21a..175bd9cdfdac 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -35,11 +35,6 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value"); /* This is the time (in jiffies) between invocations of the hardware * monitor. - * On Falcon-based NICs, this will: - * - Check the on-board hardware monitor; - * - Poll the link state and reconfigure the hardware as necessary. - * On Siena-based NICs for power systems with EEH support, this will give EEH a - * chance to start. */ static unsigned int efx_monitor_interval = 1 * HZ; diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h index 5f201a547e5b..0d45900afa76 100644 --- a/drivers/net/ethernet/sfc/filter.h +++ b/drivers/net/ethernet/sfc/filter.h @@ -30,13 +30,6 @@ * * Only some combinations are supported, depending on NIC type: * - * - Falcon supports RX filters matching by {TCP,UDP}/IPv4 4-tuple or - * local 2-tuple (only implemented for Falcon B0) - * - * - Siena supports RX and TX filters matching by {TCP,UDP}/IPv4 4-tuple - * or local 2-tuple, or local MAC with or without outer VID, and RX - * default filters - * * - Huntington supports filter matching controlled by firmware, potentially * using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit, * with or without outer and inner VID diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h index 47b1c46c069d..466df5348b29 100644 --- a/drivers/net/ethernet/sfc/nic_common.h +++ b/drivers/net/ethernet/sfc/nic_common.h @@ -79,9 +79,7 @@ int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb, /* Decide whether to push a TX descriptor to the NIC vs merely writing * the doorbell. This can reduce latency when we are adding a single - * descriptor to an empty queue, but is otherwise pointless. Further, - * Falcon and Siena have hardware bugs (SF bug 33851) that may be - * triggered if we don't check this. + * descriptor to an empty queue, but is otherwise pointless. * We use the write_count used for the last doorbell push, to get the * NIC's view of the tx queue. */ diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 96d856b9043c..40d9bf642408 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -38,8 +38,7 @@ /* * Loopback test packet structure * - * The self-test should stress every RSS vector, and unfortunately - * Falcon only performs RSS on TCP/UDP packets. + * The self-test should stress every RSS vector. */ struct efx_loopback_payload { char pad[2]; /* Ensures ip is 4-byte aligned */ @@ -581,10 +580,6 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, return 0; } -/* Wait for link up. On Falcon, we would prefer to rely on efx_monitor, but - * any contention on the mac lock (via e.g. efx_mac_mcast_work) causes it - * to delay and retry. Therefore, it's safer to just poll directly. Wait - * for link up and any faults to dissipate. */ static int efx_wait_for_link(struct efx_nic *efx) { struct efx_link_state *link_state = &efx->link_state; -- cgit From b0d1fe9bcdc66406dcc650ec0b750bd3c2ce2005 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:32 +0100 Subject: sfc: Cleanups in io.h Most of the Falcon locking description does not apply to EF10. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/io.h | 84 +++++------------------------------------- drivers/net/ethernet/sfc/nic.c | 5 --- 2 files changed, 9 insertions(+), 80 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h index 30439cc83a89..7432c09010d6 100644 --- a/drivers/net/ethernet/sfc/io.h +++ b/drivers/net/ethernet/sfc/io.h @@ -17,46 +17,22 @@ * ************************************************************************** * - * Notes on locking strategy for the Falcon architecture: - * - * Many CSRs are very wide and cannot be read or written atomically. - * Writes from the host are buffered by the Bus Interface Unit (BIU) - * up to 128 bits. Whenever the host writes part of such a register, - * the BIU collects the written value and does not write to the - * underlying register until all 4 dwords have been written. A - * similar buffering scheme applies to host access to the NIC's 64-bit - * SRAM. - * - * Writes to different CSRs and 64-bit SRAM words must be serialised, - * since interleaved access can result in lost writes. We use - * efx_nic::biu_lock for this. - * - * We also serialise reads from 128-bit CSRs and SRAM with the same - * spinlock. This may not be necessary, but it doesn't really matter - * as there are no such reads on the fast path. + * The EF10 architecture exposes very few registers to the host and + * most of them are only 32 bits wide. The only exceptions are the MC + * doorbell register pair, which has its own latching, and + * TX_DESC_UPD. * - * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are - * 128-bit but are special-cased in the BIU to avoid the need for - * locking in the host: + * The TX_DESC_UPD DMA descriptor pointer is 128-bits but is a special + * case in the BIU to avoid the need for locking in the host: * - * - They are write-only. - * - The semantics of writing to these registers are such that + * - It is write-only. + * - The semantics of writing to this register is such that * replacing the low 96 bits with zero does not affect functionality. - * - If the host writes to the last dword address of such a register + * - If the host writes to the last dword address of the register * (i.e. the high 32 bits) the underlying register will always be * written. If the collector and the current write together do not * provide values for all 128 bits of the register, the low 96 bits * will be written as zero. - * - If the host writes to the address of any other part of such a - * register while the collector already holds values for some other - * register, the write is discarded and the collector maintains its - * current state. - * - * The EF10 architecture exposes very few registers to the host and - * most of them are only 32 bits wide. The only exceptions are the MC - * doorbell register pair, which has its own latching, and - * TX_DESC_UPD, which works in a similar way to the Falcon - * architecture. */ #if BITS_PER_LONG == 64 @@ -125,27 +101,6 @@ static inline void efx_writeo(struct efx_nic *efx, const efx_oword_t *value, spin_unlock_irqrestore(&efx->biu_lock, flags); } -/* Write 64-bit SRAM through the supplied mapping, locking as appropriate. */ -static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase, - const efx_qword_t *value, unsigned int index) -{ - unsigned int addr = index * sizeof(*value); - unsigned long flags __attribute__ ((unused)); - - netif_vdbg(efx, hw, efx->net_dev, - "writing SRAM address %x with " EFX_QWORD_FMT "\n", - addr, EFX_QWORD_VAL(*value)); - - spin_lock_irqsave(&efx->biu_lock, flags); -#ifdef EFX_USE_QWORD_IO - __raw_writeq((__force u64)value->u64[0], membase + addr); -#else - __raw_writel((__force u32)value->u32[0], membase + addr); - __raw_writel((__force u32)value->u32[1], membase + addr + 4); -#endif - spin_unlock_irqrestore(&efx->biu_lock, flags); -} - /* Write a 32-bit CSR or the last dword of a special 128-bit CSR */ static inline void efx_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned int reg) @@ -176,27 +131,6 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value, EFX_OWORD_VAL(*value)); } -/* Read 64-bit SRAM through the supplied mapping, locking as appropriate. */ -static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase, - efx_qword_t *value, unsigned int index) -{ - unsigned int addr = index * sizeof(*value); - unsigned long flags __attribute__ ((unused)); - - spin_lock_irqsave(&efx->biu_lock, flags); -#ifdef EFX_USE_QWORD_IO - value->u64[0] = (__force __le64)__raw_readq(membase + addr); -#else - value->u32[0] = (__force __le32)__raw_readl(membase + addr); - value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4); -#endif - spin_unlock_irqrestore(&efx->biu_lock, flags); - - netif_vdbg(efx, hw, efx->net_dev, - "read from SRAM address %x, got "EFX_QWORD_FMT"\n", - addr, EFX_QWORD_VAL(*value)); -} - /* Read a 32-bit CSR or SRAM */ static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value, unsigned int reg) diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 7e057741425f..a33ed473cc8a 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -272,11 +272,6 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf) case 4: /* 32-bit SRAM */ efx_readd(efx, buf, table->offset + 4 * i); break; - case 8: /* 64-bit SRAM */ - efx_sram_readq(efx, - efx->membase + table->offset, - buf, i); - break; case 16: /* 128-bit-readable register */ efx_reado_table(efx, buf, table->offset, i); break; -- cgit From 3771c878b460c11acab5fc72f393a1b27612ac49 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Thu, 27 Jul 2023 11:41:37 +0100 Subject: sfc: Remove vfdi.h It was only used for Siena SRIOV, so nothing includes it any more in this directory. Signed-off-by: Martin Habets Acked-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/vfdi.h | 252 ---------------------------------------- 1 file changed, 252 deletions(-) delete mode 100644 drivers/net/ethernet/sfc/vfdi.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/vfdi.h b/drivers/net/ethernet/sfc/vfdi.h deleted file mode 100644 index 480b872eb4d1..000000000000 --- a/drivers/net/ethernet/sfc/vfdi.h +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/**************************************************************************** - * Driver for Solarflare network controllers and boards - * Copyright 2010-2012 Solarflare Communications Inc. - */ -#ifndef _VFDI_H -#define _VFDI_H - -/** - * DOC: Virtual Function Driver Interface - * - * This file contains software structures used to form a two way - * communication channel between the VF driver and the PF driver, - * named Virtual Function Driver Interface (VFDI). - * - * For the purposes of VFDI, a page is a memory region with size and - * alignment of 4K. All addresses are DMA addresses to be used within - * the domain of the relevant VF. - * - * The only hardware-defined channels for a VF driver to communicate - * with the PF driver are the event mailboxes (%FR_CZ_USR_EV - * registers). Writing to these registers generates an event with - * EV_CODE = EV_CODE_USR_EV, USER_QID set to the index of the mailbox - * and USER_EV_REG_VALUE set to the value written. The PF driver may - * direct or disable delivery of these events by setting - * %FR_CZ_USR_EV_CFG. - * - * The PF driver can send arbitrary events to arbitrary event queues. - * However, for consistency, VFDI events from the PF are defined to - * follow the same form and be sent to the first event queue assigned - * to the VF while that queue is enabled by the VF driver. - * - * The general form of the variable bits of VFDI events is: - * - * 0 16 24 31 - * | DATA | TYPE | SEQ | - * - * SEQ is a sequence number which should be incremented by 1 (modulo - * 256) for each event. The sequence numbers used in each direction - * are independent. - * - * The VF submits requests of type &struct vfdi_req by sending the - * address of the request (ADDR) in a series of 4 events: - * - * 0 16 24 31 - * | ADDR[0:15] | VFDI_EV_TYPE_REQ_WORD0 | SEQ | - * | ADDR[16:31] | VFDI_EV_TYPE_REQ_WORD1 | SEQ+1 | - * | ADDR[32:47] | VFDI_EV_TYPE_REQ_WORD2 | SEQ+2 | - * | ADDR[48:63] | VFDI_EV_TYPE_REQ_WORD3 | SEQ+3 | - * - * The address must be page-aligned. After receiving such a valid - * series of events, the PF driver will attempt to read the request - * and write a response to the same address. In case of an invalid - * sequence of events or a DMA error, there will be no response. - * - * The VF driver may request that the PF driver writes status - * information into its domain asynchronously. After writing the - * status, the PF driver will send an event of the form: - * - * 0 16 24 31 - * | reserved | VFDI_EV_TYPE_STATUS | SEQ | - * - * In case the VF must be reset for any reason, the PF driver will - * send an event of the form: - * - * 0 16 24 31 - * | reserved | VFDI_EV_TYPE_RESET | SEQ | - * - * It is then the responsibility of the VF driver to request - * reinitialisation of its queues. - */ -#define VFDI_EV_SEQ_LBN 24 -#define VFDI_EV_SEQ_WIDTH 8 -#define VFDI_EV_TYPE_LBN 16 -#define VFDI_EV_TYPE_WIDTH 8 -#define VFDI_EV_TYPE_REQ_WORD0 0 -#define VFDI_EV_TYPE_REQ_WORD1 1 -#define VFDI_EV_TYPE_REQ_WORD2 2 -#define VFDI_EV_TYPE_REQ_WORD3 3 -#define VFDI_EV_TYPE_STATUS 4 -#define VFDI_EV_TYPE_RESET 5 -#define VFDI_EV_DATA_LBN 0 -#define VFDI_EV_DATA_WIDTH 16 - -struct vfdi_endpoint { - u8 mac_addr[ETH_ALEN]; - __be16 tci; -}; - -/** - * enum vfdi_op - VFDI operation enumeration - * @VFDI_OP_RESPONSE: Indicates a response to the request. - * @VFDI_OP_INIT_EVQ: Initialize SRAM entries and initialize an EVQ. - * @VFDI_OP_INIT_RXQ: Initialize SRAM entries and initialize an RXQ. - * @VFDI_OP_INIT_TXQ: Initialize SRAM entries and initialize a TXQ. - * @VFDI_OP_FINI_ALL_QUEUES: Flush all queues, finalize all queues, then - * finalize the SRAM entries. - * @VFDI_OP_INSERT_FILTER: Insert a MAC filter targeting the given RXQ. - * @VFDI_OP_REMOVE_ALL_FILTERS: Remove all filters. - * @VFDI_OP_SET_STATUS_PAGE: Set the DMA page(s) used for status updates - * from PF and write the initial status. - * @VFDI_OP_CLEAR_STATUS_PAGE: Clear the DMA page(s) used for status - * updates from PF. - */ -enum vfdi_op { - VFDI_OP_RESPONSE = 0, - VFDI_OP_INIT_EVQ = 1, - VFDI_OP_INIT_RXQ = 2, - VFDI_OP_INIT_TXQ = 3, - VFDI_OP_FINI_ALL_QUEUES = 4, - VFDI_OP_INSERT_FILTER = 5, - VFDI_OP_REMOVE_ALL_FILTERS = 6, - VFDI_OP_SET_STATUS_PAGE = 7, - VFDI_OP_CLEAR_STATUS_PAGE = 8, - VFDI_OP_LIMIT, -}; - -/* Response codes for VFDI operations. Other values may be used in future. */ -#define VFDI_RC_SUCCESS 0 -#define VFDI_RC_ENOMEM (-12) -#define VFDI_RC_EINVAL (-22) -#define VFDI_RC_EOPNOTSUPP (-95) -#define VFDI_RC_ETIMEDOUT (-110) - -/** - * struct vfdi_req - Request from VF driver to PF driver - * @op: Operation code or response indicator, taken from &enum vfdi_op. - * @rc: Response code. Set to 0 on success or a negative error code on failure. - * @u.init_evq.index: Index of event queue to create. - * @u.init_evq.buf_count: Number of 4k buffers backing event queue. - * @u.init_evq.addr: Array of length %u.init_evq.buf_count containing DMA - * address of each page backing the event queue. - * @u.init_rxq.index: Index of receive queue to create. - * @u.init_rxq.buf_count: Number of 4k buffers backing receive queue. - * @u.init_rxq.evq: Instance of event queue to target receive events at. - * @u.init_rxq.label: Label used in receive events. - * @u.init_rxq.flags: Unused. - * @u.init_rxq.addr: Array of length %u.init_rxq.buf_count containing DMA - * address of each page backing the receive queue. - * @u.init_txq.index: Index of transmit queue to create. - * @u.init_txq.buf_count: Number of 4k buffers backing transmit queue. - * @u.init_txq.evq: Instance of event queue to target transmit completion - * events at. - * @u.init_txq.label: Label used in transmit completion events. - * @u.init_txq.flags: Checksum offload flags. - * @u.init_txq.addr: Array of length %u.init_txq.buf_count containing DMA - * address of each page backing the transmit queue. - * @u.mac_filter.rxq: Insert MAC filter at VF local address/VLAN targeting - * all traffic at this receive queue. - * @u.mac_filter.flags: MAC filter flags. - * @u.set_status_page.dma_addr: Base address for the &struct vfdi_status. - * This address must be page-aligned and the PF may write up to a - * whole page (allowing for extension of the structure). - * @u.set_status_page.peer_page_count: Number of additional pages the VF - * has provided into which peer addresses may be DMAd. - * @u.set_status_page.peer_page_addr: Array of DMA addresses of pages. - * If the number of peers exceeds 256, then the VF must provide - * additional pages in this array. The PF will then DMA up to - * 512 vfdi_endpoint structures into each page. These addresses - * must be page-aligned. - */ -struct vfdi_req { - u32 op; - u32 reserved1; - s32 rc; - u32 reserved2; - union { - struct { - u32 index; - u32 buf_count; - u64 addr[]; - } init_evq; - struct { - u32 index; - u32 buf_count; - u32 evq; - u32 label; - u32 flags; -#define VFDI_RXQ_FLAG_SCATTER_EN 1 - u32 reserved; - u64 addr[]; - } init_rxq; - struct { - u32 index; - u32 buf_count; - u32 evq; - u32 label; - u32 flags; -#define VFDI_TXQ_FLAG_IP_CSUM_DIS 1 -#define VFDI_TXQ_FLAG_TCPUDP_CSUM_DIS 2 - u32 reserved; - u64 addr[]; - } init_txq; - struct { - u32 rxq; - u32 flags; -#define VFDI_MAC_FILTER_FLAG_RSS 1 -#define VFDI_MAC_FILTER_FLAG_SCATTER 2 - } mac_filter; - struct { - u64 dma_addr; - u64 peer_page_count; - u64 peer_page_addr[]; - } set_status_page; - } u; -}; - -/** - * struct vfdi_status - Status provided by PF driver to VF driver - * @generation_start: A generation count DMA'd to VF *before* the - * rest of the structure. - * @generation_end: A generation count DMA'd to VF *after* the - * rest of the structure. - * @version: Version of this structure; currently set to 1. Later - * versions must either be layout-compatible or only be sent to VFs - * that specifically request them. - * @length: Total length of this structure including embedded tables - * @vi_scale: log2 the number of VIs available on this VF. This quantity - * is used by the hardware for register decoding. - * @max_tx_channels: The maximum number of transmit queues the VF can use. - * @rss_rxq_count: The number of receive queues present in the shared RSS - * indirection table. - * @peer_count: Total number of peers in the complete peer list. If larger - * than ARRAY_SIZE(%peers), then the VF must provide sufficient - * additional pages each of which is filled with vfdi_endpoint structures. - * @local: The MAC address and outer VLAN tag of *this* VF - * @peers: Table of peer addresses. The @tci fields in these structures - * are currently unused and must be ignored. Additional peers are - * written into any additional pages provided by the VF. - * @timer_quantum_ns: Timer quantum (nominal period between timer ticks) - * for interrupt moderation timers, in nanoseconds. This member is only - * present if @length is sufficiently large. - */ -struct vfdi_status { - u32 generation_start; - u32 generation_end; - u32 version; - u32 length; - u8 vi_scale; - u8 max_tx_channels; - u8 rss_rxq_count; - u8 reserved1; - u16 peer_count; - u16 reserved2; - struct vfdi_endpoint local; - struct vfdi_endpoint peers[256]; - - /* Members below here extend version 1 of this structure */ - u32 timer_quantum_ns; -}; - -#endif -- cgit From 569f98b36b38387133862a0fce37896f05c042d6 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:19 +0200 Subject: mlxsw: spectrum: Drop unused functions mlxsw_sp_port_lower_dev_hold/_put() As of commit 151b89f6025a ("mlxsw: spectrum_router: Reuse work neighbor initialization in work scheduler"), the functions mlxsw_sp_port_lower_dev_hold() and mlxsw_sp_port_dev_put() have no users. Drop them. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/d0adcd7cb4ea19416294a0f861100edba84c9f36.1690471774.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 17 ----------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 -- 2 files changed, 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index f0f6af3ec7c5..9dbd5edff0b0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4112,23 +4112,6 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev) return (struct mlxsw_sp_port *)priv.data; } -struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev) -{ - struct mlxsw_sp_port *mlxsw_sp_port; - - rcu_read_lock(); - mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev); - if (mlxsw_sp_port) - dev_hold(mlxsw_sp_port->dev); - rcu_read_unlock(); - return mlxsw_sp_port; -} - -void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port) -{ - dev_put(mlxsw_sp_port->dev); -} - int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp) { char mprs_pl[MLXSW_REG_MPRS_LEN]; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 65eaa181e0aa..62151f0531ae 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -720,8 +720,6 @@ int mlxsw_sp_txhdr_ptp_data_construct(struct mlxsw_core *mlxsw_core, bool mlxsw_sp_port_dev_check(const struct net_device *dev); struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev); struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev); -struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev); -void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port); struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev); int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp); -- cgit From 16f8c846cd6f8c5c45392e0f3dde843983adb9ab Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:20 +0200 Subject: mlxsw: spectrum_nve: Do not take reference when looking up netdevice mlxsw_sp_nve_fid_disable() is always called under RTNL. It is therefore safe to call __dev_get_by_index() to get the netdevice pointer without bumping the reference count, because we can be sure the netdevice is not going away. That then obviates the need to put the netdevice later in the function. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/341d1046f89d8d839d9d00e4a3d58cdc351e9397.1690471774.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index d2b57a045aa4..5479a1c19d2e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -989,6 +989,9 @@ void mlxsw_sp_nve_fid_disable(struct mlxsw_sp *mlxsw_sp, int nve_ifindex; __be32 vni; + /* Necessary for __dev_get_by_index() below. */ + ASSERT_RTNL(); + mlxsw_sp_nve_flood_ip_flush(mlxsw_sp, fid); mlxsw_sp_nve_fdb_flush_by_fid(mlxsw_sp, fid_index); mlxsw_sp_nve_ipv6_addr_flush_by_fid(mlxsw_sp, fid_index); @@ -997,15 +1000,13 @@ void mlxsw_sp_nve_fid_disable(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_fid_vni(fid, &vni))) goto out; - nve_dev = dev_get_by_index(mlxsw_sp_net(mlxsw_sp), nve_ifindex); + nve_dev = __dev_get_by_index(mlxsw_sp_net(mlxsw_sp), nve_ifindex); if (!nve_dev) goto out; mlxsw_sp_nve_fdb_clear_offload(mlxsw_sp, fid, nve_dev, vni); mlxsw_sp_fid_fdb_clear_offload(fid, nve_dev); - dev_put(nve_dev); - out: mlxsw_sp_fid_vni_clear(fid); mlxsw_sp_nve_tunnel_fini(mlxsw_sp); -- cgit From 1ae489ab43e0a74d96d41a607c1d924f8ba47186 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:21 +0200 Subject: mlxsw: spectrum_switchdev: Use tracker helpers to hold & put netdevices Using the tracking helpers makes it easier to debug netdevice refcount imbalances when CONFIG_NET_DEV_REFCNT_TRACKER is enabled. Convert dev_hold() / dev_put() to netdev_hold() / netdev_put() in the switchdev module. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/774c3d7b5b0231f1435df2ec9dd660192e382756.1690471774.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index dffb67c1038e..5376d4af5f91 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3380,6 +3380,7 @@ out: struct mlxsw_sp_switchdev_event_work { struct work_struct work; + netdevice_tracker dev_tracker; union { struct switchdev_notifier_fdb_info fdb_info; struct switchdev_notifier_vxlan_fdb_info vxlan_fdb_info; @@ -3536,8 +3537,8 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work) out: rtnl_unlock(); kfree(switchdev_work->fdb_info.addr); + netdev_put(dev, &switchdev_work->dev_tracker); kfree(switchdev_work); - dev_put(dev); } static void @@ -3692,8 +3693,8 @@ static void mlxsw_sp_switchdev_vxlan_fdb_event_work(struct work_struct *work) out: rtnl_unlock(); + netdev_put(dev, &switchdev_work->dev_tracker); kfree(switchdev_work); - dev_put(dev); } static int @@ -3793,7 +3794,7 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused, * upper device containig mlxsw_sp_port or just a * mlxsw_sp_port */ - dev_hold(dev); + netdev_hold(dev, &switchdev_work->dev_tracker, GFP_ATOMIC); break; case SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE: case SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE: @@ -3803,7 +3804,7 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused, info); if (err) goto err_vxlan_work_prepare; - dev_hold(dev); + netdev_hold(dev, &switchdev_work->dev_tracker, GFP_ATOMIC); break; default: kfree(switchdev_work); -- cgit From deeaa3716f4fa2dd1722de8e1b203217e7dd677f Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:22 +0200 Subject: mlxsw: spectrum_router: FIB: Use tracker helpers to hold & put netdevices Using the tracking helpers makes it easier to debug netdevice refcount imbalances when CONFIG_NET_DEV_REFCNT_TRACKER is enabled. Convert dev_hold() / dev_put() to netdev_hold() / netdev_put() in the router code that deals with FIB events. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/5221a92e751c40447c55959f622267ccc999ed04.1690471774.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 57f0faac836c..0744497f2762 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7547,6 +7547,7 @@ struct mlxsw_sp_fib6_event_work { struct mlxsw_sp_fib_event_work { struct work_struct work; + netdevice_tracker dev_tracker; union { struct mlxsw_sp_fib6_event_work fib6_work; struct fib_entry_notifier_info fen_info; @@ -7720,12 +7721,12 @@ static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work) &fib_work->ven_info); if (err) dev_warn(mlxsw_sp->bus_info->dev, "MR VIF add failed.\n"); - dev_put(fib_work->ven_info.dev); + netdev_put(fib_work->ven_info.dev, &fib_work->dev_tracker); break; case FIB_EVENT_VIF_DEL: mlxsw_sp_router_fibmr_vif_del(mlxsw_sp, &fib_work->ven_info); - dev_put(fib_work->ven_info.dev); + netdev_put(fib_work->ven_info.dev, &fib_work->dev_tracker); break; } mutex_unlock(&mlxsw_sp->router->lock); @@ -7796,7 +7797,8 @@ mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work, case FIB_EVENT_VIF_ADD: case FIB_EVENT_VIF_DEL: memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info)); - dev_hold(fib_work->ven_info.dev); + netdev_hold(fib_work->ven_info.dev, &fib_work->dev_tracker, + GFP_ATOMIC); break; } } -- cgit From b17b2d57b7c1193a1b86c07b3ff0beca7a607a95 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:23 +0200 Subject: mlxsw: spectrum_router: hw_stats: Use tracker helpers to hold & put netdevices Using the tracking helpers makes it easier to debug netdevice refcount imbalances when CONFIG_NET_DEV_REFCNT_TRACKER is enabled. Convert dev_hold() / dev_put() to netdev_hold() / netdev_put() in the router code that deals with hw_stats events. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/b972314cfef4f4c24e66e60d13cffa5d606d1bf3.1690471774.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 0744497f2762..3ecd34ad0743 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8308,6 +8308,7 @@ mlxsw_sp_router_port_l3_stats_report_delta(struct mlxsw_sp_rif *rif, struct mlxsw_sp_router_hwstats_notify_work { struct work_struct work; struct net_device *dev; + netdevice_tracker dev_tracker; }; static void mlxsw_sp_router_hwstats_notify_work(struct work_struct *work) @@ -8319,7 +8320,7 @@ static void mlxsw_sp_router_hwstats_notify_work(struct work_struct *work) rtnl_lock(); rtnl_offload_xstats_notify(hws_work->dev); rtnl_unlock(); - dev_put(hws_work->dev); + netdev_put(hws_work->dev, &hws_work->dev_tracker); kfree(hws_work); } @@ -8339,7 +8340,7 @@ mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev) return; INIT_WORK(&hws_work->work, mlxsw_sp_router_hwstats_notify_work); - dev_hold(dev); + netdev_hold(dev, &hws_work->dev_tracker, GFP_KERNEL); hws_work->dev = dev; mlxsw_core_schedule_work(&hws_work->work); } -- cgit From d0e0e880122fb865884ef86372cd6221225c6459 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:24 +0200 Subject: mlxsw: spectrum_router: RIF: Use tracker helpers to hold & put netdevices Using the tracking helpers makes it easier to debug netdevice refcount imbalances when CONFIG_NET_DEV_REFCNT_TRACKER is enabled. Convert dev_hold() / dev_put() to netdev_hold() / netdev_put() in the router code that deals with RIF allocation. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/8b7701a7b439ac268e4be4040eff99d01e27ae47.1690471775.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 3ecd34ad0743..59d12cf45939 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -71,6 +71,7 @@ static const struct rhashtable_params mlxsw_sp_crif_ht_params = { struct mlxsw_sp_rif { struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */ + netdevice_tracker dev_tracker; struct list_head neigh_list; struct mlxsw_sp_fid *fid; unsigned char addr[ETH_ALEN]; @@ -8412,7 +8413,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, err = -ENOMEM; goto err_rif_alloc; } - dev_hold(params->dev); + netdev_hold(params->dev, &rif->dev_tracker, GFP_KERNEL); mlxsw_sp->router->rifs[rif_index] = rif; rif->mlxsw_sp = mlxsw_sp; rif->ops = ops; @@ -8469,7 +8470,7 @@ err_configure: mlxsw_sp_fid_put(fid); err_fid_get: mlxsw_sp->router->rifs[rif_index] = NULL; - dev_put(params->dev); + netdev_put(params->dev, &rif->dev_tracker); mlxsw_sp_rif_free(rif); err_rif_alloc: err_crif_lookup: @@ -8511,7 +8512,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) /* Loopback RIFs are not associated with a FID. */ mlxsw_sp_fid_put(fid); mlxsw_sp->router->rifs[rif->rif_index] = NULL; - dev_put(dev); + netdev_put(dev, &rif->dev_tracker); mlxsw_sp_rif_free(rif); mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); vr->rif_count--; -- cgit From cb2116204169b24fbb667c823e8fced069d5e561 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 27 Jul 2023 17:59:25 +0200 Subject: mlxsw: spectrum_router: IPv6 events: Use tracker helpers to hold & put netdevices Using the tracking helpers makes it easier to debug netdevice refcount imbalances when CONFIG_NET_DEV_REFCNT_TRACKER is enabled. Convert dev_hold() / dev_put() to netdev_hold() / netdev_put() in the router code that deals with IPv6 address events. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/f0af6ad4722b4ca6e598fd4fda8311a3041651ec.1690471775.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 59d12cf45939..debd2c466f11 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -9333,6 +9333,7 @@ struct mlxsw_sp_inet6addr_event_work { struct work_struct work; struct mlxsw_sp *mlxsw_sp; struct net_device *dev; + netdevice_tracker dev_tracker; unsigned long event; }; @@ -9356,7 +9357,7 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work) out: mutex_unlock(&mlxsw_sp->router->lock); rtnl_unlock(); - dev_put(dev); + netdev_put(dev, &inet6addr_work->dev_tracker); kfree(inet6addr_work); } @@ -9382,7 +9383,7 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb, inet6addr_work->mlxsw_sp = router->mlxsw_sp; inet6addr_work->dev = dev; inet6addr_work->event = event; - dev_hold(dev); + netdev_hold(dev, &inet6addr_work->dev_tracker, GFP_ATOMIC); mlxsw_core_schedule_work(&inet6addr_work->work); return NOTIFY_DONE; -- cgit From 833c4a8105ac8c2df42ec061be09a5a682454f69 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 27 Jul 2023 12:07:25 -0700 Subject: eth: bnxt: fix one of the W=1 warnings about fortified memcpy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a W=1 warning with gcc 13.1: In function ‘fortify_memcpy_chk’, inlined from ‘bnxt_hwrm_queue_cos2bw_cfg’ at drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c:133:3: include/linux/fortify-string.h:592:25: warning: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Wattribute-warning] 592 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The field group is already defined and starts at queue_id: struct bnxt_cos2bw_cfg { u8 pad[3]; struct_group_attr(cfg, __packed, u8 queue_id; __le32 min_bw; Reviewed-by: Michael Chan Link: https://lore.kernel.org/r/20230727190726.1859515-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index caab3d626a2a..31f85f3e2364 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -130,7 +130,7 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets, BW_VALUE_UNIT_PERCENT1_100); } data = &req->unused_0 + qidx * (sizeof(cos2bw) - 4); - memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4); + memcpy(data, &cos2bw.cfg, sizeof(cos2bw) - 4); if (qidx == 0) { req->queue_id0 = cos2bw.queue_id; req->unused_0 = 0; -- cgit From 9f49db62f58eceffd8345abe8ec110f1fb142ab6 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 27 Jul 2023 12:07:26 -0700 Subject: eth: bnxt: fix warning for define in struct_group Fix C=1 warning with sparse 0.6.4: drivers/net/ethernet/broadcom/bnxt/bnxt.c: note: in included file: drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h:30:1: warning: directive in macro's argument list Don't put defines in a struct_group(). Reviewed-by: Michael Chan Link: https://lore.kernel.org/r/20230727190726.1859515-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h index 716742522161..5b2a6f678244 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h @@ -27,11 +27,12 @@ struct bnxt_cos2bw_cfg { u8 queue_id; __le32 min_bw; __le32 max_bw; -#define BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) u8 tsa; u8 pri_lvl; u8 bw_weight; ); +/* for min_bw / max_bw */ +#define BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) u8 unused; }; -- cgit From 222a6c42e9ef131fd20463bf95d7ce7b39bee2f8 Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Thu, 27 Jul 2023 22:01:01 +0530 Subject: octeontx2-af: Initialize 'cntr_val' to fix uninitialized symbol error drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c:860 otx2_tc_update_mcam_table_del_req() error: uninitialized symbol 'cntr_val'. Fixes: ec87f05402f5 ("octeontx2-af: Install TC filter rules in hardware based on priority") Signed-off-by: Suman Ghosh Link: https://lore.kernel.org/r/20230727163101.2793453-1-sumang@marvell.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 1e6fc23eca4f..0915a0121316 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -841,7 +841,7 @@ static int otx2_tc_update_mcam_table_del_req(struct otx2_nic *nic, struct list_head *pos, *n; struct otx2_tc_flow *tmp; int i = 0, index = 0; - u16 cntr_val; + u16 cntr_val = 0; /* Find and delete the entry from the list and re-install * all the entries from beginning to the index of the @@ -880,7 +880,7 @@ static int otx2_tc_update_mcam_table_add_req(struct otx2_nic *nic, int mcam_idx = flow_cfg->max_flows - flow_cfg->nr_flows - 1; struct otx2_tc_flow *tmp; int list_idx, i; - u16 cntr_val; + u16 cntr_val = 0; /* Find the index of the entry(list_idx) whose priority * is greater than the new entry and re-install all -- cgit From 6a7eccef47b205ae66371a26d36dfb2529835075 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 27 Jul 2023 13:35:23 -0400 Subject: net/tls: Move TLS protocol elements to a separate header Kernel TLS consumers will need definitions of various parts of the TLS protocol, but often do not need the function declarations and other infrastructure provided in . Break out existing standardized protocol elements into a separate header, and make room for a few more elements in subsequent patches. Signed-off-by: Chuck Lever Link: https://lore.kernel.org/r/169047931374.5241.7713175865185969309.stgit@oracle-102.nfsv4bat.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h index 68562a82d036..62f62bff74a5 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "t4fw_api.h" -- cgit From 3bdd85e2e3508a5f10949cae66c1d9e21a82d16f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 26 Jul 2023 17:45:22 +0100 Subject: net: ethernet: slicoss: remove redundant increment of pointer data The pointer data is being incremented but this change to the pointer is not used afterwards. The increment is redundant and can be removed. Signed-off-by: Colin Ian King Acked-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20230726164522.369206-1-colin.i.king@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/alacritech/slicoss.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index a30d0f172986..78231c85234d 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -1520,10 +1520,8 @@ static void slic_get_ethtool_stats(struct net_device *dev, static void slic_get_strings(struct net_device *dev, u32 stringset, u8 *data) { - if (stringset == ETH_SS_STATS) { + if (stringset == ETH_SS_STATS) memcpy(data, slic_stats_strings, sizeof(slic_stats_strings)); - data += sizeof(slic_stats_strings); - } } static void slic_get_drvinfo(struct net_device *dev, -- cgit From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Wed, 26 Jul 2023 11:08:07 +0800 Subject: r8152: adjust generic_ocp_write function Reduce the control transfer if all bytes of first or the last DWORD are written. The original method is to split the control transfer into three parts (the first DWORD, middle continuous data, and the last DWORD). However, they could be combined if whole bytes of the first DWORD or last DWORD are written. That is, the first DWORD or the last DWORD could be combined with the middle continuous data, if the byte_en is 0xff. Signed-off-by: Hayes Wang Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/r8152.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 0738baa5b82e..f6578a99dbac 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1314,16 +1314,24 @@ static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen, byteen_end = byteen & BYTE_EN_END_MASK; byen = byteen_start | (byteen_start << 4); - ret = set_registers(tp, index, type | byen, 4, data); - if (ret < 0) - goto error1; - index += 4; - data += 4; - size -= 4; + /* Split the first DWORD if the byte_en is not 0xff */ + if (byen != BYTE_EN_DWORD) { + ret = set_registers(tp, index, type | byen, 4, data); + if (ret < 0) + goto error1; - if (size) { + index += 4; + data += 4; size -= 4; + } + + if (size) { + byen = byteen_end | (byteen_end >> 4); + + /* Split the last DWORD if the byte_en is not 0xff */ + if (byen != BYTE_EN_DWORD) + size -= 4; while (size) { if (size > limit) { @@ -1350,10 +1358,9 @@ static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen, } } - byen = byteen_end | (byteen_end >> 4); - ret = set_registers(tp, index, type | byen, 4, data); - if (ret < 0) - goto error1; + /* Set the last DWORD */ + if (byen != BYTE_EN_DWORD) + ret = set_registers(tp, index, type | byen, 4, data); } error1: -- cgit From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Wed, 26 Jul 2023 11:08:08 +0800 Subject: r8152: set bp in bulk PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we could combine the control transfers into one control transfer. Signed-off-by: Hayes Wang Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/r8152.c | 75 +++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index f6578a99dbac..db9897e825b4 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3978,29 +3978,10 @@ static void rtl_reset_bmu(struct r8152 *tp) /* Clear the bp to stop the firmware before loading a new one */ static void rtl_clear_bp(struct r8152 *tp, u16 type) { - switch (tp->version) { - case RTL_VER_01: - case RTL_VER_02: - case RTL_VER_07: - break; - case RTL_VER_03: - case RTL_VER_04: - case RTL_VER_05: - case RTL_VER_06: - ocp_write_byte(tp, type, PLA_BP_EN, 0); - break; - case RTL_VER_14: - ocp_write_word(tp, type, USB_BP2_EN, 0); + u16 bp[16] = {0}; + u16 bp_num; - ocp_write_word(tp, type, USB_BP_8, 0); - ocp_write_word(tp, type, USB_BP_9, 0); - ocp_write_word(tp, type, USB_BP_10, 0); - ocp_write_word(tp, type, USB_BP_11, 0); - ocp_write_word(tp, type, USB_BP_12, 0); - ocp_write_word(tp, type, USB_BP_13, 0); - ocp_write_word(tp, type, USB_BP_14, 0); - ocp_write_word(tp, type, USB_BP_15, 0); - break; + switch (tp->version) { case RTL_VER_08: case RTL_VER_09: case RTL_VER_10: @@ -4008,32 +3989,31 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) case RTL_VER_12: case RTL_VER_13: case RTL_VER_15: - default: if (type == MCU_TYPE_USB) { ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); - - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0); - } else { - ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); + bp_num = 16; + break; } + fallthrough; + case RTL_VER_03: + case RTL_VER_04: + case RTL_VER_05: + case RTL_VER_06: + ocp_write_byte(tp, type, PLA_BP_EN, 0); + fallthrough; + case RTL_VER_01: + case RTL_VER_02: + case RTL_VER_07: + bp_num = 8; + break; + case RTL_VER_14: + default: + ocp_write_word(tp, type, USB_BP2_EN, 0); + bp_num = 16; break; } - ocp_write_word(tp, type, PLA_BP_0, 0); - ocp_write_word(tp, type, PLA_BP_1, 0); - ocp_write_word(tp, type, PLA_BP_2, 0); - ocp_write_word(tp, type, PLA_BP_3, 0); - ocp_write_word(tp, type, PLA_BP_4, 0); - ocp_write_word(tp, type, PLA_BP_5, 0); - ocp_write_word(tp, type, PLA_BP_6, 0); - ocp_write_word(tp, type, PLA_BP_7, 0); + generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type); /* wait 3 ms to make sure the firmware is stopped */ usleep_range(3000, 6000); @@ -5007,10 +4987,9 @@ static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy) static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) { - u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg; + u16 bp_en_addr, type, fw_ver_reg; u32 length; u8 *data; - int i; switch (__le32_to_cpu(mac->blk_hdr.type)) { case RTL_FW_PLA: @@ -5052,12 +5031,8 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr), __le16_to_cpu(mac->bp_ba_value)); - bp_index = __le16_to_cpu(mac->bp_start); - bp_num = __le16_to_cpu(mac->bp_num); - for (i = 0; i < bp_num; i++) { - ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i])); - bp_index += 2; - } + generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD, + __le16_to_cpu(mac->bp_num) << 1, mac->bp, type); bp_en_addr = __le16_to_cpu(mac->bp_en_addr); if (bp_en_addr) -- cgit From c88c157d25d96ed760b91837aec81f19c44b0bf3 Mon Sep 17 00:00:00 2001 From: Chen Jiahao Date: Thu, 27 Jul 2023 19:55:51 +0800 Subject: net: bcmasp: Clean up redundant dev_err_probe() Referring to platform_get_irq()'s definition, the return value has already been checked, error message also been printed via dev_err_probe() if ret < 0. Calling dev_err_probe() one more time outside platform_get_irq() is obviously redundant. Removing dev_err_probe() outside platform_get_irq() to clean up above problem. Signed-off-by: Chen Jiahao Reviewed-by: Simon Horman Acked-by: Justin Chen Link: https://lore.kernel.org/r/20230727115551.2655840-1-chenjiahao16@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index a9984efff6d1..eb35ced1c8ba 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -1232,7 +1232,7 @@ static int bcmasp_probe(struct platform_device *pdev) priv->irq = platform_get_irq(pdev, 0); if (priv->irq <= 0) - return dev_err_probe(dev, -EINVAL, "invalid interrupt\n"); + return -EINVAL; priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp"); if (IS_ERR(priv->clk)) -- cgit From 58ea461b690cb093ef3f502e51adbb03d2ea61d8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 27 Jul 2023 09:02:26 +0200 Subject: net: ethernet: mtk_eth_soc: enable page_pool support for MT7988 SoC In order to recycle pages, enable page_pool allocator for MT7988 SoC. Tested-by: Daniel Golle Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/fd4e8693980e47385a543e7b002eec0b88bd09df.1690440675.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 38f39be04eae..bd1e4921c7b4 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1674,7 +1674,7 @@ static void mtk_update_rx_cpu_idx(struct mtk_eth *eth) static bool mtk_page_pool_enabled(struct mtk_eth *eth) { - return eth->soc->version == 2; + return mtk_is_netsys_v2_or_greater(eth); } static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, -- cgit From 88efedf517e69a4b12e4dd40c44c2e298f53fa83 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 27 Jul 2023 09:07:28 +0200 Subject: net: ethernet: mtk_eth_soc: enable nft hw flowtable_offload for MT7988 SoC Enable hw Packet Process Engine (PPE) for MT7988 SoC. Tested-by: Daniel Golle Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/5e86341b0220a49620dadc02d77970de5ded9efc.1690441576.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ drivers/net/ethernet/mediatek/mtk_ppe.c | 19 +++++++++++++++---- drivers/net/ethernet/mediatek/mtk_ppe.h | 19 ++++++++++++++++++- 3 files changed, 36 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index bd1e4921c7b4..05be702f19c5 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -5062,6 +5062,9 @@ static const struct mtk_soc_data mt7988_data = { .required_clks = MT7988_CLKS_BITMAP, .required_pctl = false, .version = 3, + .offload_version = 2, + .hash_offset = 4, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index 2f0e682449ef..bf1ecb0c1c10 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -423,13 +423,22 @@ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - if (mtk_is_netsys_v2_or_greater(eth)) { + switch (eth->soc->version) { + case 3: + *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; + *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | + MTK_FOE_IB2_WDMA_WINFO_V2; + l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | + FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); + break; + case 2: *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | MTK_FOE_IB2_WDMA_WINFO_V2; l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) | FIELD_PREP(MTK_FOE_WINFO_BSS, bss); - } else { + break; + default: *ib2 &= ~MTK_FOE_IB2_PORT_MG; *ib2 |= MTK_FOE_IB2_WDMA_WINFO; if (wdma_idx) @@ -437,6 +446,7 @@ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); + break; } return 0; @@ -964,8 +974,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) mtk_ppe_init_foe_table(ppe); ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); - val = MTK_PPE_TB_CFG_ENTRY_80B | - MTK_PPE_TB_CFG_AGE_NON_L4 | + val = MTK_PPE_TB_CFG_AGE_NON_L4 | MTK_PPE_TB_CFG_AGE_UNBIND | MTK_PPE_TB_CFG_AGE_TCP | MTK_PPE_TB_CFG_AGE_UDP | @@ -981,6 +990,8 @@ void mtk_ppe_start(struct mtk_ppe *ppe) MTK_PPE_ENTRIES_SHIFT); if (mtk_is_netsys_v2_or_greater(ppe->eth)) val |= MTK_PPE_TB_CFG_INFO_SEL; + if (!mtk_is_netsys_v3_or_greater(ppe->eth)) + val |= MTK_PPE_TB_CFG_ENTRY_80B; ppe_w32(ppe, MTK_PPE_TB_CFG, val); ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h index fb6bf58172d9..e3d0ec72bc69 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h @@ -85,6 +85,17 @@ enum { #define MTK_FOE_WINFO_BSS GENMASK(5, 0) #define MTK_FOE_WINFO_WCID GENMASK(15, 6) +#define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) +#define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) + +#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) +#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) +#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) +#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) +#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) +#define MTK_FOE_WINFO_PAO_HF BIT(23) +#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) + enum { MTK_FOE_STATE_INVALID, MTK_FOE_STATE_UNBIND, @@ -106,8 +117,13 @@ struct mtk_foe_mac_info { u16 pppoe_id; u16 src_mac_lo; + /* netsys_v2 */ u16 minfo; u16 winfo; + + /* netsys_v3 */ + u32 w3info; + u32 wpao; }; /* software-only entry type */ @@ -218,6 +234,7 @@ struct mtk_foe_ipv6_6rd { #define MTK_FOE_ENTRY_V1_SIZE 80 #define MTK_FOE_ENTRY_V2_SIZE 96 +#define MTK_FOE_ENTRY_V3_SIZE 128 struct mtk_foe_entry { u32 ib1; @@ -228,7 +245,7 @@ struct mtk_foe_entry { struct mtk_foe_ipv4_dslite dslite; struct mtk_foe_ipv6 ipv6; struct mtk_foe_ipv6_6rd ipv6_6rd; - u32 data[23]; + u32 data[31]; }; }; -- cgit From 64a37272fa5fb2d951ebd1a96fd42b045d64924c Mon Sep 17 00:00:00 2001 From: Yang Li Date: Thu, 27 Jul 2023 08:57:41 +0800 Subject: team: Remove NULL check before dev_{put, hold} The call netdev_{put, hold} of dev_{put, hold} will check NULL, so there is no need to check before using dev_{put, hold}, remove it to silence the warning: ./drivers/net/team/team.c:2325:3-10: WARNING: NULL check before dev_{put, hold} functions is not needed. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=5991 Signed-off-by: Yang Li Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/team/team.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index d3dc22509ea5..bc50fc3f6913 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2321,8 +2321,7 @@ static struct team *team_nl_team_get(struct genl_info *info) ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]); dev = dev_get_by_index(net, ifindex); if (!dev || dev->netdev_ops != &team_netdev_ops) { - if (dev) - dev_put(dev); + dev_put(dev); return NULL; } -- cgit From 2b3082c6ef3b0104d822f6f18d2afbe5fc9a5c2c Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Sat, 29 Jul 2023 04:52:15 +0530 Subject: net: flow_dissector: Use 64bits for used_keys As 32bits of dissector->used_keys are exhausted, increase the size to 64bits. This is base change for ESP/AH flow dissector patch. Please find patch and discussions at https://lore.kernel.org/netdev/ZMDNjD46BvZ5zp5I@corigine.com/T/#t Signed-off-by: Ratheesh Kannoth Reviewed-by: Petr Machata # for mlxsw Tested-by: Petr Machata Reviewed-by: Martin Habets Reviewed-by: Simon Horman Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix_vsc9959.c | 8 +-- drivers/net/dsa/sja1105/sja1105_flower.c | 8 +-- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 6 +- .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 18 +++--- .../ethernet/freescale/dpaa2/dpaa2-switch-flower.c | 22 +++---- drivers/net/ethernet/freescale/enetc/enetc_qos.c | 8 +-- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 16 +++--- drivers/net/ethernet/intel/i40e/i40e_main.c | 18 +++--- drivers/net/ethernet/intel/iavf/iavf_main.c | 18 +++--- drivers/net/ethernet/intel/ice/ice_tc_lib.c | 44 +++++++------- drivers/net/ethernet/intel/igb/igb_main.c | 8 +-- .../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 18 +++--- .../ethernet/marvell/prestera/prestera_flower.c | 20 +++---- .../ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c | 25 ++++---- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 44 +++++++------- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 22 +++---- .../ethernet/microchip/lan966x/lan966x_tc_flower.c | 4 +- .../ethernet/microchip/sparx5/sparx5_tc_flower.c | 4 +- drivers/net/ethernet/microchip/vcap/vcap_tc.c | 18 +++--- drivers/net/ethernet/microchip/vcap/vcap_tc.h | 2 +- drivers/net/ethernet/mscc/ocelot_flower.c | 28 ++++----- .../net/ethernet/netronome/nfp/flower/conntrack.c | 43 +++++++------- .../net/ethernet/netronome/nfp/flower/offload.c | 64 ++++++++++----------- drivers/net/ethernet/qlogic/qede/qede_filter.c | 12 ++-- drivers/net/ethernet/sfc/tc.c | 67 +++++++++++----------- .../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 6 +- drivers/net/ethernet/ti/am65-cpsw-qos.c | 6 +- drivers/net/ethernet/ti/cpsw_priv.c | 6 +- 28 files changed, 286 insertions(+), 277 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index dce3548dcd05..4a6e52929d25 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1746,10 +1746,10 @@ static int vsc9959_stream_identify(struct flow_cls_offload *f, struct flow_dissector *dissector = rule->match.dissector; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) return -EOPNOTSUPP; if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c index fad5afe3819c..9e8ca182c722 100644 --- a/drivers/net/dsa/sja1105/sja1105_flower.c +++ b/drivers/net/dsa/sja1105/sja1105_flower.c @@ -205,10 +205,10 @@ static int sja1105_flower_parse_key(struct sja1105_private *priv, u16 pcp = U16_MAX; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index d8afcf8d6b30..38d89d80b4a9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -373,9 +373,9 @@ static int bnxt_tc_parse_flow(struct bnxt *bp, struct flow_dissector *dissector = rule->match.dissector; /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ - if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || - (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) { - netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x\n", + if ((dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || + (dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_BASIC)) == 0) { + netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c index d3541159487d..72ac4a34424b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c @@ -313,15 +313,15 @@ static int cxgb4_validate_flow_match(struct net_device *dev, u16 ethtype_key = 0; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IP))) { - netdev_warn(dev, "Unsupported key used: 0x%x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP))) { + netdev_warn(dev, "Unsupported key used: 0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c index c39b866e2582..4798fb7fe35d 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c @@ -17,14 +17,14 @@ static int dpaa2_switch_flower_parse_key(struct flow_cls_offload *cls, struct dpsw_acl_fields *acl_h, *acl_m; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_IP) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used"); return -EOPNOTSUPP; @@ -539,9 +539,9 @@ static int dpaa2_switch_flower_parse_mirror_key(struct flow_cls_offload *cls, int ret = -EOPNOTSUPP; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_VLAN))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) { NL_SET_ERR_MSG_MOD(extack, "Mirroring is supported only per VLAN"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c index 270cbd5e8684..2513b44056c1 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c @@ -483,13 +483,13 @@ struct enetc_psfp { static struct actions_fwd enetc_act_fwd[] = { { BIT(FLOW_ACTION_GATE), - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS), + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS), FILTER_ACTION_TYPE_PSFP }, { BIT(FLOW_ACTION_POLICE) | BIT(FLOW_ACTION_GATE), - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS), + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS), FILTER_ACTION_TYPE_PSFP }, /* example for ACL actions */ @@ -1069,8 +1069,8 @@ revert_sid: return err; } -static struct actions_fwd *enetc_check_flow_actions(u64 acts, - unsigned int inputkeys) +static struct actions_fwd * +enetc_check_flow_actions(u64 acts, unsigned long long inputkeys) { int i; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bf675c15fbb9..83ab89f44250 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7315,14 +7315,14 @@ static int hclge_parse_cls_flower(struct hclge_dev *hdev, struct flow_dissector *dissector = flow->match.dissector; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS))) { - dev_err(&hdev->pdev->dev, "unsupported key set: %#x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS))) { + dev_err(&hdev->pdev->dev, "unsupported key set: %#llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 982ae70c51e8..3d0d6974c2a7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8525,15 +8525,15 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, u8 field_flags = 0; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) { - dev_err(&pf->pdev->dev, "Unsupported key used: 0x%x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID))) { + dev_err(&pf->pdev->dev, "Unsupported key used: 0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 9610ca770349..7b300c86ceda 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -3744,15 +3744,15 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, struct virtchnl_filter *vf = &filter->f; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) { - dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID))) { + dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index 4a34ef5f58d3..38547db1ec4e 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -1343,24 +1343,24 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, dissector = rule->match.dissector; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_CVLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | - BIT(FLOW_DISSECTOR_KEY_IP) | - BIT(FLOW_DISSECTOR_KEY_ENC_IP) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_PPPOE) | - BIT(FLOW_DISSECTOR_KEY_L2TPV3))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PPPOE) | + BIT_ULL(FLOW_DISSECTOR_KEY_L2TPV3))) { NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported key used"); return -EOPNOTSUPP; } @@ -1382,10 +1382,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, */ headers = &fltr->inner_headers; } else if (dissector->used_keys & - (BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS))) { + (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) { NL_SET_ERR_MSG_MOD(fltr->extack, "Tunnel key used, but device isn't a tunnel"); return -EOPNOTSUPP; } else { diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9a2561409b06..9f63a10c6f80 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2615,10 +2615,10 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter, struct netlink_ext_ack *extack = f->common.extack; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported key used, only BASIC, CONTROL, ETH_ADDRS and VLAN are supported"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 0915a0121316..5a44e9b96fc0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -454,15 +454,15 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, dissector = rule->match.dissector; if ((dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_IP)))) { - netdev_info(nic->netdev, "unsupported flow used key 0x%x", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP)))) { + netdev_info(nic->netdev, "unsupported flow used key 0x%llx", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c index 3e20e71b0f81..8b9455d8a4f7 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c @@ -202,16 +202,16 @@ static int prestera_flower_parse(struct prestera_flow_block *block, int err; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_META) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ICMP) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_PORTS_RANGE) | - BIT(FLOW_DISSECTOR_KEY_VLAN))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_META) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ICMP) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS_RANGE) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) { NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported key"); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c index 2b80fe73549d..8c531f4ec912 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c @@ -221,16 +221,21 @@ mlx5_ct_fs_smfs_destroy(struct mlx5_ct_fs *fs) } static inline bool -mlx5_tc_ct_valid_used_dissector_keys(const u32 used_keys) +mlx5_tc_ct_valid_used_dissector_keys(const u64 used_keys) { -#define DISS_BIT(name) BIT(FLOW_DISSECTOR_KEY_ ## name) - const u32 basic_keys = DISS_BIT(BASIC) | DISS_BIT(CONTROL) | DISS_BIT(META); - const u32 ipv4_tcp = basic_keys | DISS_BIT(IPV4_ADDRS) | DISS_BIT(PORTS) | DISS_BIT(TCP); - const u32 ipv6_tcp = basic_keys | DISS_BIT(IPV6_ADDRS) | DISS_BIT(PORTS) | DISS_BIT(TCP); - const u32 ipv4_udp = basic_keys | DISS_BIT(IPV4_ADDRS) | DISS_BIT(PORTS); - const u32 ipv6_udp = basic_keys | DISS_BIT(IPV6_ADDRS) | DISS_BIT(PORTS); - const u32 ipv4_gre = basic_keys | DISS_BIT(IPV4_ADDRS); - const u32 ipv6_gre = basic_keys | DISS_BIT(IPV6_ADDRS); +#define DISS_BIT(name) BIT_ULL(FLOW_DISSECTOR_KEY_ ## name) + const u64 basic_keys = DISS_BIT(BASIC) | DISS_BIT(CONTROL) | + DISS_BIT(META); + const u64 ipv4_tcp = basic_keys | DISS_BIT(IPV4_ADDRS) | + DISS_BIT(PORTS) | DISS_BIT(TCP); + const u64 ipv6_tcp = basic_keys | DISS_BIT(IPV6_ADDRS) | + DISS_BIT(PORTS) | DISS_BIT(TCP); + const u64 ipv4_udp = basic_keys | DISS_BIT(IPV4_ADDRS) | + DISS_BIT(PORTS); + const u64 ipv6_udp = basic_keys | DISS_BIT(IPV6_ADDRS) | + DISS_BIT(PORTS); + const u64 ipv4_gre = basic_keys | DISS_BIT(IPV4_ADDRS); + const u64 ipv6_gre = basic_keys | DISS_BIT(IPV6_ADDRS); return (used_keys == ipv4_tcp || used_keys == ipv4_udp || used_keys == ipv6_tcp || used_keys == ipv6_udp || used_keys == ipv4_gre || used_keys == ipv6_gre); @@ -247,7 +252,7 @@ mlx5_ct_fs_smfs_ct_validate_flow_rule(struct mlx5_ct_fs *fs, struct flow_rule *f struct flow_match_tcp tcp; if (!mlx5_tc_ct_valid_used_dissector_keys(flow_rule->match.dissector->used_keys)) { - ct_dbg("rule uses unexpected dissectors (0x%08x)", + ct_dbg("rule uses unexpected dissectors (0x%016llx)", flow_rule->match.dissector->used_keys); return false; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 507825a1abc8..dfd282319753 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2590,29 +2590,29 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, match_level = outer_match_level; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_META) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_CVLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_TCP) | - BIT(FLOW_DISSECTOR_KEY_IP) | - BIT(FLOW_DISSECTOR_KEY_CT) | - BIT(FLOW_DISSECTOR_KEY_ENC_IP) | - BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | - BIT(FLOW_DISSECTOR_KEY_ICMP) | - BIT(FLOW_DISSECTOR_KEY_MPLS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_META) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_CT) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ICMP) | + BIT_ULL(FLOW_DISSECTOR_KEY_MPLS))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported key"); - netdev_dbg(priv->netdev, "Unsupported key used: 0x%x\n", + netdev_dbg(priv->netdev, "Unsupported key used: 0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 8329100479b3..af3f57d017ec 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -558,17 +558,17 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, int err; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_META) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_PORTS_RANGE) | - BIT(FLOW_DISSECTOR_KEY_TCP) | - BIT(FLOW_DISSECTOR_KEY_IP) | - BIT(FLOW_DISSECTOR_KEY_VLAN))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_META) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS_RANGE) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) { dev_err(mlxsw_sp->bus_info->dev, "Unsupported key\n"); NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported key"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c index 96b3def6c474..d696cf9dbd19 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c @@ -75,7 +75,7 @@ lan966x_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL); return err; @@ -172,7 +172,7 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st) } } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC); return err; out: NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error"); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c index 3f87a5285a6d..906299ad8425 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c @@ -126,7 +126,7 @@ sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st) } } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC); return err; @@ -175,7 +175,7 @@ sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL); return err; diff --git a/drivers/net/ethernet/microchip/vcap/vcap_tc.c b/drivers/net/ethernet/microchip/vcap/vcap_tc.c index 09abe7944af6..27e2dffb65e6 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_tc.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_tc.c @@ -50,7 +50,7 @@ int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS); return err; @@ -86,7 +86,7 @@ int vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage *st) } } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS); return err; @@ -124,7 +124,7 @@ int vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage *st) goto out; } } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS); return err; out: NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error"); @@ -158,7 +158,7 @@ int vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_PORTS); return err; @@ -201,7 +201,7 @@ int vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN); return 0; out: @@ -238,7 +238,7 @@ int vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st, if (mt.mask->vlan_tpid) st->tpid = be16_to_cpu(mt.key->vlan_tpid); - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_VLAN); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_VLAN); return 0; out: @@ -313,7 +313,7 @@ int vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_TCP); return err; @@ -376,7 +376,7 @@ int vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ARP); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ARP); return 0; @@ -401,7 +401,7 @@ int vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage *st) goto out; } - st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IP); + st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IP); return err; diff --git a/drivers/net/ethernet/microchip/vcap/vcap_tc.h b/drivers/net/ethernet/microchip/vcap/vcap_tc.h index 071f892f9aa4..49b02d032906 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_tc.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_tc.h @@ -14,7 +14,7 @@ struct vcap_tc_flower_parse_usage { u16 l3_proto; u8 l4_proto; u16 tpid; - unsigned int used_keys; + unsigned long long used_keys; }; int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st); diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index e0916afcddfb..33b438c6aec5 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -581,14 +581,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, int ret; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_META) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_META) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { return -EOPNOTSUPP; } @@ -641,12 +641,12 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, * then just bail out */ if ((dissector->used_keys & - (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL))) != - (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL))) + (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) != + (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) return -EOPNOTSUPP; flow_rule_match_eth_addrs(rule, &match); diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c index 73032173ac4e..2643c4b3ff1f 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c +++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c @@ -61,7 +61,7 @@ bool is_pre_ct_flow(struct flow_cls_offload *flow) struct flow_match_ct ct; int i; - if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT)) { + if (dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CT)) { flow_rule_match_ct(rule, &ct); if (ct.key->ct_state) return false; @@ -94,7 +94,7 @@ bool is_post_ct_flow(struct flow_cls_offload *flow) struct flow_match_ct ct; int i; - if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT)) { + if (dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CT)) { flow_rule_match_ct(rule, &ct); if (ct.key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) return true; @@ -236,10 +236,11 @@ static bool nfp_ct_merge_check_cannot_skip(struct nfp_fl_ct_flow_entry *entry1, static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, struct nfp_fl_ct_flow_entry *entry2) { - unsigned int ovlp_keys = entry1->rule->match.dissector->used_keys & - entry2->rule->match.dissector->used_keys; + unsigned long long ovlp_keys; bool out, is_v6 = false; u8 ip_proto = 0; + ovlp_keys = entry1->rule->match.dissector->used_keys & + entry2->rule->match.dissector->used_keys; /* Temporary buffer for mangling keys, 64 is enough to cover max * struct size of key in various fields that may be mangled. * Supported fields to mangle: @@ -257,7 +258,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, /* Check the overlapped fields one by one, the unmasked part * should not conflict with each other. */ - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)) { struct flow_match_control match1, match2; flow_rule_match_control(entry1->rule, &match1); @@ -267,7 +268,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_BASIC)) { struct flow_match_basic match1, match2; flow_rule_match_basic(entry1->rule, &match1); @@ -289,7 +290,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, * will be do merge check when do nft and post ct merge, * so skip this ip merge check here. */ - if ((ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS)) && + if ((ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS)) && nfp_ct_merge_check_cannot_skip(entry1, entry2)) { struct flow_match_ipv4_addrs match1, match2; @@ -311,7 +312,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, * will be do merge check when do nft and post ct merge, * so skip this ip merge check here. */ - if ((ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS)) && + if ((ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS)) && nfp_ct_merge_check_cannot_skip(entry1, entry2)) { struct flow_match_ipv6_addrs match1, match2; @@ -333,7 +334,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, * will be do merge check when do nft and post ct merge, * so skip this tport merge check here. */ - if ((ovlp_keys & BIT(FLOW_DISSECTOR_KEY_PORTS)) && + if ((ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_PORTS)) && nfp_ct_merge_check_cannot_skip(entry1, entry2)) { enum flow_action_mangle_base htype = FLOW_ACT_MANGLE_UNSPEC; struct flow_match_ports match1, match2; @@ -355,7 +356,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS)) { struct flow_match_eth_addrs match1, match2; flow_rule_match_eth_addrs(entry1->rule, &match1); @@ -371,7 +372,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_VLAN)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_VLAN)) { struct flow_match_vlan match1, match2; flow_rule_match_vlan(entry1->rule, &match1); @@ -381,7 +382,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_MPLS)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_MPLS)) { struct flow_match_mpls match1, match2; flow_rule_match_mpls(entry1->rule, &match1); @@ -391,7 +392,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_TCP)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_TCP)) { struct flow_match_tcp match1, match2; flow_rule_match_tcp(entry1->rule, &match1); @@ -401,7 +402,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IP)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_IP)) { struct flow_match_ip match1, match2; flow_rule_match_ip(entry1->rule, &match1); @@ -413,7 +414,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_KEYID)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID)) { struct flow_match_enc_keyid match1, match2; flow_rule_match_enc_keyid(entry1->rule, &match1); @@ -423,7 +424,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { struct flow_match_ipv4_addrs match1, match2; flow_rule_match_enc_ipv4_addrs(entry1->rule, &match1); @@ -433,7 +434,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) { struct flow_match_ipv6_addrs match1, match2; flow_rule_match_enc_ipv6_addrs(entry1->rule, &match1); @@ -443,7 +444,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL)) { struct flow_match_control match1, match2; flow_rule_match_enc_control(entry1->rule, &match1); @@ -453,7 +454,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IP)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP)) { struct flow_match_ip match1, match2; flow_rule_match_enc_ip(entry1->rule, &match1); @@ -463,7 +464,7 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1, goto check_failed; } - if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_OPTS)) { + if (ovlp_keys & BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS)) { struct flow_match_enc_opts match1, match2; flow_rule_match_enc_opts(entry1->rule, &match1); @@ -589,7 +590,7 @@ static int nfp_ct_check_meta(struct nfp_fl_ct_flow_entry *post_ct_entry, int i; ct_met = get_flow_act(nft_entry->rule, FLOW_ACTION_CT_METADATA); - if (ct_met && (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT))) { + if (ct_met && (dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CT))) { u32 *act_lbl; act_lbl = ct_met->ct_metadata.labels; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 18328eb7f5c3..c153f0575b92 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -24,43 +24,43 @@ FLOW_DIS_FIRST_FRAG) #define NFP_FLOWER_WHITELIST_DISSECTOR \ - (BIT(FLOW_DISSECTOR_KEY_CONTROL) | \ - BIT(FLOW_DISSECTOR_KEY_BASIC) | \ - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_TCP) | \ - BIT(FLOW_DISSECTOR_KEY_PORTS) | \ - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_VLAN) | \ - BIT(FLOW_DISSECTOR_KEY_CVLAN) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IP) | \ - BIT(FLOW_DISSECTOR_KEY_MPLS) | \ - BIT(FLOW_DISSECTOR_KEY_CT) | \ - BIT(FLOW_DISSECTOR_KEY_META) | \ - BIT(FLOW_DISSECTOR_KEY_IP)) + (BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_MPLS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_CT) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_META) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_IP)) #define NFP_FLOWER_WHITELIST_TUN_DISSECTOR \ - (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IP)) + (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP)) #define NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R \ - (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) + (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) #define NFP_FLOWER_WHITELIST_TUN_DISSECTOR_V6_R \ - (BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) + (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | \ + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) #define NFP_FLOWER_MERGE_FIELDS \ (NFP_FLOWER_LAYER_PORT | \ @@ -1303,7 +1303,7 @@ static bool offload_pre_check(struct flow_cls_offload *flow) struct flow_dissector *dissector = rule->match.dissector; struct flow_match_ct ct; - if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT)) { + if (dissector->used_keys & BIT_ULL(FLOW_DISSECTOR_KEY_CT)) { flow_rule_match_ct(rule, &ct); /* Allow special case where CT match is all 0 */ if (memchr_inv(ct.key, 0, sizeof(*ct.key))) diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index 3010833ddde3..a5ac21a0ee33 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -1827,12 +1827,12 @@ qede_parse_flow_attr(struct qede_dev *edev, __be16 proto, memset(tuple, 0, sizeof(*tuple)); if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS))) { - DP_NOTICE(edev, "Unsupported key set:0x%x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS))) { + DP_NOTICE(edev, "Unsupported key set:0x%llx\n", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 15ebd3973922..4dc881159246 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -201,23 +201,23 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, } } if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_CVLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IP) | - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | - BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_TCP) | - BIT(FLOW_DISSECTOR_KEY_IP))) { - NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#x", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP))) { + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#llx", dissector->used_keys); return -EOPNOTSUPP; } @@ -228,12 +228,13 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, !(match->value.eth_proto == htons(ETH_P_IP) || match->value.eth_proto == htons(ETH_P_IPV6))) if (dissector->used_keys & - (BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_IP) | - BIT(FLOW_DISSECTOR_KEY_TCP))) { - NL_SET_ERR_MSG_FMT_MOD(extack, "L3/L4 flower keys %#x require protocol ipv[46]", + (BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP))) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "L3/L4 flower keys %#llx require protocol ipv[46]", dissector->used_keys); return -EINVAL; } @@ -281,9 +282,10 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, if ((match->value.ip_proto != IPPROTO_UDP && match->value.ip_proto != IPPROTO_TCP) || !IS_ALL_ONES(match->mask.ip_proto)) if (dissector->used_keys & - (BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_TCP))) { - NL_SET_ERR_MSG_FMT_MOD(extack, "L4 flower keys %#x require ipproto udp or tcp", + (BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP))) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "L4 flower keys %#llx require ipproto udp or tcp", dissector->used_keys); return -EINVAL; } @@ -344,12 +346,13 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, MAP_ENC_KEY_AND_MASK(PORTS, ports, enc_ports, dst, enc_dport); MAP_ENC_KEY_AND_MASK(KEYID, enc_keyid, enc_keyid, keyid, enc_keyid); } else if (dissector->used_keys & - (BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ENC_IP) | - BIT(FLOW_DISSECTOR_KEY_ENC_PORTS))) { - NL_SET_ERR_MSG_FMT_MOD(extack, "Flower enc keys require enc_control (keys: %#x)", + (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Flower enc keys require enc_control (keys: %#llx)", dissector->used_keys); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 687f43cd466c..f9e43fc32ee8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -1355,7 +1355,7 @@ static int __stmmac_test_l3filt(struct stmmac_priv *priv, u32 dst, u32 src, goto cleanup_rss; } - dissector->used_keys |= (1 << FLOW_DISSECTOR_KEY_IPV4_ADDRS); + dissector->used_keys |= (1ULL << FLOW_DISSECTOR_KEY_IPV4_ADDRS); dissector->offset[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = 0; cls = kzalloc(sizeof(*cls), GFP_KERNEL); @@ -1481,8 +1481,8 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src, goto cleanup_rss; } - dissector->used_keys |= (1 << FLOW_DISSECTOR_KEY_BASIC); - dissector->used_keys |= (1 << FLOW_DISSECTOR_KEY_PORTS); + dissector->used_keys |= (1ULL << FLOW_DISSECTOR_KEY_BASIC); + dissector->used_keys |= (1ULL << FLOW_DISSECTOR_KEY_PORTS); dissector->offset[FLOW_DISSECTOR_KEY_BASIC] = 0; dissector->offset[FLOW_DISSECTOR_KEY_PORTS] = offsetof(typeof(keys), key); diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c index eced87fa261c..9ac2ff05d501 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.c +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c @@ -624,9 +624,9 @@ static int am65_cpsw_qos_clsflower_add_policer(struct am65_cpsw_port *port, int ret; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c index e966dd47e2db..ae52cdbcf8cc 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.c +++ b/drivers/net/ethernet/ti/cpsw_priv.c @@ -1396,9 +1396,9 @@ static int cpsw_qos_clsflower_add_policer(struct cpsw_priv *priv, int ret; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { + ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used"); return -EOPNOTSUPP; -- cgit From 53b8d2be4d71953cce547696c39a2a3cb0f1ee48 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 31 Jul 2023 15:52:52 +0800 Subject: can: flexcan: fix the return value handle for platform_get_irq() There is no possible for platform_get_irq() to return 0 and the return value of platform_get_irq() is more sensible to show the error reason. Signed-off-by: Ruan Jinjie Link: https://lore.kernel.org/all/20230731075252.359965-1-ruanjinjie@huawei.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan/flexcan-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index 48273d51f271..add39e922b89 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -2089,8 +2089,8 @@ static int flexcan_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -ENODEV; + if (irq < 0) + return irq; regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) @@ -2167,13 +2167,13 @@ static int flexcan_probe(struct platform_device *pdev) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) { priv->irq_boff = platform_get_irq(pdev, 1); - if (priv->irq_boff <= 0) { - err = -ENODEV; + if (priv->irq_boff < 0) { + err = priv->irq_boff; goto failed_platform_get_irq; } priv->irq_err = platform_get_irq(pdev, 2); - if (priv->irq_err <= 0) { - err = -ENODEV; + if (priv->irq_err < 0) { + err = priv->irq_err; goto failed_platform_get_irq; } } -- cgit From fbe534f7bf213d485b0ed5362b24a41bf3e18803 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Fri, 28 Jul 2023 16:19:19 +0200 Subject: can: tcan4x5x: Remove reserved register 0x814 from writable table The mentioned register is not writable. It is reserved and should not be written. Fixes: 39dbb21b6a29 ("can: tcan4x5x: Specify separate read/write ranges") Signed-off-by: Markus Schneider-Pargmann Reviewed-by: Michal Kubiak Link: https://lore.kernel.org/all/20230728141923.162477-3-msp@baylibre.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/tcan4x5x-regmap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/tcan4x5x-regmap.c b/drivers/net/can/m_can/tcan4x5x-regmap.c index 2b218ce04e9f..fafa6daa67e6 100644 --- a/drivers/net/can/m_can/tcan4x5x-regmap.c +++ b/drivers/net/can/m_can/tcan4x5x-regmap.c @@ -95,7 +95,6 @@ static const struct regmap_range tcan4x5x_reg_table_wr_range[] = { regmap_reg_range(0x000c, 0x0010), /* Device configuration registers and Interrupt Flags*/ regmap_reg_range(0x0800, 0x080c), - regmap_reg_range(0x0814, 0x0814), regmap_reg_range(0x0820, 0x0820), regmap_reg_range(0x0830, 0x0830), /* M_CAN */ -- cgit From c1b17ea7dd7ca7a199d85e42fd3f8e3d46816b73 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Fri, 28 Jul 2023 16:19:20 +0200 Subject: can: tcan4x5x: Check size of mram configuration To reduce debugging effort in case the mram is misconfigured, add this size check of the DT configuration. Currently if the mram configuration doesn't fit into the available MRAM it just overwrites other areas of the MRAM. Signed-off-by: Markus Schneider-Pargmann Reviewed-by: Michal Kubiak Link: https://lore.kernel.org/all/20230728141923.162477-4-msp@baylibre.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/m_can.c | 16 ++++++++++++++++ drivers/net/can/m_can/m_can.h | 1 + drivers/net/can/m_can/tcan4x5x-core.c | 5 +++++ 3 files changed, 22 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index d204703521d2..16ecc11c7f62 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1913,6 +1913,22 @@ static int register_m_can_dev(struct net_device *dev) return register_candev(dev); } +int m_can_check_mram_cfg(struct m_can_classdev *cdev, u32 mram_max_size) +{ + u32 total_size; + + total_size = cdev->mcfg[MRAM_TXB].off - cdev->mcfg[MRAM_SIDF].off + + cdev->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; + if (total_size > mram_max_size) { + dev_err(cdev->dev, "Total size of mram config(%u) exceeds mram(%u)\n", + total_size, mram_max_size); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(m_can_check_mram_cfg); + static void m_can_of_parse_mram(struct m_can_classdev *cdev, const u32 *mram_config_vals) { diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index c543928c756f..520e14277dff 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -103,6 +103,7 @@ int m_can_class_register(struct m_can_classdev *cdev); void m_can_class_unregister(struct m_can_classdev *cdev); int m_can_class_get_clocks(struct m_can_classdev *cdev); int m_can_init_ram(struct m_can_classdev *priv); +int m_can_check_mram_cfg(struct m_can_classdev *cdev, u32 mram_max_size); int m_can_class_suspend(struct device *dev); int m_can_class_resume(struct device *dev); diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index 2342aa011647..e706518176e4 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -80,6 +80,7 @@ TCAN4X5X_MCAN_IR_RF1F) #define TCAN4X5X_MRAM_START 0x8000 +#define TCAN4X5X_MRAM_SIZE 0x800 #define TCAN4X5X_MCAN_OFFSET 0x1000 #define TCAN4X5X_CLEAR_ALL_INT 0xffffffff @@ -307,6 +308,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi) if (!mcan_class) return -ENOMEM; + ret = m_can_check_mram_cfg(mcan_class, TCAN4X5X_MRAM_SIZE); + if (ret) + goto out_m_can_class_free_dev; + priv = cdev_to_priv(mcan_class); priv->power = devm_regulator_get_optional(&spi->dev, "vsup"); -- cgit From 0d6f3b25ac2fa13fddc6106239f7fa7795c8e808 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Fri, 28 Jul 2023 16:19:21 +0200 Subject: can: tcan4x5x: Rename ID registers to match datasheet The datasheet calls these registers ID1 and ID2. Rename these to avoid confusion. Signed-off-by: Markus Schneider-Pargmann Reviewed-by: Michal Kubiak Link: https://lore.kernel.org/all/20230728141923.162477-5-msp@baylibre.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/tcan4x5x-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index e706518176e4..fb9375fa20ec 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -6,8 +6,8 @@ #define TCAN4X5X_EXT_CLK_DEF 40000000 -#define TCAN4X5X_DEV_ID0 0x00 -#define TCAN4X5X_DEV_ID1 0x04 +#define TCAN4X5X_DEV_ID1 0x00 +#define TCAN4X5X_DEV_ID2 0x04 #define TCAN4X5X_REV 0x08 #define TCAN4X5X_STATUS 0x0C #define TCAN4X5X_ERROR_STATUS_MASK 0x10 -- cgit From 142c6dc6d9d7c27157e41985519464d5985e3d95 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Fri, 28 Jul 2023 16:19:22 +0200 Subject: can: tcan4x5x: Add support for tcan4552/4553 tcan4552 and tcan4553 do not have wake or state pins, so they are currently not compatible with the generic driver. The generic driver uses tcan4x5x_disable_state() and tcan4x5x_disable_wake() if the gpios are not defined. These functions use register bits that are not available in tcan4552/4553. This patch adds support by introducing version information to reflect if the chip has wake and state pins. Also the version is now checked. Signed-off-by: Markus Schneider-Pargmann Link: https://lore.kernel.org/all/20230728141923.162477-6-msp@baylibre.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/tcan4x5x-core.c | 104 +++++++++++++++++++++++++++++----- 1 file changed, 90 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index fb9375fa20ec..2d329b4e4f52 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -7,6 +7,7 @@ #define TCAN4X5X_EXT_CLK_DEF 40000000 #define TCAN4X5X_DEV_ID1 0x00 +#define TCAN4X5X_DEV_ID1_TCAN 0x4e414354 /* ASCII TCAN */ #define TCAN4X5X_DEV_ID2 0x04 #define TCAN4X5X_REV 0x08 #define TCAN4X5X_STATUS 0x0C @@ -103,6 +104,37 @@ #define TCAN4X5X_WD_3_S_TIMER BIT(29) #define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29)) +struct tcan4x5x_version_info { + const char *name; + u32 id2_register; + + bool has_wake_pin; + bool has_state_pin; +}; + +enum { + TCAN4552 = 0, + TCAN4553, + TCAN4X5X, +}; + +static const struct tcan4x5x_version_info tcan4x5x_versions[] = { + [TCAN4552] = { + .name = "4552", + .id2_register = 0x32353534, + }, + [TCAN4553] = { + .name = "4553", + .id2_register = 0x32353534, + }, + /* generic version with no id2_register at the end */ + [TCAN4X5X] = { + .name = "generic", + .has_wake_pin = true, + .has_state_pin = true, + }, +}; + static inline struct tcan4x5x_priv *cdev_to_priv(struct m_can_classdev *cdev) { return container_of(cdev, struct tcan4x5x_priv, cdev); @@ -254,18 +286,53 @@ static int tcan4x5x_disable_state(struct m_can_classdev *cdev) TCAN4X5X_DISABLE_INH_MSK, 0x01); } -static int tcan4x5x_get_gpios(struct m_can_classdev *cdev) +static const struct tcan4x5x_version_info +*tcan4x5x_find_version(struct tcan4x5x_priv *priv) +{ + u32 val; + int ret; + + ret = regmap_read(priv->regmap, TCAN4X5X_DEV_ID1, &val); + if (ret) + return ERR_PTR(ret); + + if (val != TCAN4X5X_DEV_ID1_TCAN) { + dev_err(&priv->spi->dev, "Not a tcan device %x\n", val); + return ERR_PTR(-ENODEV); + } + + ret = regmap_read(priv->regmap, TCAN4X5X_DEV_ID2, &val); + if (ret) + return ERR_PTR(ret); + + for (int i = 0; i != ARRAY_SIZE(tcan4x5x_versions); ++i) { + const struct tcan4x5x_version_info *vinfo = &tcan4x5x_versions[i]; + + if (!vinfo->id2_register || val == vinfo->id2_register) { + dev_info(&priv->spi->dev, "Detected TCAN device version %s\n", + vinfo->name); + return vinfo; + } + } + + return &tcan4x5x_versions[TCAN4X5X]; +} + +static int tcan4x5x_get_gpios(struct m_can_classdev *cdev, + const struct tcan4x5x_version_info *version_info) { struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); int ret; - tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake", - GPIOD_OUT_HIGH); - if (IS_ERR(tcan4x5x->device_wake_gpio)) { - if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (version_info->has_wake_pin) { + tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake", + GPIOD_OUT_HIGH); + if (IS_ERR(tcan4x5x->device_wake_gpio)) { + if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; - tcan4x5x_disable_wake(cdev); + tcan4x5x_disable_wake(cdev); + } } tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset", @@ -277,12 +344,14 @@ static int tcan4x5x_get_gpios(struct m_can_classdev *cdev) if (ret) return ret; - tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, - "device-state", - GPIOD_IN); - if (IS_ERR(tcan4x5x->device_state_gpio)) { - tcan4x5x->device_state_gpio = NULL; - tcan4x5x_disable_state(cdev); + if (version_info->has_state_pin) { + tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, + "device-state", + GPIOD_IN); + if (IS_ERR(tcan4x5x->device_state_gpio)) { + tcan4x5x->device_state_gpio = NULL; + tcan4x5x_disable_state(cdev); + } } return 0; @@ -299,6 +368,7 @@ static struct m_can_ops tcan4x5x_ops = { static int tcan4x5x_can_probe(struct spi_device *spi) { + const struct tcan4x5x_version_info *version_info; struct tcan4x5x_priv *priv; struct m_can_classdev *mcan_class; int freq, ret; @@ -361,7 +431,13 @@ static int tcan4x5x_can_probe(struct spi_device *spi) if (ret) goto out_m_can_class_free_dev; - ret = tcan4x5x_get_gpios(mcan_class); + version_info = tcan4x5x_find_version(priv); + if (IS_ERR(version_info)) { + ret = PTR_ERR(version_info); + goto out_power; + } + + ret = tcan4x5x_get_gpios(mcan_class, version_info); if (ret) goto out_power; -- cgit From 35e7aaab3e0058dba3eaf082c3f1ccee96c20b1c Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Fri, 28 Jul 2023 16:19:23 +0200 Subject: can: tcan4x5x: Add error messages in probe To be able to understand issues during probe easier, add error messages if something fails. Signed-off-by: Markus Schneider-Pargmann Link: https://lore.kernel.org/all/20230728141923.162477-7-msp@baylibre.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/m_can/tcan4x5x-core.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index 2d329b4e4f52..8a4143809d33 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -402,6 +402,8 @@ static int tcan4x5x_can_probe(struct spi_device *spi) /* Sanity check */ if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) { + dev_err(&spi->dev, "Clock frequency is out of supported range %d\n", + freq); ret = -ERANGE; goto out_m_can_class_free_dev; } @@ -420,16 +422,23 @@ static int tcan4x5x_can_probe(struct spi_device *spi) /* Configure the SPI bus */ spi->bits_per_word = 8; ret = spi_setup(spi); - if (ret) + if (ret) { + dev_err(&spi->dev, "SPI setup failed %pe\n", ERR_PTR(ret)); goto out_m_can_class_free_dev; + } ret = tcan4x5x_regmap_init(priv); - if (ret) + if (ret) { + dev_err(&spi->dev, "regmap init failed %pe\n", ERR_PTR(ret)); goto out_m_can_class_free_dev; + } ret = tcan4x5x_power_enable(priv->power, 1); - if (ret) + if (ret) { + dev_err(&spi->dev, "Enabling regulator failed %pe\n", + ERR_PTR(ret)); goto out_m_can_class_free_dev; + } version_info = tcan4x5x_find_version(priv); if (IS_ERR(version_info)) { @@ -438,16 +447,24 @@ static int tcan4x5x_can_probe(struct spi_device *spi) } ret = tcan4x5x_get_gpios(mcan_class, version_info); - if (ret) + if (ret) { + dev_err(&spi->dev, "Getting gpios failed %pe\n", ERR_PTR(ret)); goto out_power; + } ret = tcan4x5x_init(mcan_class); - if (ret) + if (ret) { + dev_err(&spi->dev, "tcan initialization failed %pe\n", + ERR_PTR(ret)); goto out_power; + } ret = m_can_class_register(mcan_class); - if (ret) + if (ret) { + dev_err(&spi->dev, "Failed registering m_can device %pe\n", + ERR_PTR(ret)); goto out_power; + } netdev_info(mcan_class->net, "TCAN4X5X successfully initialized.\n"); return 0; -- cgit From 3bb014c72b087fa1d440d1b83cb3dfcfc4d24cff Mon Sep 17 00:00:00 2001 From: Yuanjun Gong Date: Mon, 17 Jul 2023 22:50:08 +0800 Subject: wifi: mt76: mt76x02: fix return value check in mt76x02_mac_process_rx in mt76x02_mac_process_rx(), return an error code if an unexpected result is returned by pskb_trim. Signed-off-by: Yuanjun Gong Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 3e41d809ade3..d5db6ffd6d36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -853,7 +853,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, if (WARN_ON_ONCE(len > skb->len)) return -EINVAL; - pskb_trim(skb, len); + if (pskb_trim(skb, len)) + return -EINVAL; status->chains = BIT(0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); -- cgit From 4f1875c288dfc1ccea81fc17fef1d30c9d8498b2 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 27 Jul 2023 02:35:05 +0800 Subject: wifi: mt76: mt7915: fix tlv length of mt7915_mcu_get_chan_mib_info Correct per-device TLV lengths to avoid invalid operation in firmware. ( 64.040375:28:STATS-E)statsGetSingleHWCounter: MIB counter index = 65472 not supported. This happens on mt7916/mt7986. Fixes: b0bfa00595be ("wifi: mt76: mt7915: improve accuracy of time_busy calculation") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 5f4c2946b26b..50ae7bf3af91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -3038,7 +3038,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO), - req, sizeof(req), true, &skb); + req, len * sizeof(req[0]), true, &skb); if (ret) return ret; -- cgit From 6c0570bc21ec2073890aa252c8420ca7bec402e4 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 27 Jul 2023 02:35:06 +0800 Subject: wifi: mt76: mt7915: fix power-limits while chan_switch If user changes the channel without completely disabling the interface the txpower_sku values reported track the old channel the device was operating on. If user bounces the interface the correct power tables are applied. mt7915_sku_group_len array gets updated before the channel switch happens so it uses data from the old channel. Fixes: ecb187a74e18 ("mt76: mt7915: rework the flow of txpower setting") Fixes: f1d962369d56 ("mt76: mt7915: implement HE per-rate tx power support") Reported-By: Chad Monroe Tested-by: Chad Monroe Signed-off-by: Allen Ye Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index eb95fb28d354..8ebbf186fab2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -471,7 +471,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) ieee80211_wake_queues(hw); } - if (changed & IEEE80211_CONF_CHANGE_POWER) { + if (changed & (IEEE80211_CONF_CHANGE_POWER | + IEEE80211_CONF_CHANGE_CHANNEL)) { ret = mt7915_mcu_set_txpower_sku(phy); if (ret) return ret; -- cgit From 230f3d53a5477bf8b04e649dca67da85635cd1eb Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Fri, 28 Jul 2023 10:13:36 -0700 Subject: i40e: remove i40e_status Replace uses of i40e_status to as equivalent as possible error codes. Remove enum i40e_status as it is no longer needed Signed-off-by: Jan Sokolowski Tested-by: Gurucharan G (A Contingent worker at Intel) Signed-off-by: Tony Nguyen Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230728171336.2446156-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 49 +++--- drivers/net/ethernet/intel/i40e/i40e_adminq.h | 3 +- drivers/net/ethernet/intel/i40e/i40e_common.c | 116 ++++++------- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 20 +-- drivers/net/ethernet/intel/i40e/i40e_ddp.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_diag.c | 6 +- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_hmc.c | 21 ++- drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c | 54 +++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 48 +++--- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 52 +++--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_status.h | 43 ----- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 - drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 179 ++++++++++----------- 16 files changed, 275 insertions(+), 327 deletions(-) delete mode 100644 drivers/net/ethernet/intel/i40e/i40e_status.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 86fac8f959bb..100eb77b8dfe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ -#include "i40e_status.h" #include "i40e_type.h" #include "i40e_register.h" #include "i40e_adminq.h" @@ -284,7 +283,7 @@ static int i40e_config_asq_regs(struct i40e_hw *hw) /* Check one register to verify that config was applied */ reg = rd32(hw, hw->aq.asq.bal); if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa)) - ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; + ret_code = -EIO; return ret_code; } @@ -316,7 +315,7 @@ static int i40e_config_arq_regs(struct i40e_hw *hw) /* Check one register to verify that config was applied */ reg = rd32(hw, hw->aq.arq.bal); if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa)) - ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; + ret_code = -EIO; return ret_code; } @@ -340,14 +339,14 @@ static int i40e_init_asq(struct i40e_hw *hw) if (hw->aq.asq.count > 0) { /* queue already initialized */ - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto init_adminq_exit; } /* verify input for valid configuration */ if ((hw->aq.num_asq_entries == 0) || (hw->aq.asq_buf_size == 0)) { - ret_code = I40E_ERR_CONFIG; + ret_code = -EIO; goto init_adminq_exit; } @@ -399,14 +398,14 @@ static int i40e_init_arq(struct i40e_hw *hw) if (hw->aq.arq.count > 0) { /* queue already initialized */ - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto init_adminq_exit; } /* verify input for valid configuration */ if ((hw->aq.num_arq_entries == 0) || (hw->aq.arq_buf_size == 0)) { - ret_code = I40E_ERR_CONFIG; + ret_code = -EIO; goto init_adminq_exit; } @@ -452,7 +451,7 @@ static int i40e_shutdown_asq(struct i40e_hw *hw) mutex_lock(&hw->aq.asq_mutex); if (hw->aq.asq.count == 0) { - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto shutdown_asq_out; } @@ -486,7 +485,7 @@ static int i40e_shutdown_arq(struct i40e_hw *hw) mutex_lock(&hw->aq.arq_mutex); if (hw->aq.arq.count == 0) { - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto shutdown_arq_out; } @@ -594,7 +593,7 @@ int i40e_init_adminq(struct i40e_hw *hw) (hw->aq.num_asq_entries == 0) || (hw->aq.arq_buf_size == 0) || (hw->aq.asq_buf_size == 0)) { - ret_code = I40E_ERR_CONFIG; + ret_code = -EIO; goto init_adminq_exit; } @@ -626,13 +625,13 @@ int i40e_init_adminq(struct i40e_hw *hw) &hw->aq.api_maj_ver, &hw->aq.api_min_ver, NULL); - if (ret_code != I40E_ERR_ADMIN_QUEUE_TIMEOUT) + if (ret_code != -EIO) break; retry++; msleep(100); i40e_resume_aq(hw); } while (retry < 10); - if (ret_code != I40E_SUCCESS) + if (ret_code != 0) goto init_adminq_free_arq; /* Some features were introduced in different FW API version @@ -672,7 +671,7 @@ int i40e_init_adminq(struct i40e_hw *hw) hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE; if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) { - ret_code = I40E_ERR_FIRMWARE_API_VERSION; + ret_code = -EIO; goto init_adminq_free_arq; } @@ -799,7 +798,7 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, if (hw->aq.asq.count == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Admin queue not initialized.\n"); - status = I40E_ERR_QUEUE_EMPTY; + status = -EIO; goto asq_send_command_error; } @@ -809,7 +808,7 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: head overrun at %d\n", val); - status = I40E_ERR_ADMIN_QUEUE_FULL; + status = -ENOSPC; goto asq_send_command_error; } @@ -840,7 +839,7 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Invalid buffer size: %d.\n", buff_size); - status = I40E_ERR_INVALID_SIZE; + status = -EINVAL; goto asq_send_command_error; } @@ -848,7 +847,7 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Async flag not set along with postpone flag"); - status = I40E_ERR_PARAM; + status = -EINVAL; goto asq_send_command_error; } @@ -863,7 +862,7 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Error queue is full.\n"); - status = I40E_ERR_ADMIN_QUEUE_FULL; + status = -ENOSPC; goto asq_send_command_error; } @@ -940,9 +939,9 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK) status = 0; else if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_EBUSY) - status = I40E_ERR_NOT_READY; + status = -EBUSY; else - status = I40E_ERR_ADMIN_QUEUE_ERROR; + status = -EIO; hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; } @@ -960,11 +959,11 @@ i40e_asq_send_command_atomic_exec(struct i40e_hw *hw, if (rd32(hw, hw->aq.asq.len) & I40E_GL_ATQLEN_ATQCRIT_MASK) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: AQ Critical error.\n"); - status = I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR; + status = -EIO; } else { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Writeback timeout.\n"); - status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; + status = -EIO; } } @@ -1106,7 +1105,7 @@ int i40e_clean_arq_element(struct i40e_hw *hw, if (hw->aq.arq.count == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: Admin queue not initialized.\n"); - ret_code = I40E_ERR_QUEUE_EMPTY; + ret_code = -EIO; goto clean_arq_element_err; } @@ -1114,7 +1113,7 @@ int i40e_clean_arq_element(struct i40e_hw *hw, ntu = rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK; if (ntu == ntc) { /* nothing to do - shouldn't need to update ring's values */ - ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK; + ret_code = -EALREADY; goto clean_arq_element_out; } @@ -1126,7 +1125,7 @@ int i40e_clean_arq_element(struct i40e_hw *hw, (enum i40e_admin_queue_err)le16_to_cpu(desc->retval); flags = le16_to_cpu(desc->flags); if (flags & I40E_AQ_FLAG_ERR) { - ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; + ret_code = -EIO; i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: Event received with error 0x%X.\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index ee394aacef4d..267f2e0a21ce 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -5,7 +5,6 @@ #define _I40E_ADMINQ_H_ #include "i40e_osdep.h" -#include "i40e_status.h" #include "i40e_adminq_cmd.h" #define I40E_ADMINQ_DESC(R, i) \ @@ -117,7 +116,7 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc) }; /* aq_rc is invalid if AQ timed out */ - if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) + if (aq_ret == -EIO) return -EAGAIN; if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])))) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ed88e38d488b..eeef20f77106 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -56,7 +56,7 @@ int i40e_set_mac_type(struct i40e_hw *hw) break; } } else { - status = I40E_ERR_DEVICE_NOT_SUPPORTED; + status = -ENODEV; } hw_dbg(hw, "i40e_set_mac_type found mac: %d, returns: %d\n", @@ -660,7 +660,7 @@ int i40e_init_shared_code(struct i40e_hw *hw) case I40E_MAC_X722: break; default: - return I40E_ERR_DEVICE_NOT_SUPPORTED; + return -ENODEV; } hw->phy.get_link_info = true; @@ -780,7 +780,7 @@ int i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr) if (flags & I40E_AQC_PORT_ADDR_VALID) ether_addr_copy(mac_addr, addrs.port_mac); else - status = I40E_ERR_INVALID_MAC_ADDR; + status = -EINVAL; return status; } @@ -858,7 +858,7 @@ int i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num, pba_size--; if (pba_num_size < (((u32)pba_size * 2) + 1)) { hw_dbg(hw, "Buffer too small for PBA data.\n"); - return I40E_ERR_PARAM; + return -EINVAL; } for (i = 0; i < pba_size; i++) { @@ -955,7 +955,7 @@ static int i40e_poll_globr(struct i40e_hw *hw, hw_dbg(hw, "Global reset failed.\n"); hw_dbg(hw, "I40E_GLGEN_RSTAT = 0x%x\n", reg); - return I40E_ERR_RESET_FAILED; + return -EIO; } #define I40E_PF_RESET_WAIT_COUNT_A0 200 @@ -995,7 +995,7 @@ int i40e_pf_reset(struct i40e_hw *hw) } if (reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK) { hw_dbg(hw, "Global reset polling failed to complete.\n"); - return I40E_ERR_RESET_FAILED; + return -EIO; } /* Now Wait for the FW to be ready */ @@ -1014,7 +1014,7 @@ int i40e_pf_reset(struct i40e_hw *hw) I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK))) { hw_dbg(hw, "wait for FW Reset complete timedout\n"); hw_dbg(hw, "I40E_GLNVM_ULD = 0x%x\n", reg); - return I40E_ERR_RESET_FAILED; + return -EIO; } /* If there was a Global Reset in progress when we got here, @@ -1040,10 +1040,10 @@ int i40e_pf_reset(struct i40e_hw *hw) } if (reg2 & I40E_GLGEN_RSTAT_DEVSTATE_MASK) { if (i40e_poll_globr(hw, grst_del)) - return I40E_ERR_RESET_FAILED; + return -EIO; } else if (reg & I40E_PFGEN_CTRL_PFSWR_MASK) { hw_dbg(hw, "PF reset polling failed to complete.\n"); - return I40E_ERR_RESET_FAILED; + return -EIO; } } @@ -1318,7 +1318,7 @@ i40e_aq_get_phy_capabilities(struct i40e_hw *hw, int status; if (!abilities) - return I40E_ERR_PARAM; + return -EINVAL; do { i40e_fill_default_direct_cmd_desc(&desc, @@ -1341,12 +1341,12 @@ i40e_aq_get_phy_capabilities(struct i40e_hw *hw, switch (hw->aq.asq_last_status) { case I40E_AQ_RC_EIO: - status = I40E_ERR_UNKNOWN_PHY; + status = -EIO; break; case I40E_AQ_RC_EAGAIN: usleep_range(1000, 2000); total_delay++; - status = I40E_ERR_TIMEOUT; + status = -EIO; break; /* also covers I40E_AQ_RC_OK */ default: @@ -1396,7 +1396,7 @@ int i40e_aq_set_phy_config(struct i40e_hw *hw, int status; if (!config) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_phy_config); @@ -2312,7 +2312,7 @@ int i40e_aq_send_driver_version(struct i40e_hw *hw, u16 len; if (dv == NULL) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_driver_version); @@ -2430,7 +2430,7 @@ int i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, /* SEIDs need to either both be set or both be 0 for floating VEB */ if (!!uplink_seid != !!downlink_seid) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_veb); @@ -2485,7 +2485,7 @@ int i40e_aq_get_veb_parameters(struct i40e_hw *hw, int status; if (veb_seid == 0) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_veb_parameters); @@ -2575,7 +2575,7 @@ i40e_aq_add_macvlan(struct i40e_hw *hw, u16 seid, u16 buf_size; if (count == 0 || !mv_list || !hw) - return I40E_ERR_PARAM; + return -EINVAL; buf_size = i40e_prepare_add_macvlan(mv_list, &desc, count, seid); @@ -2608,7 +2608,7 @@ i40e_aq_add_macvlan_v2(struct i40e_hw *hw, u16 seid, u16 buf_size; if (count == 0 || !mv_list || !hw) - return I40E_ERR_PARAM; + return -EINVAL; buf_size = i40e_prepare_add_macvlan(mv_list, &desc, count, seid); @@ -2638,7 +2638,7 @@ i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid, int status; if (count == 0 || !mv_list || !hw) - return I40E_ERR_PARAM; + return -EINVAL; buf_size = count * sizeof(*mv_list); @@ -2685,7 +2685,7 @@ i40e_aq_remove_macvlan_v2(struct i40e_hw *hw, u16 seid, u16 buf_size; if (count == 0 || !mv_list || !hw) - return I40E_ERR_PARAM; + return -EINVAL; buf_size = count * sizeof(*mv_list); @@ -2791,7 +2791,7 @@ int i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid, if (!(rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS || rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS)) { if (count == 0 || !mr_list) - return I40E_ERR_PARAM; + return -EINVAL; } return i40e_mirrorrule_op(hw, i40e_aqc_opc_add_mirror_rule, sw_seid, @@ -2827,7 +2827,7 @@ int i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid, * not matter. */ if (count == 0 || !mr_list) - return I40E_ERR_PARAM; + return -EINVAL; } return i40e_mirrorrule_op(hw, i40e_aqc_opc_delete_mirror_rule, sw_seid, @@ -2892,7 +2892,7 @@ int i40e_aq_debug_read_register(struct i40e_hw *hw, int status; if (reg_val == NULL) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_read_reg); @@ -3031,7 +3031,7 @@ int i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer, /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { - status = I40E_ERR_PARAM; + status = -EINVAL; goto i40e_aq_read_nvm_exit; } @@ -3076,7 +3076,7 @@ int i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer, /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { - status = I40E_ERR_PARAM; + status = -EINVAL; goto i40e_aq_erase_nvm_exit; } @@ -3368,7 +3368,7 @@ int i40e_aq_discover_capabilities(struct i40e_hw *hw, if (list_type_opc != i40e_aqc_opc_list_func_capabilities && list_type_opc != i40e_aqc_opc_list_dev_capabilities) { - status = I40E_ERR_PARAM; + status = -EINVAL; goto exit; } @@ -3416,7 +3416,7 @@ int i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer, /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { - status = I40E_ERR_PARAM; + status = -EINVAL; goto i40e_aq_update_nvm_exit; } @@ -3473,7 +3473,7 @@ int i40e_aq_rearrange_nvm(struct i40e_hw *hw, I40E_AQ_NVM_REARRANGE_TO_STRUCT); if (!rearrange_nvm) { - status = I40E_ERR_PARAM; + status = -EINVAL; goto i40e_aq_rearrange_nvm_exit; } @@ -3510,7 +3510,7 @@ int i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type, int status; if (buff_size == 0 || !buff) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_get_mib); /* Indirect Command */ @@ -3558,7 +3558,7 @@ i40e_aq_set_lldp_mib(struct i40e_hw *hw, cmd = (struct i40e_aqc_lldp_set_local_mib *)&desc.params.raw; if (buff_size == 0 || !buff) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_set_local_mib); @@ -3627,7 +3627,7 @@ i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore, if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)) { i40e_debug(hw, I40E_DEBUG_ALL, "Restore LLDP not supported by current FW version.\n"); - return I40E_ERR_DEVICE_NOT_SUPPORTED; + return -ENODEV; } i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore); @@ -3729,7 +3729,7 @@ i40e_aq_set_dcb_parameters(struct i40e_hw *hw, bool dcb_enable, int status; if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE)) - return I40E_ERR_DEVICE_NOT_SUPPORTED; + return -ENODEV; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_dcb_parameters); @@ -3760,7 +3760,7 @@ int i40e_aq_get_cee_dcb_config(struct i40e_hw *hw, int status; if (buff_size == 0 || !buff) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_cee_dcb_cfg); @@ -3848,7 +3848,7 @@ int i40e_aq_delete_element(struct i40e_hw *hw, u16 seid, int status; if (seid == 0) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_delete_element); @@ -3922,7 +3922,7 @@ static int i40e_aq_tx_sched_cmd(struct i40e_hw *hw, u16 seid, cmd_param_flag = false; break; default: - return I40E_ERR_PARAM; + return -EINVAL; } i40e_fill_default_direct_cmd_desc(&desc, opcode); @@ -4148,7 +4148,7 @@ i40e_validate_filter_settings(struct i40e_hw *hw, fcoe_filt_size <<= (u32)settings->fcoe_filt_num; break; default: - return I40E_ERR_PARAM; + return -EINVAL; } switch (settings->fcoe_cntx_num) { @@ -4160,7 +4160,7 @@ i40e_validate_filter_settings(struct i40e_hw *hw, fcoe_cntx_size <<= (u32)settings->fcoe_cntx_num; break; default: - return I40E_ERR_PARAM; + return -EINVAL; } /* Validate PE settings passed */ @@ -4178,7 +4178,7 @@ i40e_validate_filter_settings(struct i40e_hw *hw, case I40E_HASH_FILTER_SIZE_1M: break; default: - return I40E_ERR_PARAM; + return -EINVAL; } switch (settings->pe_cntx_num) { @@ -4194,7 +4194,7 @@ i40e_validate_filter_settings(struct i40e_hw *hw, case I40E_DMA_CNTX_SIZE_256K: break; default: - return I40E_ERR_PARAM; + return -EINVAL; } /* FCHSIZE + FCDSIZE should not be greater than PMFCOEFMAX */ @@ -4202,7 +4202,7 @@ i40e_validate_filter_settings(struct i40e_hw *hw, fcoe_fmax = (val & I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK) >> I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT; if (fcoe_filt_size + fcoe_cntx_size > fcoe_fmax) - return I40E_ERR_INVALID_SIZE; + return -EINVAL; return 0; } @@ -4224,7 +4224,7 @@ int i40e_set_filter_control(struct i40e_hw *hw, u32 val; if (!settings) - return I40E_ERR_PARAM; + return -EINVAL; /* Validate the input settings */ ret = i40e_validate_filter_settings(hw, settings); @@ -4306,7 +4306,7 @@ int i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, int status; if (vsi_seid == 0) - return I40E_ERR_PARAM; + return -EINVAL; if (is_add) { i40e_fill_default_direct_cmd_desc(&desc, @@ -4381,7 +4381,7 @@ static int i40e_aq_alternate_read(struct i40e_hw *hw, int status; if (!reg_val0) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_read); cmd_resp->address0 = cpu_to_le32(reg_addr0); @@ -4517,7 +4517,7 @@ int i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id, int status; if (buff_size == 0 || !buff) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_dump_internals); @@ -4635,7 +4635,7 @@ int i40e_read_phy_register_clause22(struct i40e_hw *hw, u16 reg, u8 phy_addr, u16 *value) { u8 port_num = (u8)hw->func_caps.mdio_port_num; - int status = I40E_ERR_TIMEOUT; + int status = -EIO; u32 command = 0; u16 retry = 1000; @@ -4680,7 +4680,7 @@ int i40e_write_phy_register_clause22(struct i40e_hw *hw, u16 reg, u8 phy_addr, u16 value) { u8 port_num = (u8)hw->func_caps.mdio_port_num; - int status = I40E_ERR_TIMEOUT; + int status = -EIO; u32 command = 0; u16 retry = 1000; @@ -4721,7 +4721,7 @@ int i40e_read_phy_register_clause45(struct i40e_hw *hw, u8 page, u16 reg, u8 phy_addr, u16 *value) { u8 port_num = hw->func_caps.mdio_port_num; - int status = I40E_ERR_TIMEOUT; + int status = -EIO; u32 command = 0; u16 retry = 1000; @@ -4755,7 +4755,7 @@ int i40e_read_phy_register_clause45(struct i40e_hw *hw, (I40E_MDIO_CLAUSE45_STCODE_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); - status = I40E_ERR_TIMEOUT; + status = -EIO; retry = 1000; wr32(hw, I40E_GLGEN_MSCA(port_num), command); do { @@ -4795,7 +4795,7 @@ int i40e_write_phy_register_clause45(struct i40e_hw *hw, u8 page, u16 reg, u8 phy_addr, u16 value) { u8 port_num = hw->func_caps.mdio_port_num; - int status = I40E_ERR_TIMEOUT; + int status = -EIO; u16 retry = 1000; u32 command = 0; @@ -4831,7 +4831,7 @@ int i40e_write_phy_register_clause45(struct i40e_hw *hw, (I40E_MDIO_CLAUSE45_STCODE_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); - status = I40E_ERR_TIMEOUT; + status = -EIO; retry = 1000; wr32(hw, I40E_GLGEN_MSCA(port_num), command); do { @@ -4880,7 +4880,7 @@ int i40e_write_phy_register(struct i40e_hw *hw, phy_addr, value); break; default: - status = I40E_ERR_UNKNOWN_PHY; + status = -EIO; break; } @@ -4919,7 +4919,7 @@ int i40e_read_phy_register(struct i40e_hw *hw, phy_addr, value); break; default: - status = I40E_ERR_UNKNOWN_PHY; + status = -EIO; break; } @@ -5109,7 +5109,7 @@ int i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr, I40E_PHY_COM_REG_PAGE, true, I40E_PHY_LED_PROV_REG_1, ®_val_aq, NULL); - if (status == I40E_SUCCESS) + if (status == 0) *val = (u16)reg_val_aq; return status; } @@ -5204,7 +5204,7 @@ int i40e_aq_rx_ctl_read_register(struct i40e_hw *hw, int status; if (!reg_val) - return I40E_ERR_PARAM; + return -EINVAL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_rx_ctl_reg_read); @@ -5644,7 +5644,7 @@ i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, if (track_id == I40E_DDP_TRACKID_INVALID) { i40e_debug(hw, I40E_DEBUG_PACKAGE, "Invalid track_id\n"); - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; } dev_cnt = profile->device_table_count; @@ -5657,7 +5657,7 @@ i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, if (dev_cnt && i == dev_cnt) { i40e_debug(hw, I40E_DEBUG_PACKAGE, "Device doesn't support DDP\n"); - return I40E_ERR_DEVICE_NOT_SUPPORTED; + return -ENODEV; } I40E_SECTION_TABLE(profile, sec_tbl); @@ -5672,14 +5672,14 @@ i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, sec->section.type == SECTION_TYPE_RB_AQ) { i40e_debug(hw, I40E_DEBUG_PACKAGE, "Not a roll-back package\n"); - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; } } else { if (sec->section.type == SECTION_TYPE_RB_AQ || sec->section.type == SECTION_TYPE_RB_MMIO) { i40e_debug(hw, I40E_DEBUG_PACKAGE, "Not an original package\n"); - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; } } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 90638b67f8dc..f81e744c0fb3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -17,7 +17,7 @@ int i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status) u32 reg; if (!status) - return I40E_ERR_PARAM; + return -EINVAL; reg = rd32(hw, I40E_PRTDCB_GENS); *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >> @@ -508,7 +508,7 @@ int i40e_lldp_to_dcb_config(u8 *lldpmib, u16 type; if (!lldpmib || !dcbcfg) - return I40E_ERR_PARAM; + return -EINVAL; /* set to the start of LLDPDU */ lldpmib += ETH_HLEN; @@ -874,7 +874,7 @@ int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) int ret = 0; if (!hw->func_caps.dcb) - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; /* Read LLDP NVM area */ if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) { @@ -885,7 +885,7 @@ int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) else if (hw->mac.type == I40E_MAC_X722) offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET; else - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; ret = i40e_read_nvm_module_data(hw, I40E_SR_EMP_SR_SETTINGS_PTR, @@ -897,7 +897,7 @@ int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) ret = i40e_read_lldp_cfg(hw, &lldp_cfg); } if (ret) - return I40E_ERR_NOT_READY; + return -EBUSY; /* Get the LLDP AdminStatus for the current port */ adminstatus = lldp_cfg.adminstatus >> (hw->port * 4); @@ -906,7 +906,7 @@ int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) /* LLDP agent disabled */ if (!adminstatus) { hw->dcbx_status = I40E_DCBX_STATUS_DISABLED; - return I40E_ERR_NOT_READY; + return -EBUSY; } /* Get DCBX status */ @@ -922,7 +922,7 @@ int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) if (ret) return ret; } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) { - return I40E_ERR_NOT_READY; + return -EBUSY; } /* Configure the LLDP MIB change event */ @@ -949,7 +949,7 @@ i40e_get_fw_lldp_status(struct i40e_hw *hw, int ret; if (!lldp_status) - return I40E_ERR_PARAM; + return -EINVAL; /* Allocate buffer for the LLDPDU */ ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); @@ -1299,7 +1299,7 @@ int i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen, sizeof(tlv->typelength) + length); } while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU); *miblen = offset; - return I40E_SUCCESS; + return 0; } /** @@ -1957,7 +1957,7 @@ int i40e_read_lldp_cfg(struct i40e_hw *hw, u32 mem; if (!lldp_cfg) - return I40E_ERR_PARAM; + return -EINVAL; ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (ret) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ddp.c b/drivers/net/ethernet/intel/i40e/i40e_ddp.c index 7e8183762fd9..969120587cad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ddp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ddp.c @@ -344,7 +344,7 @@ int i40e_ddp_load(struct net_device *netdev, const u8 *data, size_t size, if (is_add) { status = i40e_write_profile(&pf->hw, profile_hdr, track_id); if (status) { - if (status == I40E_ERR_DEVICE_NOT_SUPPORTED) { + if (status == -ENODEV) { netdev_err(netdev, "Profile is not supported by the device."); return -EPERM; diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 62497f5565c5..1a497cb07710 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1309,7 +1309,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ret = i40e_asq_send_command(&pf->hw, desc, NULL, 0, NULL); if (!ret) { dev_info(&pf->pdev->dev, "AQ command sent Status : Success\n"); - } else if (ret == I40E_ERR_ADMIN_QUEUE_ERROR) { + } else if (ret == -EIO) { dev_info(&pf->pdev->dev, "AQ command send failed Opcode %x AQ Error: %d\n", desc->opcode, pf->hw.aq.asq_last_status); @@ -1370,7 +1370,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, buffer_len, NULL); if (!ret) { dev_info(&pf->pdev->dev, "AQ command sent Status : Success\n"); - } else if (ret == I40E_ERR_ADMIN_QUEUE_ERROR) { + } else if (ret == -EIO) { dev_info(&pf->pdev->dev, "AQ command send failed Opcode %x AQ Error: %d\n", desc->opcode, pf->hw.aq.asq_last_status); diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c index 97fe1787a8f4..b1ad7c4259b9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.c +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c @@ -28,7 +28,7 @@ static int i40e_diag_reg_pattern_test(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_DIAG, "%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n", __func__, reg, pat, val); - return I40E_ERR_DIAG_TEST_FAILED; + return -EIO; } } @@ -38,7 +38,7 @@ static int i40e_diag_reg_pattern_test(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_DIAG, "%s: reg restore test failed - reg 0x%08x orig_val 0x%08x val 0x%08x\n", __func__, reg, orig_val, val); - return I40E_ERR_DIAG_TEST_FAILED; + return -EIO; } return 0; @@ -127,5 +127,5 @@ int i40e_diag_eeprom_test(struct i40e_hw *hw) BIT(I40E_SR_CONTROL_WORD_1_SHIFT))) return i40e_validate_nvm_checksum(hw, NULL); else - return I40E_ERR_DIAG_TEST_FAILED; + return -EIO; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index afc4fa8c66af..bd1321bf7e26 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -5699,8 +5699,8 @@ static int i40e_set_eee(struct net_device *netdev, struct ethtool_eee *edata) struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; - int status = I40E_SUCCESS; __le16 eee_capability; + int status = 0; /* Deny parameters we don't support */ if (i40e_is_eee_param_supported(netdev, edata)) diff --git a/drivers/net/ethernet/intel/i40e/i40e_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_hmc.c index 46f7950a0049..96ee63aca7a1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_hmc.c @@ -4,7 +4,6 @@ #include "i40e.h" #include "i40e_osdep.h" #include "i40e_register.h" -#include "i40e_status.h" #include "i40e_alloc.h" #include "i40e_hmc.h" #include "i40e_type.h" @@ -26,18 +25,18 @@ int i40e_add_sd_table_entry(struct i40e_hw *hw, enum i40e_memory_type mem_type __attribute__((unused)); struct i40e_hmc_sd_entry *sd_entry; bool dma_mem_alloc_done = false; - int ret_code = I40E_SUCCESS; struct i40e_dma_mem mem; + int ret_code = 0; u64 alloc_len; if (NULL == hmc_info->sd_table.sd_entry) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_entry\n"); goto exit; } if (sd_index >= hmc_info->sd_table.sd_cnt) { - ret_code = I40E_ERR_INVALID_SD_INDEX; + ret_code = -EINVAL; hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_index\n"); goto exit; } @@ -121,7 +120,7 @@ int i40e_add_pd_table_entry(struct i40e_hw *hw, u64 *pd_addr; if (pd_index / I40E_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) { - ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX; + ret_code = -EINVAL; hw_dbg(hw, "i40e_add_pd_table_entry: bad pd_index\n"); goto exit; } @@ -200,13 +199,13 @@ int i40e_remove_pd_bp(struct i40e_hw *hw, sd_idx = idx / I40E_HMC_PD_CNT_IN_SD; rel_pd_idx = idx % I40E_HMC_PD_CNT_IN_SD; if (sd_idx >= hmc_info->sd_table.sd_cnt) { - ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX; + ret_code = -EINVAL; hw_dbg(hw, "i40e_remove_pd_bp: bad idx\n"); goto exit; } sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; if (I40E_SD_TYPE_PAGED != sd_entry->entry_type) { - ret_code = I40E_ERR_INVALID_SD_TYPE; + ret_code = -EINVAL; hw_dbg(hw, "i40e_remove_pd_bp: wrong sd_entry type\n"); goto exit; } @@ -251,7 +250,7 @@ int i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info, sd_entry = &hmc_info->sd_table.sd_entry[idx]; I40E_DEC_BP_REFCNT(&sd_entry->u.bp); if (sd_entry->u.bp.ref_cnt) { - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto exit; } I40E_DEC_SD_REFCNT(&hmc_info->sd_table); @@ -276,7 +275,7 @@ int i40e_remove_sd_bp_new(struct i40e_hw *hw, struct i40e_hmc_sd_entry *sd_entry; if (!is_pf) - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; /* get the entry and decrease its ref counter */ sd_entry = &hmc_info->sd_table.sd_entry[idx]; @@ -299,7 +298,7 @@ int i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info, sd_entry = &hmc_info->sd_table.sd_entry[idx]; if (sd_entry->u.pd_table.ref_cnt) { - ret_code = I40E_ERR_NOT_READY; + ret_code = -EBUSY; goto exit; } @@ -325,7 +324,7 @@ int i40e_remove_pd_page_new(struct i40e_hw *hw, struct i40e_hmc_sd_entry *sd_entry; if (!is_pf) - return I40E_NOT_SUPPORTED; + return -EOPNOTSUPP; sd_entry = &hmc_info->sd_table.sd_entry[idx]; I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_PAGED); diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c index 40c101f286d1..474365bf0648 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c @@ -111,7 +111,7 @@ int i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, /* validate values requested by driver don't exceed HMC capacity */ if (txq_num > obj->max_cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", txq_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; @@ -134,7 +134,7 @@ int i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, /* validate values requested by driver don't exceed HMC capacity */ if (rxq_num > obj->max_cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", rxq_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; @@ -157,7 +157,7 @@ int i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, /* validate values requested by driver don't exceed HMC capacity */ if (fcoe_cntx_num > obj->max_cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", fcoe_cntx_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; @@ -180,7 +180,7 @@ int i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, /* validate values requested by driver don't exceed HMC capacity */ if (fcoe_filt_num > obj->max_cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n", fcoe_filt_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; @@ -289,30 +289,30 @@ static int i40e_create_lan_hmc_object(struct i40e_hw *hw, u32 i, j; if (NULL == info) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_create_lan_hmc_object: bad info ptr\n"); goto exit; } if (NULL == info->hmc_info) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_create_lan_hmc_object: bad hmc_info ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_create_lan_hmc_object: bad signature\n"); goto exit; } if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; + ret_code = -EINVAL; hw_dbg(hw, "i40e_create_lan_hmc_object: returns error %d\n", ret_code); goto exit; } if ((info->start_idx + info->count) > info->hmc_info->hmc_obj[info->rsrc_type].cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_create_lan_hmc_object: returns error %d\n", ret_code); goto exit; @@ -324,8 +324,8 @@ static int i40e_create_lan_hmc_object(struct i40e_hw *hw, &sd_idx, &sd_lmt); if (sd_idx >= info->hmc_info->sd_table.sd_cnt || sd_lmt > info->hmc_info->sd_table.sd_cnt) { - ret_code = I40E_ERR_INVALID_SD_INDEX; - goto exit; + ret_code = -EINVAL; + goto exit; } /* find pd index */ I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, @@ -393,7 +393,7 @@ static int i40e_create_lan_hmc_object(struct i40e_hw *hw, j, sd_entry->entry_type); break; default: - ret_code = I40E_ERR_INVALID_SD_TYPE; + ret_code = -EINVAL; goto exit; } } @@ -417,7 +417,7 @@ exit_sd_error: i40e_remove_sd_bp(hw, info->hmc_info, (j - 1)); break; default: - ret_code = I40E_ERR_INVALID_SD_TYPE; + ret_code = -EINVAL; break; } j--; @@ -474,7 +474,7 @@ try_type_paged: break; default: /* unsupported type */ - ret_code = I40E_ERR_INVALID_SD_TYPE; + ret_code = -EINVAL; hw_dbg(hw, "i40e_configure_lan_hmc: Unknown SD type: %d\n", ret_code); goto configure_lan_hmc_out; @@ -530,34 +530,34 @@ static int i40e_delete_lan_hmc_object(struct i40e_hw *hw, u32 i, j; if (NULL == info) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: bad info ptr\n"); goto exit; } if (NULL == info->hmc_info) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: bad info->hmc_info ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: bad hmc_info->signature\n"); goto exit; } if (NULL == info->hmc_info->sd_table.sd_entry) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: bad sd_entry\n"); goto exit; } if (NULL == info->hmc_info->hmc_obj) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: bad hmc_info->hmc_obj\n"); goto exit; } if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: returns error %d\n", ret_code); goto exit; @@ -565,7 +565,7 @@ static int i40e_delete_lan_hmc_object(struct i40e_hw *hw, if ((info->start_idx + info->count) > info->hmc_info->hmc_obj[info->rsrc_type].cnt) { - ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; + ret_code = -EINVAL; hw_dbg(hw, "i40e_delete_hmc_object: returns error %d\n", ret_code); goto exit; @@ -599,7 +599,7 @@ static int i40e_delete_lan_hmc_object(struct i40e_hw *hw, &sd_idx, &sd_lmt); if (sd_idx >= info->hmc_info->sd_table.sd_cnt || sd_lmt > info->hmc_info->sd_table.sd_cnt) { - ret_code = I40E_ERR_INVALID_SD_INDEX; + ret_code = -EINVAL; goto exit; } @@ -987,29 +987,29 @@ int i40e_hmc_get_object_va(struct i40e_hw *hw, u8 **object_base, int ret_code = 0; if (NULL == hmc_info) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_hmc_get_object_va: bad hmc_info ptr\n"); goto exit; } if (NULL == hmc_info->hmc_obj) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n"); goto exit; } if (NULL == object_base) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_hmc_get_object_va: bad object_base ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) { - ret_code = I40E_ERR_BAD_PTR; + ret_code = -EINVAL; hw_dbg(hw, "i40e_hmc_get_object_va: bad hmc_info->signature\n"); goto exit; } if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) { hw_dbg(hw, "i40e_hmc_get_object_va: returns error %d\n", ret_code); - ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; + ret_code = -EINVAL; goto exit; } /* find sd index and limit */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3d0d6974c2a7..a5ba873c3b24 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5709,7 +5709,7 @@ int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset) int ret; if (!vsi) - return I40E_ERR_PARAM; + return -EINVAL; pf = vsi->back; hw = &pf->hw; @@ -7153,7 +7153,7 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) */ if (pf->hw_features & I40E_HW_NO_DCB_SUPPORT) { dev_info(&pf->pdev->dev, "DCB is not supported.\n"); - err = I40E_NOT_SUPPORTED; + err = -EOPNOTSUPP; goto out; } if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) { @@ -7463,7 +7463,7 @@ static int i40e_force_link_state(struct i40e_pf *pf, bool is_up) if (pf->flags & I40E_FLAG_TOTAL_PORT_SHUTDOWN_ENABLED) non_zero_phy_type = true; else if (is_up && abilities.phy_type != 0 && abilities.link_speed != 0) - return I40E_SUCCESS; + return 0; /* To force link we need to set bits for all supported PHY types, * but there are now more than 32, so we need to split the bitmap @@ -7514,7 +7514,7 @@ static int i40e_force_link_state(struct i40e_pf *pf, bool is_up) i40e_aq_set_link_restart_an(hw, is_up, NULL); - return I40E_SUCCESS; + return 0; } /** @@ -8361,7 +8361,7 @@ int i40e_add_del_cloud_filter(struct i40e_vsi *vsi, }; if (filter->flags >= ARRAY_SIZE(flag_table)) - return I40E_ERR_CONFIG; + return -EIO; memset(&cld_filter, 0, sizeof(cld_filter)); @@ -8575,7 +8575,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad ether dest mask %pM\n", match.mask->dst); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -8585,7 +8585,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad ether src mask %pM\n", match.mask->src); - return I40E_ERR_CONFIG; + return -EIO; } } ether_addr_copy(filter->dst_mac, match.key->dst); @@ -8603,7 +8603,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad vlan mask 0x%04x\n", match.mask->vlan_id); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -8627,7 +8627,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad ip dst mask %pI4b\n", &match.mask->dst); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -8637,13 +8637,13 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad ip src mask %pI4b\n", &match.mask->src); - return I40E_ERR_CONFIG; + return -EIO; } } if (field_flags & I40E_CLOUD_FIELD_TEN_ID) { dev_err(&pf->pdev->dev, "Tenant id not allowed for ip filter\n"); - return I40E_ERR_CONFIG; + return -EIO; } filter->dst_ipv4 = match.key->dst; filter->src_ipv4 = match.key->src; @@ -8661,7 +8661,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, ipv6_addr_loopback(&match.key->src)) { dev_err(&pf->pdev->dev, "Bad ipv6, addr is LOOPBACK\n"); - return I40E_ERR_CONFIG; + return -EIO; } if (!ipv6_addr_any(&match.mask->dst) || !ipv6_addr_any(&match.mask->src)) @@ -8683,7 +8683,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad src port mask 0x%04x\n", be16_to_cpu(match.mask->src)); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -8693,7 +8693,7 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, } else { dev_err(&pf->pdev->dev, "Bad dst port mask 0x%04x\n", be16_to_cpu(match.mask->dst)); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -9901,11 +9901,11 @@ static void i40e_link_event(struct i40e_pf *pf) status = i40e_get_link_status(&pf->hw, &new_link); /* On success, disable temp link polling */ - if (status == I40E_SUCCESS) { + if (status == 0) { clear_bit(__I40E_TEMP_LINK_POLLING, pf->state); } else { /* Enable link polling temporarily until i40e_get_link_status - * returns I40E_SUCCESS + * returns 0 */ set_bit(__I40E_TEMP_LINK_POLLING, pf->state); dev_dbg(&pf->pdev->dev, "couldn't get link state, status: %d\n", @@ -10159,7 +10159,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) do { ret = i40e_clean_arq_element(hw, &event, &pending); - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) + if (ret == -EALREADY) break; else if (ret) { dev_info(&pf->pdev->dev, "ARQ event error %d\n", ret); @@ -12569,7 +12569,7 @@ int i40e_commit_partition_bw_setting(struct i40e_pf *pf) dev_info(&pf->pdev->dev, "Commit BW only works on partition 1! This is partition %d", pf->hw.partition_id); - ret = I40E_NOT_SUPPORTED; + ret = -EOPNOTSUPP; goto bw_commit_out; } @@ -12651,10 +12651,10 @@ static bool i40e_is_total_port_shutdown_enabled(struct i40e_pf *pf) #define I40E_LINK_BEHAVIOR_WORD_LENGTH 0x1 #define I40E_LINK_BEHAVIOR_OS_FORCED_ENABLED BIT(0) #define I40E_LINK_BEHAVIOR_PORT_BIT_LENGTH 4 - int read_status = I40E_SUCCESS; u16 sr_emp_sr_settings_ptr = 0; u16 features_enable = 0; u16 link_behavior = 0; + int read_status = 0; bool ret = false; read_status = i40e_read_nvm_word(&pf->hw, @@ -15462,12 +15462,12 @@ static int i40e_pf_loop_reset(struct i40e_pf *pf) int ret; ret = i40e_pf_reset(hw); - while (ret != I40E_SUCCESS && time_before(jiffies, time_end)) { + while (ret != 0 && time_before(jiffies, time_end)) { usleep_range(10000, 20000); ret = i40e_pf_reset(hw); } - if (ret == I40E_SUCCESS) + if (ret == 0) pf->pfr_count++; else dev_info(&pf->pdev->dev, "PF reset failed: %d\n", ret); @@ -15510,10 +15510,10 @@ static int i40e_handle_resets(struct i40e_pf *pf) const int pfr = i40e_pf_loop_reset(pf); const bool is_empr = i40e_check_fw_empr(pf); - if (is_empr || pfr != I40E_SUCCESS) + if (is_empr || pfr != 0) dev_crit(&pf->pdev->dev, "Entering recovery mode due to repeated FW resets. This may take several minutes. Refer to the Intel(R) Ethernet Adapters and Devices User Guide.\n"); - return is_empr ? I40E_ERR_RESET_FAILED : pfr; + return is_empr ? -EIO : pfr; } /** @@ -15806,7 +15806,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = i40e_init_adminq(hw); if (err) { - if (err == I40E_ERR_FIRMWARE_API_VERSION) + if (err == -EIO) dev_info(&pdev->dev, "The driver for the device stopped because the NVM image v%u.%u is newer than expected v%u.%u. You must install the most recent version of the network driver.\n", hw->aq.api_maj_ver, diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 9da0c87f0328..4bb300fbb777 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -37,7 +37,7 @@ int i40e_init_nvm(struct i40e_hw *hw) nvm->blank_nvm_mode = false; } else { /* Blank programming mode */ nvm->blank_nvm_mode = true; - ret_code = I40E_ERR_NVM_BLANK_MODE; + ret_code = -EIO; i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n"); } @@ -111,8 +111,8 @@ i40e_i40e_acquire_nvm_exit: **/ void i40e_release_nvm(struct i40e_hw *hw) { - int ret_code = I40E_SUCCESS; u32 total_delay = 0; + int ret_code = 0; if (hw->nvm.blank_nvm_mode) return; @@ -122,7 +122,7 @@ void i40e_release_nvm(struct i40e_hw *hw) /* there are some rare cases when trying to release the resource * results in an admin Q timeout, so handle them correctly */ - while ((ret_code == I40E_ERR_ADMIN_QUEUE_TIMEOUT) && + while ((ret_code == -EIO) && (total_delay < hw->aq.asq_cmd_timeout)) { usleep_range(1000, 2000); ret_code = i40e_aq_release_resource(hw, @@ -140,7 +140,7 @@ void i40e_release_nvm(struct i40e_hw *hw) **/ static int i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) { - int ret_code = I40E_ERR_TIMEOUT; + int ret_code = -EIO; u32 srctl, wait_cnt; /* Poll the I40E_GLNVM_SRCTL until the done bit is set */ @@ -152,7 +152,7 @@ static int i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) } udelay(5); } - if (ret_code == I40E_ERR_TIMEOUT) + if (ret_code == -EIO) i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set"); return ret_code; } @@ -168,14 +168,14 @@ static int i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) static int i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, u16 *data) { - int ret_code = I40E_ERR_TIMEOUT; + int ret_code = -EIO; u32 sr_reg; if (offset >= hw->nvm.sr_size) { i40e_debug(hw, I40E_DEBUG_NVM, "NVM read error: offset %d beyond Shadow RAM limit %d\n", offset, hw->nvm.sr_size); - ret_code = I40E_ERR_PARAM; + ret_code = -EINVAL; goto read_nvm_exit; } @@ -222,7 +222,7 @@ static int i40e_read_nvm_aq(struct i40e_hw *hw, bool last_command) { struct i40e_asq_cmd_details cmd_details; - int ret_code = I40E_ERR_NVM; + int ret_code = -EIO; memset(&cmd_details, 0, sizeof(cmd_details)); cmd_details.wb_desc = &hw->nvm_wb_desc; @@ -267,7 +267,7 @@ static int i40e_read_nvm_aq(struct i40e_hw *hw, static int i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, u16 *data) { - int ret_code = I40E_ERR_TIMEOUT; + int ret_code = -EIO; ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true); *data = le16_to_cpu(*(__le16 *)data); @@ -348,7 +348,7 @@ int i40e_read_nvm_module_data(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_ALL, "Reading nvm word failed.Error code: %d.\n", status); - return I40E_ERR_NVM; + return -EIO; } } #define I40E_NVM_INVALID_PTR_VAL 0x7FFF @@ -358,7 +358,7 @@ int i40e_read_nvm_module_data(struct i40e_hw *hw, if (ptr_value == I40E_NVM_INVALID_PTR_VAL || ptr_value == I40E_NVM_INVALID_VAL) { i40e_debug(hw, I40E_DEBUG_ALL, "Pointer not initialized.\n"); - return I40E_ERR_BAD_PTR; + return -EINVAL; } /* Check whether the module is in SR mapped area or outside */ @@ -367,7 +367,7 @@ int i40e_read_nvm_module_data(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_ALL, "Reading nvm data failed. Pointer points outside of the Shared RAM mapped area.\n"); - return I40E_ERR_PARAM; + return -EINVAL; } else { /* Read from the Shadow RAM */ @@ -377,7 +377,7 @@ int i40e_read_nvm_module_data(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_ALL, "Reading nvm word failed.Error code: %d.\n", status); - return I40E_ERR_NVM; + return -EIO; } offset = ptr_value + module_offset + specific_ptr + @@ -549,7 +549,7 @@ static int i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, bool last_command) { struct i40e_asq_cmd_details cmd_details; - int ret_code = I40E_ERR_NVM; + int ret_code = -EIO; memset(&cmd_details, 0, sizeof(cmd_details)); cmd_details.wb_desc = &hw->nvm_wb_desc; @@ -614,7 +614,7 @@ static int i40e_calc_nvm_checksum(struct i40e_hw *hw, /* read pointer to VPD area */ ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module); if (ret_code) { - ret_code = I40E_ERR_NVM_CHECKSUM; + ret_code = -EIO; goto i40e_calc_nvm_checksum_exit; } @@ -622,7 +622,7 @@ static int i40e_calc_nvm_checksum(struct i40e_hw *hw, ret_code = __i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, &pcie_alt_module); if (ret_code) { - ret_code = I40E_ERR_NVM_CHECKSUM; + ret_code = -EIO; goto i40e_calc_nvm_checksum_exit; } @@ -636,7 +636,7 @@ static int i40e_calc_nvm_checksum(struct i40e_hw *hw, ret_code = __i40e_read_nvm_buffer(hw, i, &words, data); if (ret_code) { - ret_code = I40E_ERR_NVM_CHECKSUM; + ret_code = -EIO; goto i40e_calc_nvm_checksum_exit; } } @@ -724,7 +724,7 @@ int i40e_validate_nvm_checksum(struct i40e_hw *hw, * calculated checksum */ if (checksum_local != checksum_sr) - ret_code = I40E_ERR_NVM_CHECKSUM; + ret_code = -EIO; /* If the user cares, return the calculated checksum */ if (checksum) @@ -839,7 +839,7 @@ int i40e_nvmupd_command(struct i40e_hw *hw, if (upd_cmd == I40E_NVMUPD_STATUS) { if (!cmd->data_size) { *perrno = -EFAULT; - return I40E_ERR_BUF_TOO_SHORT; + return -EINVAL; } bytes[0] = hw->nvmupd_state; @@ -896,7 +896,7 @@ int i40e_nvmupd_command(struct i40e_hw *hw, break; } - status = I40E_ERR_NOT_READY; + status = -EBUSY; *perrno = -EBUSY; break; @@ -904,7 +904,7 @@ int i40e_nvmupd_command(struct i40e_hw *hw, /* invalid state, should never happen */ i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: no such state %d\n", hw->nvmupd_state); - status = I40E_NOT_SUPPORTED; + status = -EOPNOTSUPP; *perrno = -ESRCH; break; } @@ -1045,7 +1045,7 @@ static int i40e_nvmupd_state_init(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in init state\n", i40e_nvm_update_state_str[upd_cmd]); - status = I40E_ERR_NVM; + status = -EIO; *perrno = -ESRCH; break; } @@ -1087,7 +1087,7 @@ static int i40e_nvmupd_state_reading(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in reading state.\n", i40e_nvm_update_state_str[upd_cmd]); - status = I40E_NOT_SUPPORTED; + status = -EOPNOTSUPP; *perrno = -ESRCH; break; } @@ -1174,7 +1174,7 @@ retry: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in writing state.\n", i40e_nvm_update_state_str[upd_cmd]); - status = I40E_NOT_SUPPORTED; + status = -EOPNOTSUPP; *perrno = -ESRCH; break; } @@ -1398,7 +1398,7 @@ static int i40e_nvmupd_exec_aq(struct i40e_hw *hw, "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n", cmd->data_size, aq_desc_len); *perrno = -EINVAL; - return I40E_ERR_PARAM; + return -EINVAL; } aq_desc = (struct i40e_aq_desc *)bytes; @@ -1473,7 +1473,7 @@ static int i40e_nvmupd_get_aq_result(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n", __func__, cmd->offset, aq_total_len); *perrno = -EINVAL; - return I40E_ERR_PARAM; + return -EINVAL; } /* check copylength range */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index c37abbb3cd06..8a26811140b4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -1132,7 +1132,7 @@ int i40e_ptp_alloc_pins(struct i40e_pf *pf) if (!pf->ptp_pins) { dev_warn(&pf->pdev->dev, "Cannot allocate memory for PTP pins structure.\n"); - return -I40E_ERR_NO_MEMORY; + return -ENOMEM; } pf->ptp_pins->sdp3_2 = off; diff --git a/drivers/net/ethernet/intel/i40e/i40e_status.h b/drivers/net/ethernet/intel/i40e/i40e_status.h deleted file mode 100644 index 4d2782e76038..000000000000 --- a/drivers/net/ethernet/intel/i40e/i40e_status.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2013 - 2018 Intel Corporation. */ - -#ifndef _I40E_STATUS_H_ -#define _I40E_STATUS_H_ - -/* Error Codes */ -enum i40e_status_code { - I40E_SUCCESS = 0, - I40E_ERR_NVM = -1, - I40E_ERR_NVM_CHECKSUM = -2, - I40E_ERR_CONFIG = -4, - I40E_ERR_PARAM = -5, - I40E_ERR_UNKNOWN_PHY = -7, - I40E_ERR_INVALID_MAC_ADDR = -10, - I40E_ERR_DEVICE_NOT_SUPPORTED = -11, - I40E_ERR_RESET_FAILED = -15, - I40E_ERR_NO_AVAILABLE_VSI = -17, - I40E_ERR_NO_MEMORY = -18, - I40E_ERR_BAD_PTR = -19, - I40E_ERR_INVALID_SIZE = -26, - I40E_ERR_QUEUE_EMPTY = -32, - I40E_ERR_TIMEOUT = -37, - I40E_ERR_INVALID_SD_INDEX = -45, - I40E_ERR_INVALID_PAGE_DESC_INDEX = -46, - I40E_ERR_INVALID_SD_TYPE = -47, - I40E_ERR_INVALID_HMC_OBJ_INDEX = -49, - I40E_ERR_INVALID_HMC_OBJ_COUNT = -50, - I40E_ERR_ADMIN_QUEUE_ERROR = -53, - I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54, - I40E_ERR_BUF_TOO_SHORT = -55, - I40E_ERR_ADMIN_QUEUE_FULL = -56, - I40E_ERR_ADMIN_QUEUE_NO_WORK = -57, - I40E_ERR_NVM_BLANK_MODE = -59, - I40E_ERR_NOT_IMPLEMENTED = -60, - I40E_ERR_DIAG_TEST_FAILED = -62, - I40E_ERR_NOT_READY = -63, - I40E_NOT_SUPPORTED = -64, - I40E_ERR_FIRMWARE_API_VERSION = -65, - I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR = -66, -}; - -#endif /* _I40E_STATUS_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 388c3d36d96a..5f61546f50d8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -4,7 +4,6 @@ #ifndef _I40E_TYPE_H_ #define _I40E_TYPE_H_ -#include "i40e_status.h" #include "i40e_osdep.h" #include "i40e_register.h" #include "i40e_adminq.h" diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 398fb4854cbe..98aca9f8b602 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1346,14 +1346,14 @@ static int i40e_config_vf_promiscuous_mode(struct i40e_vf *vf, bool alluni) { struct i40e_pf *pf = vf->pf; - int aq_ret = I40E_SUCCESS; struct i40e_vsi *vsi; + int aq_ret = 0; u16 num_vlans; s16 *vl; vsi = i40e_find_vsi_from_id(pf, vsi_id); if (!i40e_vc_isvalid_vsi_id(vf, vsi_id) || !vsi) - return I40E_ERR_PARAM; + return -EINVAL; if (vf->port_vlan_id) { aq_ret = i40e_set_vsi_promisc(vf, vsi->seid, allmulti, @@ -1363,7 +1363,7 @@ static int i40e_config_vf_promiscuous_mode(struct i40e_vf *vf, i40e_get_vlan_list_sync(vsi, &num_vlans, &vl); if (!vl) - return I40E_ERR_NO_MEMORY; + return -ENOMEM; aq_ret = i40e_set_vsi_promisc(vf, vsi->seid, allmulti, alluni, vl, num_vlans); @@ -2037,7 +2037,7 @@ static int i40e_vc_get_version_msg(struct i40e_vf *vf, u8 *msg) if (VF_IS_V10(&vf->vf_ver)) info.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS; return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION, - I40E_SUCCESS, (u8 *)&info, + 0, (u8 *)&info, sizeof(struct virtchnl_version_info)); } @@ -2099,14 +2099,14 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) int ret; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } len = struct_size(vfres, vsi_res, num_vsis); vfres = kzalloc(len, GFP_KERNEL); if (!vfres) { - aq_ret = I40E_ERR_NO_MEMORY; + aq_ret = -ENOMEM; len = 0; goto err; } @@ -2159,7 +2159,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) dev_err(&pf->pdev->dev, "VF %d requested polling mode: this feature is supported only when the device is running in single function per port (SFP) mode\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_POLLING; @@ -2227,7 +2227,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) { @@ -2243,12 +2243,12 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) } if (info->flags > I40E_MAX_VF_PROMISC_FLAGS) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } if (!i40e_vc_isvalid_vsi_id(vf, info->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } @@ -2315,17 +2315,17 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_isvalid_vsi_id(vf, qci->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (qci->num_queue_pairs > I40E_MAX_VF_QUEUES) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -2333,7 +2333,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) for (i = 0; i < vf->num_tc; i++) num_qps_all += vf->ch[i].num_qps; if (num_qps_all != qci->num_queue_pairs) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } } @@ -2346,7 +2346,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) if (!vf->adq_enabled) { if (!i40e_vc_isvalid_queue_id(vf, vsi_id, qpi->txq.queue_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -2355,14 +2355,14 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) if (qpi->txq.vsi_id != qci->vsi_id || qpi->rxq.vsi_id != qci->vsi_id || qpi->rxq.queue_id != vsi_queue_id) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } } if (vf->adq_enabled) { if (idx >= ARRAY_SIZE(vf->ch)) { - aq_ret = I40E_ERR_NO_AVAILABLE_VSI; + aq_ret = -ENODEV; goto error_param; } vsi_id = vf->ch[idx].vsi_id; @@ -2372,7 +2372,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) &qpi->rxq) || i40e_config_vsi_tx_queue(vf, vsi_id, vsi_queue_id, &qpi->txq)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -2383,7 +2383,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) */ if (vf->adq_enabled) { if (idx >= ARRAY_SIZE(vf->ch)) { - aq_ret = I40E_ERR_NO_AVAILABLE_VSI; + aq_ret = -ENODEV; goto error_param; } if (j == (vf->ch[idx].num_qps - 1)) { @@ -2406,7 +2406,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) vsi->num_queue_pairs = vf->ch[i].num_qps; if (i40e_update_adq_vsi_queues(vsi, i)) { - aq_ret = I40E_ERR_CONFIG; + aq_ret = -EIO; goto error_param; } } @@ -2464,13 +2464,13 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) int i; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (irqmap_info->num_vectors > vf->pf->hw.func_caps.num_msix_vectors_vf) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -2479,18 +2479,18 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) /* validate msg params */ if (!i40e_vc_isvalid_vector_id(vf, map->vector_id) || !i40e_vc_isvalid_vsi_id(vf, map->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } vsi_id = map->vsi_id; if (i40e_validate_queue_map(vf, vsi_id, map->rxq_map)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (i40e_validate_queue_map(vf, vsi_id, map->txq_map)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -2579,29 +2579,29 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg) int i; if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_isvalid_vsi_id(vf, vqs->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_validate_vqs_bitmaps(vqs)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } /* Use the queue bit map sent by the VF */ if (i40e_ctrl_vf_rx_rings(pf->vsi[vf->lan_vsi_idx], vqs->rx_queues, true)) { - aq_ret = I40E_ERR_TIMEOUT; + aq_ret = -EIO; goto error_param; } if (i40e_ctrl_vf_tx_rings(pf->vsi[vf->lan_vsi_idx], vqs->tx_queues, true)) { - aq_ret = I40E_ERR_TIMEOUT; + aq_ret = -EIO; goto error_param; } @@ -2610,7 +2610,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg) /* zero belongs to LAN VSI */ for (i = 1; i < vf->num_tc; i++) { if (i40e_vsi_start_rings(pf->vsi[vf->ch[i].vsi_idx])) - aq_ret = I40E_ERR_TIMEOUT; + aq_ret = -EIO; } } @@ -2636,29 +2636,29 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_isvalid_vsi_id(vf, vqs->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_validate_vqs_bitmaps(vqs)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } /* Use the queue bit map sent by the VF */ if (i40e_ctrl_vf_tx_rings(pf->vsi[vf->lan_vsi_idx], vqs->tx_queues, false)) { - aq_ret = I40E_ERR_TIMEOUT; + aq_ret = -EIO; goto error_param; } if (i40e_ctrl_vf_rx_rings(pf->vsi[vf->lan_vsi_idx], vqs->rx_queues, false)) { - aq_ret = I40E_ERR_TIMEOUT; + aq_ret = -EIO; goto error_param; } error_param: @@ -2790,18 +2790,18 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg) memset(&stats, 0, sizeof(struct i40e_eth_stats)); if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (!i40e_vc_isvalid_vsi_id(vf, vqs->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } vsi = pf->vsi[vf->lan_vsi_idx]; if (!vsi) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } i40e_update_eth_stats(vsi); @@ -2862,7 +2862,7 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, is_zero_ether_addr(addr)) { dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", addr); - return I40E_ERR_INVALID_MAC_ADDR; + return -EINVAL; } /* If the host VMM administrator has set the VF MAC address @@ -2998,7 +2998,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { - ret = I40E_ERR_PARAM; + ret = -EINVAL; goto error_param; } @@ -3027,7 +3027,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) dev_err(&pf->pdev->dev, "Unable to add MAC filter %pM for VF %d\n", al->list[i].addr, vf->vf_id); - ret = I40E_ERR_PARAM; + ret = -EINVAL; spin_unlock_bh(&vsi->mac_filter_hash_lock); goto error_param; } @@ -3067,7 +3067,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { - ret = I40E_ERR_PARAM; + ret = -EINVAL; goto error_param; } @@ -3076,7 +3076,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) is_zero_ether_addr(al->list[i].addr)) { dev_err(&pf->pdev->dev, "Invalid MAC addr %pM for VF %d\n", al->list[i].addr, vf->vf_id); - ret = I40E_ERR_INVALID_MAC_ADDR; + ret = -EINVAL; goto error_param; } if (ether_addr_equal(al->list[i].addr, vf->default_lan_addr.addr)) @@ -3088,7 +3088,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) if (i40e_del_mac_filter(vsi, al->list[i].addr)) { - ret = I40E_ERR_INVALID_MAC_ADDR; + ret = -EINVAL; spin_unlock_bh(&vsi->mac_filter_hash_lock); goto error_param; } @@ -3149,13 +3149,13 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg) } if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } for (i = 0; i < vfl->num_elements; i++) { if (vfl->vlan_id[i] > I40E_MAX_VLANID) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; dev_err(&pf->pdev->dev, "invalid VF VLAN id %d\n", vfl->vlan_id[i]); goto error_param; @@ -3163,7 +3163,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg) } vsi = pf->vsi[vf->lan_vsi_idx]; if (vsi->info.pvid) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -3214,13 +3214,13 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } for (i = 0; i < vfl->num_elements; i++) { if (vfl->vlan_id[i] > I40E_MAX_VLANID) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } } @@ -3228,7 +3228,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) vsi = pf->vsi[vf->lan_vsi_idx]; if (vsi->info.pvid) { if (vfl->num_elements > 1 || vfl->vlan_id[0]) - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -3269,7 +3269,7 @@ static int i40e_vc_rdma_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || !test_bit(I40E_VF_STATE_RDMAENA, &vf->vf_states)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } @@ -3298,13 +3298,13 @@ static int i40e_vc_rdma_qvmap_msg(struct i40e_vf *vf, u8 *msg, bool config) if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || !test_bit(I40E_VF_STATE_RDMAENA, &vf->vf_states)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto error_param; } if (config) { if (i40e_config_rdma_qvlist(vf, qvlist_info)) - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; } else { i40e_release_rdma_qvlist(vf); } @@ -3335,7 +3335,7 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg) if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) || vrk->key_len != I40E_HKEY_ARRAY_SIZE) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3366,13 +3366,13 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg) if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) || vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } for (i = 0; i < vrl->lut_entries; i++) if (vrl->lut[i] >= vf->num_queue_pairs) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3399,14 +3399,14 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg) int len = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } len = sizeof(struct virtchnl_rss_hena); vrh = kzalloc(len, GFP_KERNEL); if (!vrh) { - aq_ret = I40E_ERR_NO_MEMORY; + aq_ret = -ENOMEM; len = 0; goto err; } @@ -3435,7 +3435,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(0, vf->vf_id), (u32)vrh->hena); @@ -3460,7 +3460,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3486,7 +3486,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3574,7 +3574,7 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf, dev_err(&pf->pdev->dev, "VF %d not trusted, make VF trusted to add advanced mode ADq cloud filters\n", vf->vf_id); - return I40E_ERR_CONFIG; + return -EIO; } } @@ -3627,9 +3627,9 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf, } } - return I40E_SUCCESS; + return 0; err: - return I40E_ERR_CONFIG; + return -EIO; } /** @@ -3713,7 +3713,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) int i, ret; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3721,7 +3721,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) dev_info(&pf->pdev->dev, "VF %d: ADq not enabled, can't apply cloud filter\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3729,7 +3729,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) dev_info(&pf->pdev->dev, "VF %d: Invalid input, can't apply cloud filter\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3844,7 +3844,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) int i, ret; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } @@ -3852,7 +3852,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) dev_info(&pf->pdev->dev, "VF %d: ADq is not enabled, can't apply cloud filter\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } @@ -3860,7 +3860,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) dev_info(&pf->pdev->dev, "VF %d: Invalid input/s, can't apply cloud filter\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err_out; } @@ -3953,7 +3953,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) u64 speed = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3961,7 +3961,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) if (vf->spoofchk) { dev_err(&pf->pdev->dev, "Spoof check is ON, turn it OFF to enable ADq\n"); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3969,7 +3969,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) dev_err(&pf->pdev->dev, "VF %d attempting to enable ADq, but hasn't properly negotiated that capability\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3978,7 +3978,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) dev_err(&pf->pdev->dev, "VF %d trying to set %u TCs, valid range 1-%u TCs per VF\n", vf->vf_id, tci->num_tc, I40E_MAX_VF_VSI); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -3990,7 +3990,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) "VF %d: TC %d trying to set %u queues, valid range 1-%u queues per TC\n", vf->vf_id, i, tci->list[i].count, I40E_DEFAULT_QUEUES_PER_VF); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -4001,7 +4001,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) dev_err(&pf->pdev->dev, "No queues left to allocate to VF %d\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } else { /* we need to allocate max VF queues to enable ADq so as to @@ -4016,7 +4016,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) if (speed == SPEED_UNKNOWN) { dev_err(&pf->pdev->dev, "Cannot detect link speed\n"); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -4029,7 +4029,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) "Invalid max tx rate %llu specified for VF %d.", tci->list[i].max_tx_rate, vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } else { vf->ch[i].max_tx_rate = @@ -4045,7 +4045,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) /* reset the VF in order to allocate resources */ i40e_vc_reset_vf(vf, true); - return I40E_SUCCESS; + return 0; /* send the response to the VF */ err: @@ -4064,7 +4064,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) int aq_ret = 0; if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; goto err; } @@ -4079,13 +4079,13 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) } else { dev_info(&pf->pdev->dev, "VF %d trying to delete queue channels but ADq isn't enabled\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; + aq_ret = -EINVAL; } /* reset the VF in order to allocate resources */ i40e_vc_reset_vf(vf, true); - return I40E_SUCCESS; + return 0; err: return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DISABLE_CHANNELS, @@ -4119,21 +4119,16 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, /* Check if VF is disabled. */ if (test_bit(I40E_VF_STATE_DISABLED, &vf->vf_states)) - return I40E_ERR_PARAM; + return -EINVAL; /* perform basic checks on the msg */ ret = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen); if (ret) { - i40e_vc_send_resp_to_vf(vf, v_opcode, I40E_ERR_PARAM); + i40e_vc_send_resp_to_vf(vf, v_opcode, -EINVAL); dev_err(&pf->pdev->dev, "Invalid message from VF %d, opcode %d, len %d\n", local_vf_id, v_opcode, msglen); - switch (ret) { - case VIRTCHNL_STATUS_ERR_PARAM: - return -EPERM; - default: - return -EINVAL; - } + return ret; } switch (v_opcode) { @@ -4226,7 +4221,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, dev_err(&pf->pdev->dev, "Unsupported opcode %d from VF %d\n", v_opcode, local_vf_id); ret = i40e_vc_send_resp_to_vf(vf, v_opcode, - I40E_ERR_NOT_IMPLEMENTED); + -EOPNOTSUPP); break; } -- cgit From df41fa677d9b4717c930afbe88b06f5cefdacb21 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 28 Jul 2023 11:39:45 -0700 Subject: net: bcmgenet: Remove TX ring full logging There is no need to spam the kernel log with such an indication, remove this message. Signed-off-by: Florian Fainelli Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230728183945.760531-1-florian.fainelli@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 2b5761ad2f92..24bade875ca6 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2077,12 +2077,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock(&ring->lock); if (ring->free_bds <= (nr_frags + 1)) { - if (!netif_tx_queue_stopped(txq)) { + if (!netif_tx_queue_stopped(txq)) netif_tx_stop_queue(txq); - netdev_err(dev, - "%s: tx ring %d full when queue %d awake\n", - __func__, index, ring->queue); - } ret = NETDEV_TX_BUSY; goto out; } -- cgit From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 30 Jul 2023 09:41:10 +0200 Subject: net: dsa: qca8k: make learning configurable and keep off if standalone Address learning should initially be turned off by the driver for port operation in standalone mode, then the DSA core handles changes to it via ds->ops->port_bridge_flags(). Currently this is not the case for qca8k where learning is enabled unconditionally in qca8k_setup for every user port. Handle ports configured in standalone mode by making the learning configurable and not enabling it by default. Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to enable learning for bridge that request it and tweak .port_stp_state_set to correctly disable learning when port is configured in standalone mode. Signed-off-by: Christian Marangi Reviewed-by: Vladimir Oltean Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++--- drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/qca/qca8k.h | 6 +++++ 3 files changed, 58 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index 47b9f5bf98fb..dcef16c2a075 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1870,9 +1870,8 @@ qca8k_setup(struct dsa_switch *ds) if (ret) return ret; - /* Enable ARP Auto-learning by default */ - ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), - QCA8K_PORT_LOOKUP_LEARN); + ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_LEARN); if (ret) return ret; @@ -1978,6 +1977,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { .port_change_mtu = qca8k_port_change_mtu, .port_max_mtu = qca8k_port_max_mtu, .port_stp_state_set = qca8k_port_stp_state_set, + .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, + .port_bridge_flags = qca8k_port_bridge_flags, .port_bridge_join = qca8k_port_bridge_join, .port_bridge_leave = qca8k_port_bridge_leave, .port_fast_age = qca8k_port_fast_age, diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 13b8452ce5b2..fce04ce12cf9 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch *ds, int port, return 0; } +static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, + bool learning) +{ + struct qca8k_priv *priv = ds->priv; + + if (learning) + return regmap_set_bits(priv->regmap, + QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_LEARN); + else + return regmap_clear_bits(priv->regmap, + QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_LEARN); +} + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { + struct dsa_port *dp = dsa_to_port(ds, port); struct qca8k_priv *priv = ds->priv; + bool learning = false; u32 stp_state; switch (state) { @@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) break; case BR_STATE_LEARNING: stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; + learning = dp->learning; break; case BR_STATE_FORWARDING: + learning = dp->learning; + fallthrough; default: stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; break; @@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); + + qca8k_port_configure_learning(ds, port, learning); +} + +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & ~BR_LEARNING) + return -EINVAL; + + return 0; +} + +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + int ret; + + if (flags.mask & BR_LEARNING) { + ret = qca8k_port_configure_learning(ds, port, + flags.val & BR_LEARNING); + if (ret) + return ret; + } + + return 0; } int qca8k_port_bridge_join(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h index c5cc8a172d65..8f88b7db384d 100644 --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h @@ -522,6 +522,12 @@ int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); /* Common bridge function */ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack); +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack); int qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, bool *tx_fwd_offload, -- cgit From 18e8feae4a807994e4906d659116d249bfecd4c5 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 30 Jul 2023 09:41:11 +0200 Subject: net: dsa: qca8k: limit user ports access to the first CPU port on setup In preparation for multi-CPU support, set CPU port LOOKUP MEMBER outside the port loop and setup the LOOKUP MEMBER mask for user ports only to the first CPU port. This is to handle flooding condition where every CPU port is set as target and prevent packet duplication for unknown frames from user ports. Secondary CPU port LOOKUP MEMBER mask will be setup later when port_change_master will be implemented. Signed-off-by: Christian Marangi Reviewed-by: Simon Horman Reviewed-by: Florian Fainelli Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230730074113.21889-3-ansuelsmth@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/dsa/qca/qca8k-8xxx.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index dcef16c2a075..acee5fe6567f 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1850,18 +1850,16 @@ qca8k_setup(struct dsa_switch *ds) if (ret) return ret; + /* CPU port gets connected to all user ports of the switch */ + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), + QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); + if (ret) + return ret; + /* Setup connection between CPU port & user ports * Configure specific switch configuration for ports */ for (i = 0; i < QCA8K_NUM_PORTS; i++) { - /* CPU port gets connected to all user ports of the switch */ - if (dsa_is_cpu_port(ds, i)) { - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), - QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); - if (ret) - return ret; - } - /* Individual user ports get connected to CPU port only */ if (dsa_is_user_port(ds, i)) { ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- cgit From a9108b0712bf018dc69020864b21485b71b17dfc Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 30 Jul 2023 09:41:12 +0200 Subject: net: dsa: qca8k: move qca8xxx hol fixup to separate function Move qca8xxx hol fixup to separate function to tidy things up and to permit using a more efficent loop in future patch. Signed-off-by: Christian Marangi Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230730074113.21889-4-ansuelsmth@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/dsa/qca/qca8k-8xxx.c | 78 +++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index acee5fe6567f..f2cf8f77d3d1 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1756,6 +1756,46 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds, return 0; } +static void qca8k_setup_hol_fixup(struct qca8k_priv *priv, int port) +{ + u32 mask; + + switch (port) { + /* The 2 CPU port and port 5 requires some different + * priority than any other ports. + */ + case 0: + case 5: + case 6: + mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | + QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | + QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | + QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | + QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | + QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | + QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); + break; + default: + mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | + QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | + QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | + QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | + QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); + } + regmap_write(priv->regmap, QCA8K_REG_PORT_HOL_CTRL0(port), mask); + + mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | + QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | + QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | + QCA8K_PORT_HOL_CTRL1_WRED_EN; + regmap_update_bits(priv->regmap, QCA8K_REG_PORT_HOL_CTRL1(port), + QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | + QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | + QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | + QCA8K_PORT_HOL_CTRL1_WRED_EN, + mask); +} + static int qca8k_setup(struct dsa_switch *ds) { @@ -1895,42 +1935,8 @@ qca8k_setup(struct dsa_switch *ds) * missing settings to improve switch stability under load condition. * This problem is limited to qca8337 and other qca8k switch are not affected. */ - if (priv->switch_id == QCA8K_ID_QCA8337) { - switch (i) { - /* The 2 CPU port and port 5 requires some different - * priority than any other ports. - */ - case 0: - case 5: - case 6: - mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | - QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | - QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | - QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | - QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | - QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | - QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); - break; - default: - mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | - QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | - QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | - QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | - QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); - } - qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); - - mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | - QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | - QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | - QCA8K_PORT_HOL_CTRL1_WRED_EN; - qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), - QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | - QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | - QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | - QCA8K_PORT_HOL_CTRL1_WRED_EN, - mask); - } + if (priv->switch_id == QCA8K_ID_QCA8337) + qca8k_setup_hol_fixup(priv, i); } /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ -- cgit From 01e6f8ad8d26ced14b0cf288c42e55d03a7c5070 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 30 Jul 2023 09:41:13 +0200 Subject: net: dsa: qca8k: use dsa_for_each macro instead of for loop Convert for loop to dsa_for_each macro to save some redundant write on unconnected/unused port and tidy things up. Signed-off-by: Christian Marangi Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230730074113.21889-5-ansuelsmth@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/dsa/qca/qca8k-8xxx.c | 107 ++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 53 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index f2cf8f77d3d1..de1dc22cf683 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1800,7 +1800,8 @@ static int qca8k_setup(struct dsa_switch *ds) { struct qca8k_priv *priv = ds->priv; - int cpu_port, ret, i; + struct dsa_port *dp; + int cpu_port, ret; u32 mask; cpu_port = qca8k_find_cpu_port(ds); @@ -1855,27 +1856,27 @@ qca8k_setup(struct dsa_switch *ds) dev_warn(priv->dev, "mib init failed"); /* Initial setup of all ports */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) { + dsa_switch_for_each_port(dp, ds) { /* Disable forwarding by default on all ports */ - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(dp->index), QCA8K_PORT_LOOKUP_MEMBER, 0); if (ret) return ret; + } - /* Enable QCA header mode on all cpu ports */ - if (dsa_is_cpu_port(ds, i)) { - ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), - FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | - FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); - if (ret) { - dev_err(priv->dev, "failed enabling QCA header mode"); - return ret; - } + /* Disable MAC by default on all user ports */ + dsa_switch_for_each_user_port(dp, ds) + qca8k_port_set_status(priv, dp->index, 0); + + /* Enable QCA header mode on all cpu ports */ + dsa_switch_for_each_cpu_port(dp, ds) { + ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(dp->index), + FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | + FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); + if (ret) { + dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); + return ret; } - - /* Disable MAC by default on all user ports */ - if (dsa_is_user_port(ds, i)) - qca8k_port_set_status(priv, i, 0); } /* Forward all unknown frames to CPU port for Linux processing @@ -1897,48 +1898,48 @@ qca8k_setup(struct dsa_switch *ds) return ret; /* Setup connection between CPU port & user ports - * Configure specific switch configuration for ports + * Individual user ports get connected to CPU port only */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) { - /* Individual user ports get connected to CPU port only */ - if (dsa_is_user_port(ds, i)) { - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), - QCA8K_PORT_LOOKUP_MEMBER, - BIT(cpu_port)); - if (ret) - return ret; - - ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), - QCA8K_PORT_LOOKUP_LEARN); - if (ret) - return ret; - - /* For port based vlans to work we need to set the - * default egress vid - */ - ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), - QCA8K_EGREES_VLAN_PORT_MASK(i), - QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); - if (ret) - return ret; - - ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), - QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | - QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); - if (ret) - return ret; - } + dsa_switch_for_each_user_port(dp, ds) { + u8 port = dp->index; + + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_MEMBER, + BIT(cpu_port)); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_LEARN); + if (ret) + return ret; - /* The port 5 of the qca8337 have some problem in flood condition. The - * original legacy driver had some specific buffer and priority settings - * for the different port suggested by the QCA switch team. Add this - * missing settings to improve switch stability under load condition. - * This problem is limited to qca8337 and other qca8k switch are not affected. + /* For port based vlans to work we need to set the + * default egress vid */ - if (priv->switch_id == QCA8K_ID_QCA8337) - qca8k_setup_hol_fixup(priv, i); + ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), + QCA8K_EGREES_VLAN_PORT_MASK(port), + QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); + if (ret) + return ret; + + ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), + QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | + QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); + if (ret) + return ret; } + /* The port 5 of the qca8337 have some problem in flood condition. The + * original legacy driver had some specific buffer and priority settings + * for the different port suggested by the QCA switch team. Add this + * missing settings to improve switch stability under load condition. + * This problem is limited to qca8337 and other qca8k switch are not affected. + */ + if (priv->switch_id == QCA8K_ID_QCA8337) + dsa_switch_for_each_available_port(dp, ds) + qca8k_setup_hol_fixup(priv, dp->index); + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ if (priv->switch_id == QCA8K_ID_QCA8327) { mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | -- cgit From 942999c48cb382feb53c6da7679a994c97963836 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 24 Jul 2023 13:39:27 -0500 Subject: wifi: rtw89: Fix loading of compressed firmware When using compressed firmware, the early firmware load feature will fail. In most cases, the only downside is that if a device has more than one firmware version available, only the last one listed will be loaded. In at least two cases, there is no firmware loaded, and the device fails initialization. See https://github.com/lwfinger/rtw89/issues/259 and https://bugzilla.opensuse.org/show_bug.cgi?id=1212808 for examples of the failure. When firmware_class.dyndbg=+p" added to the kernel boot parameters, the following is found: finger@localhost:~/rtw89>sudo dmesg -t | grep rtw89 firmware_class: __allocate_fw_priv: fw-rtw89/rtw8852b_fw-1.bin fw_priv=00000000638862fb rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/5.14.21-150500.53-default/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/5.14.21-150500.53-default/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: Direct firmware load for rtw89/rtw8852b_fw-1.bin failed with error -2 firmware_class: __free_fw_priv: fw-rtw89/rtw8852b_fw-1.bin fw_priv=00000000638862fb data=00000000307c30c7 size=0 firmware_class: __allocate_fw_priv: fw-rtw89/rtw8852b_fw.bin fw_priv=00000000638862fb rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: Direct firmware load for rtw89/rtw8852b_fw.bin failed with error -2 firmware_class: __free_fw_priv: fw-rtw89/rtw8852b_fw.bin fw_priv=00000000638862fb data=00000000307c30c7 size=0 rtw89_8852be 0000:02:00.0: failed to early request firmware: -2 firmware_class: __allocate_fw_priv: fw-rtw89/rtw8852b_fw.bin fw_priv=00000000638862fb rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/rtw89/rtw8852b_fw.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/5.14.21-150500.53-default/rtw89/rtw8852b_fw.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: Loading firmware from /lib/firmware/rtw89/rtw8852b_fw.bin.xz rtw89_8852be 0000:02:00.0: f/w decompressing rtw89/rtw8852b_fw.bin firmware_class: fw_set_page_data: fw-rtw89/rtw8852b_fw.bin fw_priv=00000000638862fb data=000000004ed6c2f7 size=1035232 rtw89_8852be 0000:02:00.0: Firmware version 0.27.32.1, cmd version 0, type 1 rtw89_8852be 0000:02:00.0: Firmware version 0.27.32.1, cmd version 0, type 3 The key is that firmware version 0.27.32.1 is loaded. With this patch, the following is obtained: firmware_class: __free_fw_priv: fw-rtw89/rtw8852b_fw.bin fw_priv=000000000849addc data=00000000fd3cabe2 size=1035232 firmware_class: fw_name_devm_release: fw_name-rtw89/rtw8852b_fw.bin devm-000000002d8c3343 released firmware_class: __allocate_fw_priv: fw-rtw89/rtw8852b_fw-1.bin fw_priv=000000009e1a6364 rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/rtw89/rtw8852b_fw-1.bin failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin.zst failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw-1.bin.zst failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin.zst failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/rtw89/rtw8852b_fw-1.bin.zst failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/updates/rtw89/rtw8852b_fw-1.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: loading /lib/firmware/6.4.3-1-default/rtw89/rtw8852b_fw-1.bin.xz failed for no such file or directory. rtw89_8852be 0000:02:00.0: Loading firmware from /lib/firmware/rtw89/rtw8852b_fw-1.bin.xz rtw89_8852be 0000:02:00.0: f/w decompressing rtw89/rtw8852b_fw-1.bin firmware_class: fw_set_page_data: fw-rtw89/rtw8852b_fw-1.bin fw_priv=000000009e1a6364 data=00000000fd3cabe2 size=1184992 rtw89_8852be 0000:02:00.0: Loaded FW: rtw89/rtw8852b_fw-1.bin, sha256: 8539efc75f513f4585cf0cd6e79e6507da47fce87225f2d0de391a03aefe9ac8 rtw89_8852be 0000:02:00.0: loaded firmware rtw89/rtw8852b_fw-1.bin rtw89_8852be 0000:02:00.0: Firmware version 0.29.29.1, cmd version 0, type 5 rtw89_8852be 0000:02:00.0: Firmware version 0.29.29.1, cmd version 0, type 3 Now, version 0.29.29.1 is loaded. Fixes: ffde7f3476a6 ("wifi: rtw89: add firmware format version to backward compatible with older drivers") Cc: Ping-Ke Shih Cc: Takashi Iwai Signed-off-by: Larry Finger Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230724183927.28553-1-Larry.Finger@lwfinger.net --- drivers/net/wireless/realtek/rtw89/fw.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 9637f5e48d84..d44628a90046 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -312,31 +312,17 @@ rtw89_early_fw_feature_recognize(struct device *device, struct rtw89_fw_info *early_fw, int *used_fw_format) { - union rtw89_compat_fw_hdr buf = {}; const struct firmware *firmware; - bool full_req = false; char fw_name[64]; int fw_format; u32 ver_code; int ret; - /* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will - * be denied (-EPERM). Then, we don't get right firmware things as - * expected. So, in this case, we have to request full firmware here. - */ - if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE)) - full_req = true; - for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) { rtw89_fw_get_filename(fw_name, sizeof(fw_name), chip->fw_basename, fw_format); - if (full_req) - ret = request_firmware(&firmware, fw_name, device); - else - ret = request_partial_firmware_into_buf(&firmware, fw_name, - device, &buf, sizeof(buf), - 0); + ret = request_firmware(&firmware, fw_name, device); if (!ret) { dev_info(device, "loaded firmware %s\n", fw_name); *used_fw_format = fw_format; @@ -349,10 +335,7 @@ rtw89_early_fw_feature_recognize(struct device *device, return NULL; } - if (full_req) - ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data); - else - ver_code = rtw89_compat_fw_hdr_ver_code(&buf); + ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data); if (!ver_code) goto out; @@ -360,11 +343,7 @@ rtw89_early_fw_feature_recognize(struct device *device, rtw89_fw_iterate_feature_cfg(early_fw, chip, ver_code); out: - if (full_req) - return firmware; - - release_firmware(firmware); - return NULL; + return firmware; } int rtw89_fw_recognize(struct rtw89_dev *rtwdev) -- cgit From f698afa7ce374d41d8c2d145b11983800acd32d1 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:43 +0800 Subject: wifi: rtw89: add chip_info::chip_gen to determine chip generation The coming WiFi 7 chip is 8922AE which uses different hardware rate and register naming rule. Adding a chip_info::chip_gen field can help to do things by generations accordingly. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 9 +++++++++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + 5 files changed, 13 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index d2c67db97db1..d44f428d30b4 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -109,6 +109,14 @@ enum rtw89_core_chip_id { RTL8852B, RTL8852C, RTL8851B, + RTL8922A, +}; + +enum rtw89_chip_gen { + RTW89_CHIP_AX, + RTW89_CHIP_BE, + + RTW89_CHIP_GEN_NUM, }; enum rtw89_cv { @@ -3177,6 +3185,7 @@ struct rtw89_antdiv_info { struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; + enum rtw89_chip_gen chip_gen; const struct rtw89_chip_ops *ops; const char *fw_basename; u8 fw_format_max; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index c3ffcb645ebf..456b8369fb06 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2334,6 +2334,7 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8851b = { const struct rtw89_chip_info rtw8851b_chip_info = { .chip_id = RTL8851B, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8851b_chip_ops, .fw_basename = RTW8851B_FW_BASENAME, .fw_format_max = RTW8851B_FW_FORMAT_MAX, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 6257414a3b4b..0fc5eb777a4a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2071,6 +2071,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { const struct rtw89_chip_info rtw8852a_chip_info = { .chip_id = RTL8852A, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852a_chip_ops, .fw_basename = RTW8852A_FW_BASENAME, .fw_format_max = RTW8852A_FW_FORMAT_MAX, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 718f993da62a..d76d74cc867a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2503,6 +2503,7 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8852b = { const struct rtw89_chip_info rtw8852b_chip_info = { .chip_id = RTL8852B, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852b_chip_ops, .fw_basename = RTW8852B_FW_BASENAME, .fw_format_max = RTW8852B_FW_FORMAT_MAX, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 9c7c9812d4f4..f269832b2bc6 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2802,6 +2802,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852c_chip_ops, .fw_basename = RTW8852C_FW_BASENAME, .fw_format_max = RTW8852C_FW_FORMAT_MAX, -- cgit From 9e5c6c0df94ec70d74d22d7d74759f4aad452451 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:44 +0800 Subject: wifi: rtw89: define hardware rate v1 for WiFi 7 chips To support EHT rate, hardware rate v1 is introduced. The CCK and OFDM rates are persistent. HT/VHT/HE rates use different rate code from original, and add new code for EHT rates. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 188 ++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index d44f428d30b4..81643a9b4e85 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -395,6 +395,194 @@ enum rtw89_hw_rate { RTW89_HW_RATE_HE_NSS4_MCS9 = 0x1B9, RTW89_HW_RATE_HE_NSS4_MCS10 = 0x1BA, RTW89_HW_RATE_HE_NSS4_MCS11 = 0x1BB, + + RTW89_HW_RATE_V1_MCS0 = 0x100, + RTW89_HW_RATE_V1_MCS1 = 0x101, + RTW89_HW_RATE_V1_MCS2 = 0x102, + RTW89_HW_RATE_V1_MCS3 = 0x103, + RTW89_HW_RATE_V1_MCS4 = 0x104, + RTW89_HW_RATE_V1_MCS5 = 0x105, + RTW89_HW_RATE_V1_MCS6 = 0x106, + RTW89_HW_RATE_V1_MCS7 = 0x107, + RTW89_HW_RATE_V1_MCS8 = 0x108, + RTW89_HW_RATE_V1_MCS9 = 0x109, + RTW89_HW_RATE_V1_MCS10 = 0x10A, + RTW89_HW_RATE_V1_MCS11 = 0x10B, + RTW89_HW_RATE_V1_MCS12 = 0x10C, + RTW89_HW_RATE_V1_MCS13 = 0x10D, + RTW89_HW_RATE_V1_MCS14 = 0x10E, + RTW89_HW_RATE_V1_MCS15 = 0x10F, + RTW89_HW_RATE_V1_MCS16 = 0x110, + RTW89_HW_RATE_V1_MCS17 = 0x111, + RTW89_HW_RATE_V1_MCS18 = 0x112, + RTW89_HW_RATE_V1_MCS19 = 0x113, + RTW89_HW_RATE_V1_MCS20 = 0x114, + RTW89_HW_RATE_V1_MCS21 = 0x115, + RTW89_HW_RATE_V1_MCS22 = 0x116, + RTW89_HW_RATE_V1_MCS23 = 0x117, + RTW89_HW_RATE_V1_MCS24 = 0x118, + RTW89_HW_RATE_V1_MCS25 = 0x119, + RTW89_HW_RATE_V1_MCS26 = 0x11A, + RTW89_HW_RATE_V1_MCS27 = 0x11B, + RTW89_HW_RATE_V1_MCS28 = 0x11C, + RTW89_HW_RATE_V1_MCS29 = 0x11D, + RTW89_HW_RATE_V1_MCS30 = 0x11E, + RTW89_HW_RATE_V1_MCS31 = 0x11F, + RTW89_HW_RATE_V1_VHT_NSS1_MCS0 = 0x200, + RTW89_HW_RATE_V1_VHT_NSS1_MCS1 = 0x201, + RTW89_HW_RATE_V1_VHT_NSS1_MCS2 = 0x202, + RTW89_HW_RATE_V1_VHT_NSS1_MCS3 = 0x203, + RTW89_HW_RATE_V1_VHT_NSS1_MCS4 = 0x204, + RTW89_HW_RATE_V1_VHT_NSS1_MCS5 = 0x205, + RTW89_HW_RATE_V1_VHT_NSS1_MCS6 = 0x206, + RTW89_HW_RATE_V1_VHT_NSS1_MCS7 = 0x207, + RTW89_HW_RATE_V1_VHT_NSS1_MCS8 = 0x208, + RTW89_HW_RATE_V1_VHT_NSS1_MCS9 = 0x209, + RTW89_HW_RATE_V1_VHT_NSS1_MCS10 = 0x20A, + RTW89_HW_RATE_V1_VHT_NSS1_MCS11 = 0x20B, + RTW89_HW_RATE_V1_VHT_NSS2_MCS0 = 0x220, + RTW89_HW_RATE_V1_VHT_NSS2_MCS1 = 0x221, + RTW89_HW_RATE_V1_VHT_NSS2_MCS2 = 0x222, + RTW89_HW_RATE_V1_VHT_NSS2_MCS3 = 0x223, + RTW89_HW_RATE_V1_VHT_NSS2_MCS4 = 0x224, + RTW89_HW_RATE_V1_VHT_NSS2_MCS5 = 0x225, + RTW89_HW_RATE_V1_VHT_NSS2_MCS6 = 0x226, + RTW89_HW_RATE_V1_VHT_NSS2_MCS7 = 0x227, + RTW89_HW_RATE_V1_VHT_NSS2_MCS8 = 0x228, + RTW89_HW_RATE_V1_VHT_NSS2_MCS9 = 0x229, + RTW89_HW_RATE_V1_VHT_NSS2_MCS10 = 0x22A, + RTW89_HW_RATE_V1_VHT_NSS2_MCS11 = 0x22B, + RTW89_HW_RATE_V1_VHT_NSS3_MCS0 = 0x240, + RTW89_HW_RATE_V1_VHT_NSS3_MCS1 = 0x241, + RTW89_HW_RATE_V1_VHT_NSS3_MCS2 = 0x242, + RTW89_HW_RATE_V1_VHT_NSS3_MCS3 = 0x243, + RTW89_HW_RATE_V1_VHT_NSS3_MCS4 = 0x244, + RTW89_HW_RATE_V1_VHT_NSS3_MCS5 = 0x245, + RTW89_HW_RATE_V1_VHT_NSS3_MCS6 = 0x246, + RTW89_HW_RATE_V1_VHT_NSS3_MCS7 = 0x247, + RTW89_HW_RATE_V1_VHT_NSS3_MCS8 = 0x248, + RTW89_HW_RATE_V1_VHT_NSS3_MCS9 = 0x249, + RTW89_HW_RATE_V1_VHT_NSS3_MCS10 = 0x24A, + RTW89_HW_RATE_V1_VHT_NSS3_MCS11 = 0x24B, + RTW89_HW_RATE_V1_VHT_NSS4_MCS0 = 0x260, + RTW89_HW_RATE_V1_VHT_NSS4_MCS1 = 0x261, + RTW89_HW_RATE_V1_VHT_NSS4_MCS2 = 0x262, + RTW89_HW_RATE_V1_VHT_NSS4_MCS3 = 0x263, + RTW89_HW_RATE_V1_VHT_NSS4_MCS4 = 0x264, + RTW89_HW_RATE_V1_VHT_NSS4_MCS5 = 0x265, + RTW89_HW_RATE_V1_VHT_NSS4_MCS6 = 0x266, + RTW89_HW_RATE_V1_VHT_NSS4_MCS7 = 0x267, + RTW89_HW_RATE_V1_VHT_NSS4_MCS8 = 0x268, + RTW89_HW_RATE_V1_VHT_NSS4_MCS9 = 0x269, + RTW89_HW_RATE_V1_VHT_NSS4_MCS10 = 0x26A, + RTW89_HW_RATE_V1_VHT_NSS4_MCS11 = 0x26B, + RTW89_HW_RATE_V1_HE_NSS1_MCS0 = 0x300, + RTW89_HW_RATE_V1_HE_NSS1_MCS1 = 0x301, + RTW89_HW_RATE_V1_HE_NSS1_MCS2 = 0x302, + RTW89_HW_RATE_V1_HE_NSS1_MCS3 = 0x303, + RTW89_HW_RATE_V1_HE_NSS1_MCS4 = 0x304, + RTW89_HW_RATE_V1_HE_NSS1_MCS5 = 0x305, + RTW89_HW_RATE_V1_HE_NSS1_MCS6 = 0x306, + RTW89_HW_RATE_V1_HE_NSS1_MCS7 = 0x307, + RTW89_HW_RATE_V1_HE_NSS1_MCS8 = 0x308, + RTW89_HW_RATE_V1_HE_NSS1_MCS9 = 0x309, + RTW89_HW_RATE_V1_HE_NSS1_MCS10 = 0x30A, + RTW89_HW_RATE_V1_HE_NSS1_MCS11 = 0x30B, + RTW89_HW_RATE_V1_HE_NSS2_MCS0 = 0x320, + RTW89_HW_RATE_V1_HE_NSS2_MCS1 = 0x321, + RTW89_HW_RATE_V1_HE_NSS2_MCS2 = 0x322, + RTW89_HW_RATE_V1_HE_NSS2_MCS3 = 0x323, + RTW89_HW_RATE_V1_HE_NSS2_MCS4 = 0x324, + RTW89_HW_RATE_V1_HE_NSS2_MCS5 = 0x325, + RTW89_HW_RATE_V1_HE_NSS2_MCS6 = 0x326, + RTW89_HW_RATE_V1_HE_NSS2_MCS7 = 0x327, + RTW89_HW_RATE_V1_HE_NSS2_MCS8 = 0x328, + RTW89_HW_RATE_V1_HE_NSS2_MCS9 = 0x329, + RTW89_HW_RATE_V1_HE_NSS2_MCS10 = 0x32A, + RTW89_HW_RATE_V1_HE_NSS2_MCS11 = 0x32B, + RTW89_HW_RATE_V1_HE_NSS3_MCS0 = 0x340, + RTW89_HW_RATE_V1_HE_NSS3_MCS1 = 0x341, + RTW89_HW_RATE_V1_HE_NSS3_MCS2 = 0x342, + RTW89_HW_RATE_V1_HE_NSS3_MCS3 = 0x343, + RTW89_HW_RATE_V1_HE_NSS3_MCS4 = 0x344, + RTW89_HW_RATE_V1_HE_NSS3_MCS5 = 0x345, + RTW89_HW_RATE_V1_HE_NSS3_MCS6 = 0x346, + RTW89_HW_RATE_V1_HE_NSS3_MCS7 = 0x347, + RTW89_HW_RATE_V1_HE_NSS3_MCS8 = 0x348, + RTW89_HW_RATE_V1_HE_NSS3_MCS9 = 0x349, + RTW89_HW_RATE_V1_HE_NSS3_MCS10 = 0x34A, + RTW89_HW_RATE_V1_HE_NSS3_MCS11 = 0x34B, + RTW89_HW_RATE_V1_HE_NSS4_MCS0 = 0x360, + RTW89_HW_RATE_V1_HE_NSS4_MCS1 = 0x361, + RTW89_HW_RATE_V1_HE_NSS4_MCS2 = 0x362, + RTW89_HW_RATE_V1_HE_NSS4_MCS3 = 0x363, + RTW89_HW_RATE_V1_HE_NSS4_MCS4 = 0x364, + RTW89_HW_RATE_V1_HE_NSS4_MCS5 = 0x365, + RTW89_HW_RATE_V1_HE_NSS4_MCS6 = 0x366, + RTW89_HW_RATE_V1_HE_NSS4_MCS7 = 0x367, + RTW89_HW_RATE_V1_HE_NSS4_MCS8 = 0x368, + RTW89_HW_RATE_V1_HE_NSS4_MCS9 = 0x369, + RTW89_HW_RATE_V1_HE_NSS4_MCS10 = 0x36A, + RTW89_HW_RATE_V1_HE_NSS4_MCS11 = 0x36B, + RTW89_HW_RATE_V1_EHT_NSS1_MCS0 = 0x400, + RTW89_HW_RATE_V1_EHT_NSS1_MCS1 = 0x401, + RTW89_HW_RATE_V1_EHT_NSS1_MCS2 = 0x402, + RTW89_HW_RATE_V1_EHT_NSS1_MCS3 = 0x403, + RTW89_HW_RATE_V1_EHT_NSS1_MCS4 = 0x404, + RTW89_HW_RATE_V1_EHT_NSS1_MCS5 = 0x405, + RTW89_HW_RATE_V1_EHT_NSS1_MCS6 = 0x406, + RTW89_HW_RATE_V1_EHT_NSS1_MCS7 = 0x407, + RTW89_HW_RATE_V1_EHT_NSS1_MCS8 = 0x408, + RTW89_HW_RATE_V1_EHT_NSS1_MCS9 = 0x409, + RTW89_HW_RATE_V1_EHT_NSS1_MCS10 = 0x40A, + RTW89_HW_RATE_V1_EHT_NSS1_MCS11 = 0x40B, + RTW89_HW_RATE_V1_EHT_NSS1_MCS12 = 0x40C, + RTW89_HW_RATE_V1_EHT_NSS1_MCS13 = 0x40D, + RTW89_HW_RATE_V1_EHT_NSS1_MCS14 = 0x40E, + RTW89_HW_RATE_V1_EHT_NSS1_MCS15 = 0x40F, + RTW89_HW_RATE_V1_EHT_NSS2_MCS0 = 0x420, + RTW89_HW_RATE_V1_EHT_NSS2_MCS1 = 0x421, + RTW89_HW_RATE_V1_EHT_NSS2_MCS2 = 0x422, + RTW89_HW_RATE_V1_EHT_NSS2_MCS3 = 0x423, + RTW89_HW_RATE_V1_EHT_NSS2_MCS4 = 0x424, + RTW89_HW_RATE_V1_EHT_NSS2_MCS5 = 0x425, + RTW89_HW_RATE_V1_EHT_NSS2_MCS6 = 0x426, + RTW89_HW_RATE_V1_EHT_NSS2_MCS7 = 0x427, + RTW89_HW_RATE_V1_EHT_NSS2_MCS8 = 0x428, + RTW89_HW_RATE_V1_EHT_NSS2_MCS9 = 0x429, + RTW89_HW_RATE_V1_EHT_NSS2_MCS10 = 0x42A, + RTW89_HW_RATE_V1_EHT_NSS2_MCS11 = 0x42B, + RTW89_HW_RATE_V1_EHT_NSS2_MCS12 = 0x42C, + RTW89_HW_RATE_V1_EHT_NSS2_MCS13 = 0x42D, + RTW89_HW_RATE_V1_EHT_NSS3_MCS0 = 0x440, + RTW89_HW_RATE_V1_EHT_NSS3_MCS1 = 0x441, + RTW89_HW_RATE_V1_EHT_NSS3_MCS2 = 0x442, + RTW89_HW_RATE_V1_EHT_NSS3_MCS3 = 0x443, + RTW89_HW_RATE_V1_EHT_NSS3_MCS4 = 0x444, + RTW89_HW_RATE_V1_EHT_NSS3_MCS5 = 0x445, + RTW89_HW_RATE_V1_EHT_NSS3_MCS6 = 0x446, + RTW89_HW_RATE_V1_EHT_NSS3_MCS7 = 0x447, + RTW89_HW_RATE_V1_EHT_NSS3_MCS8 = 0x448, + RTW89_HW_RATE_V1_EHT_NSS3_MCS9 = 0x449, + RTW89_HW_RATE_V1_EHT_NSS3_MCS10 = 0x44A, + RTW89_HW_RATE_V1_EHT_NSS3_MCS11 = 0x44B, + RTW89_HW_RATE_V1_EHT_NSS3_MCS12 = 0x44C, + RTW89_HW_RATE_V1_EHT_NSS3_MCS13 = 0x44D, + RTW89_HW_RATE_V1_EHT_NSS4_MCS0 = 0x460, + RTW89_HW_RATE_V1_EHT_NSS4_MCS1 = 0x461, + RTW89_HW_RATE_V1_EHT_NSS4_MCS2 = 0x462, + RTW89_HW_RATE_V1_EHT_NSS4_MCS3 = 0x463, + RTW89_HW_RATE_V1_EHT_NSS4_MCS4 = 0x464, + RTW89_HW_RATE_V1_EHT_NSS4_MCS5 = 0x465, + RTW89_HW_RATE_V1_EHT_NSS4_MCS6 = 0x466, + RTW89_HW_RATE_V1_EHT_NSS4_MCS7 = 0x467, + RTW89_HW_RATE_V1_EHT_NSS4_MCS8 = 0x468, + RTW89_HW_RATE_V1_EHT_NSS4_MCS9 = 0x469, + RTW89_HW_RATE_V1_EHT_NSS4_MCS10 = 0x46A, + RTW89_HW_RATE_V1_EHT_NSS4_MCS11 = 0x46B, + RTW89_HW_RATE_V1_EHT_NSS4_MCS12 = 0x46C, + RTW89_HW_RATE_V1_EHT_NSS4_MCS13 = 0x46D, + RTW89_HW_RATE_NR, RTW89_HW_RATE_MASK_MOD = GENMASK(8, 7), -- cgit From 2ef14155c29b69c40350ee845a8dc051283e1ac2 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Fri, 28 Jul 2023 15:02:45 +0800 Subject: wifi: rtw89: phy: rate pattern handles HW rate by chip gen Rate pattern is controlled by 'iw bitrates' to fix rate as desired, and we extend to support v1 rate. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/phy.c | 43 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index fb15c852fdd4..e0d4b97a372d 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -444,6 +444,12 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, return true; } +#define RTW89_HW_RATE_BY_CHIP_GEN(rate) \ + { \ + [RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \ + [RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \ + } + void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) @@ -452,39 +458,46 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_phy_rate_pattern next_pattern = {0}; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); - static const u16 hw_rate_he[] = {RTW89_HW_RATE_HE_NSS1_MCS0, - RTW89_HW_RATE_HE_NSS2_MCS0, - RTW89_HW_RATE_HE_NSS3_MCS0, - RTW89_HW_RATE_HE_NSS4_MCS0}; - static const u16 hw_rate_vht[] = {RTW89_HW_RATE_VHT_NSS1_MCS0, - RTW89_HW_RATE_VHT_NSS2_MCS0, - RTW89_HW_RATE_VHT_NSS3_MCS0, - RTW89_HW_RATE_VHT_NSS4_MCS0}; - static const u16 hw_rate_ht[] = {RTW89_HW_RATE_MCS0, - RTW89_HW_RATE_MCS8, - RTW89_HW_RATE_MCS16, - RTW89_HW_RATE_MCS24}; + static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS3_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS4_MCS0), + }; + static const u16 hw_rate_vht[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS2_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS3_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS4_MCS0), + }; + static const u16 hw_rate_ht[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(MCS8), + RTW89_HW_RATE_BY_CHIP_GEN(MCS16), + RTW89_HW_RATE_BY_CHIP_GEN(MCS24), + }; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; u8 tx_nss = rtwdev->hal.tx_nss; u8 i; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_he[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_he[i][chip_gen], RA_MASK_HE_RATES, RTW89_RA_MODE_HE, mask->control[nl_band].he_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i][chip_gen], RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT, mask->control[nl_band].vht_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i][chip_gen], RA_MASK_HT_RATES, RTW89_RA_MODE_HT, mask->control[nl_band].ht_mcs[i], 0, true)) -- cgit From 401b0c161b09682aa633aa7e2cf996a26a67f46c Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:46 +0800 Subject: wifi: rtw89: use struct to set RA H2C command RA (rate adaptive) H2C command is used to tell firmware which rates can be used for specified MAC ID. Basically, this commit doesn't change result. Only change to set two 32-bit instead of continual 8-byte rate masks one by one. Originally, we only set 5-byte masks, because existing WiFi 6 2SS chips only need 5-byte masks. Setting two 32-bit masks will be more efficient and also can support coming WiFi 7 2SS chips containing more rates. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 79 +++++++------- drivers/net/wireless/realtek/rtw89/fw.h | 187 ++++++-------------------------- 2 files changed, 73 insertions(+), 193 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d44628a90046..e77a76cf9348 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -1882,61 +1882,60 @@ fail: return ret; } -#define H2C_RA_LEN 16 int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi) { struct sk_buff *skb; - u8 *cmd; + struct rtw89_h2c_ra *h2c; + u32 len = sizeof(*h2c); int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_RA_LEN); + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c join\n"); return -ENOMEM; } - skb_put(skb, H2C_RA_LEN); - cmd = skb->data; + skb_put(skb, len); + h2c = (struct rtw89_h2c_ra *)skb->data; rtw89_debug(rtwdev, RTW89_DBG_RA, "ra cmd msk: %llx ", ra->ra_mask); - RTW89_SET_FWCMD_RA_MODE(cmd, ra->mode_ctrl); - RTW89_SET_FWCMD_RA_BW_CAP(cmd, ra->bw_cap); - RTW89_SET_FWCMD_RA_MACID(cmd, ra->macid); - RTW89_SET_FWCMD_RA_DCM(cmd, ra->dcm_cap); - RTW89_SET_FWCMD_RA_ER(cmd, ra->er_cap); - RTW89_SET_FWCMD_RA_INIT_RATE_LV(cmd, ra->init_rate_lv); - RTW89_SET_FWCMD_RA_UPD_ALL(cmd, ra->upd_all); - RTW89_SET_FWCMD_RA_SGI(cmd, ra->en_sgi); - RTW89_SET_FWCMD_RA_LDPC(cmd, ra->ldpc_cap); - RTW89_SET_FWCMD_RA_STBC(cmd, ra->stbc_cap); - RTW89_SET_FWCMD_RA_SS_NUM(cmd, ra->ss_num); - RTW89_SET_FWCMD_RA_GILTF(cmd, ra->giltf); - RTW89_SET_FWCMD_RA_UPD_BW_NSS_MASK(cmd, ra->upd_bw_nss_mask); - RTW89_SET_FWCMD_RA_UPD_MASK(cmd, ra->upd_mask); - RTW89_SET_FWCMD_RA_MASK_0(cmd, FIELD_GET(MASKBYTE0, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_1(cmd, FIELD_GET(MASKBYTE1, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_2(cmd, FIELD_GET(MASKBYTE2, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_3(cmd, FIELD_GET(MASKBYTE3, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_4(cmd, FIELD_GET(MASKBYTE4, ra->ra_mask)); - RTW89_SET_FWCMD_RA_FIX_GILTF_EN(cmd, ra->fix_giltf_en); - RTW89_SET_FWCMD_RA_FIX_GILTF(cmd, ra->fix_giltf); - - if (csi) { - RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(cmd, 1); - RTW89_SET_FWCMD_RA_BAND_NUM(cmd, ra->band_num); - RTW89_SET_FWCMD_RA_CR_TBL_SEL(cmd, ra->cr_tbl_sel); - RTW89_SET_FWCMD_RA_FIXED_CSI_RATE_EN(cmd, ra->fixed_csi_rate_en); - RTW89_SET_FWCMD_RA_RA_CSI_RATE_EN(cmd, ra->ra_csi_rate_en); - RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(cmd, ra->csi_mcs_ss_idx); - RTW89_SET_FWCMD_RA_FIXED_CSI_MODE(cmd, ra->csi_mode); - RTW89_SET_FWCMD_RA_FIXED_CSI_GI_LTF(cmd, ra->csi_gi_ltf); - RTW89_SET_FWCMD_RA_FIXED_CSI_BW(cmd, ra->csi_bw); - } - + h2c->w0 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_W0_MODE) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_W0_BW_CAP) | + le32_encode_bits(ra->macid, RTW89_H2C_RA_W0_MACID) | + le32_encode_bits(ra->dcm_cap, RTW89_H2C_RA_W0_DCM) | + le32_encode_bits(ra->er_cap, RTW89_H2C_RA_W0_ER) | + le32_encode_bits(ra->init_rate_lv, RTW89_H2C_RA_W0_INIT_RATE_LV) | + le32_encode_bits(ra->upd_all, RTW89_H2C_RA_W0_UPD_ALL) | + le32_encode_bits(ra->en_sgi, RTW89_H2C_RA_W0_SGI) | + le32_encode_bits(ra->ldpc_cap, RTW89_H2C_RA_W0_LDPC) | + le32_encode_bits(ra->stbc_cap, RTW89_H2C_RA_W0_STBC) | + le32_encode_bits(ra->ss_num, RTW89_H2C_RA_W0_SS_NUM) | + le32_encode_bits(ra->giltf, RTW89_H2C_RA_W0_GILTF) | + le32_encode_bits(ra->upd_bw_nss_mask, RTW89_H2C_RA_W0_UPD_BW_NSS_MASK) | + le32_encode_bits(ra->upd_mask, RTW89_H2C_RA_W0_UPD_MASK); + h2c->w1 = le32_encode_bits(ra->ra_mask, RTW89_H2C_RA_W1_RAMASK_LO32); + h2c->w2 = le32_encode_bits(ra->ra_mask >> 32, RTW89_H2C_RA_W2_RAMASK_HI32); + h2c->w3 = le32_encode_bits(ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) | + le32_encode_bits(ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF); + + if (!csi) + goto done; + + h2c->w2 |= le32_encode_bits(1, RTW89_H2C_RA_W2_BFEE_CSI_CTL); + h2c->w3 |= le32_encode_bits(ra->band_num, RTW89_H2C_RA_W3_BAND_NUM) | + le32_encode_bits(ra->cr_tbl_sel, RTW89_H2C_RA_W3_CR_TBL_SEL) | + le32_encode_bits(ra->fixed_csi_rate_en, RTW89_H2C_RA_W3_FIXED_CSI_RATE_EN) | + le32_encode_bits(ra->ra_csi_rate_en, RTW89_H2C_RA_W3_RA_CSI_RATE_EN) | + le32_encode_bits(ra->csi_mcs_ss_idx, RTW89_H2C_RA_W3_FIXED_CSI_MCS_SS_IDX) | + le32_encode_bits(ra->csi_mode, RTW89_H2C_RA_W3_FIXED_CSI_MODE) | + le32_encode_bits(ra->csi_gi_ltf, RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF) | + le32_encode_bits(ra->csi_bw, RTW89_H2C_RA_W3_FIXED_CSI_BW); + +done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RA, H2C_FUNC_OUTSRC_RA_MACIDCFG, 0, 0, - H2C_RA_LEN); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 45f927dc212e..5e7f528c71e7 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -291,160 +291,41 @@ struct rtw89_pktofld_info { bool cancel; }; -static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(0)); -} - -static inline void RTW89_SET_FWCMD_RA_MODE(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(5, 1)); -} - -static inline void RTW89_SET_FWCMD_RA_BW_CAP(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(7, 6)); -} - -static inline void RTW89_SET_FWCMD_RA_MACID(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(15, 8)); -} - -static inline void RTW89_SET_FWCMD_RA_DCM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(16)); -} - -static inline void RTW89_SET_FWCMD_RA_ER(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(17)); -} - -static inline void RTW89_SET_FWCMD_RA_INIT_RATE_LV(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(19, 18)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_ALL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(20)); -} - -static inline void RTW89_SET_FWCMD_RA_SGI(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(21)); -} - -static inline void RTW89_SET_FWCMD_RA_LDPC(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(22)); -} - -static inline void RTW89_SET_FWCMD_RA_STBC(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(23)); -} - -static inline void RTW89_SET_FWCMD_RA_SS_NUM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(26, 24)); -} - -static inline void RTW89_SET_FWCMD_RA_GILTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(29, 27)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_BW_NSS_MASK(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(30)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_MASK(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(31)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_0(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_1(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(15, 8)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_2(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(23, 16)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_3(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(31, 24)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_4(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x02, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x02, val, BIT(31)); -} - -static inline void RTW89_SET_FWCMD_RA_BAND_NUM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_RA_CSI_RATE_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(8)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_RATE_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(9)); -} - -static inline void RTW89_SET_FWCMD_RA_CR_TBL_SEL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(10)); -} - -static inline void RTW89_SET_FWCMD_RA_FIX_GILTF_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(11)); -} - -static inline void RTW89_SET_FWCMD_RA_FIX_GILTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(14, 12)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(23, 16)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MODE(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(25, 24)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_GI_LTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(28, 26)); -} +struct rtw89_h2c_ra { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; +} __packed; -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_BW(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(31, 29)); -} +#define RTW89_H2C_RA_W0_IS_DIS BIT(0) +#define RTW89_H2C_RA_W0_MODE GENMASK(5, 1) +#define RTW89_H2C_RA_W0_BW_CAP GENMASK(7, 6) +#define RTW89_H2C_RA_W0_MACID GENMASK(15, 8) +#define RTW89_H2C_RA_W0_DCM BIT(16) +#define RTW89_H2C_RA_W0_ER BIT(17) +#define RTW89_H2C_RA_W0_INIT_RATE_LV GENMASK(19, 18) +#define RTW89_H2C_RA_W0_UPD_ALL BIT(20) +#define RTW89_H2C_RA_W0_SGI BIT(21) +#define RTW89_H2C_RA_W0_LDPC BIT(22) +#define RTW89_H2C_RA_W0_STBC BIT(23) +#define RTW89_H2C_RA_W0_SS_NUM GENMASK(26, 24) +#define RTW89_H2C_RA_W0_GILTF GENMASK(29, 27) +#define RTW89_H2C_RA_W0_UPD_BW_NSS_MASK BIT(30) +#define RTW89_H2C_RA_W0_UPD_MASK BIT(31) +#define RTW89_H2C_RA_W1_RAMASK_LO32 GENMASK(31, 0) +#define RTW89_H2C_RA_W2_RAMASK_HI32 GENMASK(30, 0) +#define RTW89_H2C_RA_W2_BFEE_CSI_CTL BIT(31) +#define RTW89_H2C_RA_W3_BAND_NUM GENMASK(7, 0) +#define RTW89_H2C_RA_W3_RA_CSI_RATE_EN BIT(8) +#define RTW89_H2C_RA_W3_FIXED_CSI_RATE_EN BIT(9) +#define RTW89_H2C_RA_W3_CR_TBL_SEL BIT(10) +#define RTW89_H2C_RA_W3_FIX_GILTF_EN BIT(11) +#define RTW89_H2C_RA_W3_FIX_GILTF GENMASK(14, 12) +#define RTW89_H2C_RA_W3_FIXED_CSI_MCS_SS_IDX GENMASK(23, 16) +#define RTW89_H2C_RA_W3_FIXED_CSI_MODE GENMASK(25, 24) +#define RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF GENMASK(28, 26) +#define RTW89_H2C_RA_W3_FIXED_CSI_BW GENMASK(31, 29) static inline void RTW89_SET_FWCMD_SEC_IDX(void *cmd, u32 val) { -- cgit From c97683ff01a47d0dcd7092c5e7d39685910262a1 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:47 +0800 Subject: wifi: rtw89: add H2C RA command V1 to support WiFi 7 chips H2C RA V1 command adds two words to support WiFi 7 chips, which can possibly support up to 4SS rates. Because current chips have only 2SS rates, leave the fields blank for now. The main changes are to set extended bits of EHT mode and bandwidth -- add a bit for EHT mode; add a bit to enumerate 320MHz channel bandwidth. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 5 +++-- drivers/net/wireless/realtek/rtw89/fw.c | 18 +++++++++++++++++- drivers/net/wireless/realtek/rtw89/fw.h | 11 +++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 81643a9b4e85..43e02a28e4cd 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -2700,9 +2700,10 @@ struct rtw89_ra_info { * Bit2 : HT * Bit3 : VHT * Bit4 : HE + * Bit5 : EHT */ - u8 mode_ctrl:5; - u8 bw_cap:2; + u8 mode_ctrl:6; + u8 bw_cap:3; /* enum rtw89_bandwidth */ u8 macid; u8 dcm_cap:1; u8 er_cap:1; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index e77a76cf9348..cf22e50bced8 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -1884,11 +1884,19 @@ fail: int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi) { - struct sk_buff *skb; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_ra_v1 *h2c_v1; struct rtw89_h2c_ra *h2c; u32 len = sizeof(*h2c); + bool format_v1 = false; + struct sk_buff *skb; int ret; + if (chip->chip_gen == RTW89_CHIP_BE) { + len = sizeof(*h2c_v1); + format_v1 = true; + } + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c join\n"); @@ -1918,6 +1926,14 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi h2c->w3 = le32_encode_bits(ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) | le32_encode_bits(ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF); + if (!format_v1) + goto csi; + + h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; + h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); + +csi: if (!csi) goto done; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 5e7f528c71e7..831dbe602393 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -327,6 +327,17 @@ struct rtw89_h2c_ra { #define RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF GENMASK(28, 26) #define RTW89_H2C_RA_W3_FIXED_CSI_BW GENMASK(31, 29) +struct rtw89_h2c_ra_v1 { + struct rtw89_h2c_ra v0; + __le32 w4; + __le32 w5; +} __packed; + +#define RTW89_H2C_RA_V1_W4_MODE_EHT GENMASK(6, 0) +#define RTW89_H2C_RA_V1_W4_BW_EHT GENMASK(10, 8) +#define RTW89_H2C_RA_V1_W4_RAMASK_UHL16 GENMASK(31, 16) +#define RTW89_H2C_RA_V1_W5_RAMASK_UHH16 GENMASK(15, 0) + static inline void RTW89_SET_FWCMD_SEC_IDX(void *cmd, u32 val) { le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(7, 0)); -- cgit From c342ac2195161611b51927eefab18879155b110e Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:48 +0800 Subject: wifi: rtw89: use struct to access firmware C2H event header Firmware C2H events contain two-word header which can indicate category, class, function and length of received events. Use struct to access them, and doesn't change logic at all. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-7-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 9 +++++---- drivers/net/wireless/realtek/rtw89/fw.h | 17 +++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index cf22e50bced8..f8616c178de7 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2809,12 +2809,13 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev) static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h) { + const struct rtw89_c2h_hdr *hdr = (const struct rtw89_c2h_hdr *)c2h->data; struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h); - attr->category = RTW89_GET_C2H_CATEGORY(c2h->data); - attr->class = RTW89_GET_C2H_CLASS(c2h->data); - attr->func = RTW89_GET_C2H_FUNC(c2h->data); - attr->len = RTW89_GET_C2H_LEN(c2h->data); + attr->category = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_CATEGORY); + attr->class = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_CLASS); + attr->func = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_FUNC); + attr->len = le32_get_bits(hdr->w1, RTW89_C2H_HDR_W1_LEN); } static bool rtw89_fw_c2h_chk_atomic(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 831dbe602393..becd8acce9c1 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3101,14 +3101,15 @@ inline void RTW89_SET_FWCMD_MCC_SET_DURATION_DURATION_Y(void *cmd, u32 val) #define RTW89_C2H_HEADER_LEN 8 -#define RTW89_GET_C2H_CATEGORY(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(1, 0)) -#define RTW89_GET_C2H_CLASS(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(7, 2)) -#define RTW89_GET_C2H_FUNC(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(15, 8)) -#define RTW89_GET_C2H_LEN(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 1), GENMASK(13, 0)) +struct rtw89_c2h_hdr { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_C2H_HDR_W0_CATEGORY GENMASK(1, 0) +#define RTW89_C2H_HDR_W0_CLASS GENMASK(7, 2) +#define RTW89_C2H_HDR_W0_FUNC GENMASK(15, 8) +#define RTW89_C2H_HDR_W1_LEN GENMASK(13, 0) struct rtw89_fw_c2h_attr { u8 category; -- cgit From 57cafeb18f06d3f4eaea9145d3396fdb8c699acc Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:49 +0800 Subject: wifi: rtw89: use struct to access RA report RA (rate adaptive), a mechanism to select proper rate, is implemented in firmware, and this report is used to tell driver TX rate it is currently using. Use struct to access this report, and doesn't change logic at all. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-8-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.h | 24 ++++++++++++------------ drivers/net/wireless/realtek/rtw89/phy.c | 13 +++++++------ 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index becd8acce9c1..586f9707a5ed 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3160,18 +3160,18 @@ struct rtw89_c2h_mac_bcnfltr_rpt { #define RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT GENMASK(11, 10) #define RTW89_C2H_MAC_BCNFLTR_RPT_W2_MA GENMASK(23, 16) -#define RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 0)) -#define RTW89_GET_PHY_C2H_RA_RPT_RETRY_RATIO(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16)) -#define RTW89_GET_PHY_C2H_RA_RPT_MCSNSS(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(6, 0)) -#define RTW89_GET_PHY_C2H_RA_RPT_MD_SEL(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(9, 8)) -#define RTW89_GET_PHY_C2H_RA_RPT_GILTF(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(12, 10)) -#define RTW89_GET_PHY_C2H_RA_RPT_BW(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(14, 13)) +struct rtw89_c2h_ra_rpt { + struct rtw89_c2h_hdr hdr; + __le32 w2; + __le32 w3; +} __packed; + +#define RTW89_C2H_RA_RPT_W2_MACID GENMASK(15, 0) +#define RTW89_C2H_RA_RPT_W2_RETRY_RATIO GENMASK(23, 16) +#define RTW89_C2H_RA_RPT_W3_MCSNSS GENMASK(6, 0) +#define RTW89_C2H_RA_RPT_W3_MD_SEL GENMASK(9, 8) +#define RTW89_C2H_RA_RPT_W3_GILTF GENMASK(12, 10) +#define RTW89_C2H_RA_RPT_W3_BW GENMASK(14, 13) /* VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS * HT-new: [6:5]: NA, [4:0]: MCS diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index e0d4b97a372d..19a0c7ce0451 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -2244,21 +2244,22 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; struct rtw89_dev *rtwdev = ra_data->rtwdev; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct rtw89_c2h_ra_rpt *c2h = + (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; struct rtw89_ra_report *ra_report = &rtwsta->ra_report; - struct sk_buff *c2h = ra_data->c2h; u8 mode, rate, bw, giltf, mac_id; u16 legacy_bitrate; bool valid; u8 mcs = 0; - mac_id = RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h->data); + mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); if (mac_id != rtwsta->mac_id) return; - rate = RTW89_GET_PHY_C2H_RA_RPT_MCSNSS(c2h->data); - bw = RTW89_GET_PHY_C2H_RA_RPT_BW(c2h->data); - giltf = RTW89_GET_PHY_C2H_RA_RPT_GILTF(c2h->data); - mode = RTW89_GET_PHY_C2H_RA_RPT_MD_SEL(c2h->data); + rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS); + bw = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW); + giltf = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_GILTF); + mode = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL); if (mode == RTW89_RA_RPT_MODE_LEGACY) { valid = rtw89_ra_report_to_bitrate(rtwdev, rate, &legacy_bitrate); -- cgit From 5c152231c341f0ea00b3ebd64cf6718b10106dab Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:50 +0800 Subject: wifi: rtw89: add C2H RA event V1 to support WiFi 7 chips WiFi 7 chips have more rate mode (EHT), higher MCS and more bandwidth, so define and use reserved bits to carry these information in C2H events. Also, the SS/MCS encoded bits of VHT and HE are changed, so define V1 masks for them. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-9-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 2 ++ drivers/net/wireless/realtek/rtw89/fw.h | 14 ++++++++++--- drivers/net/wireless/realtek/rtw89/phy.c | 35 +++++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 43e02a28e4cd..24c109746788 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -587,6 +587,8 @@ enum rtw89_hw_rate { RTW89_HW_RATE_MASK_MOD = GENMASK(8, 7), RTW89_HW_RATE_MASK_VAL = GENMASK(6, 0), + RTW89_HW_RATE_V1_MASK_MOD = GENMASK(10, 8), + RTW89_HW_RATE_V1_MASK_VAL = GENMASK(7, 0), }; /* 2G channels, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 586f9707a5ed..49ecf070de71 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3168,16 +3168,24 @@ struct rtw89_c2h_ra_rpt { #define RTW89_C2H_RA_RPT_W2_MACID GENMASK(15, 0) #define RTW89_C2H_RA_RPT_W2_RETRY_RATIO GENMASK(23, 16) +#define RTW89_C2H_RA_RPT_W2_MCSNSS_B7 BIT(31) #define RTW89_C2H_RA_RPT_W3_MCSNSS GENMASK(6, 0) #define RTW89_C2H_RA_RPT_W3_MD_SEL GENMASK(9, 8) #define RTW89_C2H_RA_RPT_W3_GILTF GENMASK(12, 10) #define RTW89_C2H_RA_RPT_W3_BW GENMASK(14, 13) - -/* VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS - * HT-new: [6:5]: NA, [4:0]: MCS +#define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15) +#define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16) + +/* For WiFi 6 chips: + * VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS + * HT-new: [6:5]: NA, [4:0]: MCS + * For WiFi 7 chips (V1): + * HT, VHT, HE, EHT: [7:5]: NSS, [4:0]: MCS */ #define RTW89_RA_RATE_MASK_NSS GENMASK(6, 4) #define RTW89_RA_RATE_MASK_MCS GENMASK(3, 0) +#define RTW89_RA_RATE_MASK_NSS_V1 GENMASK(7, 5) +#define RTW89_RA_RATE_MASK_MCS_V1 GENMASK(4, 0) #define RTW89_RA_RATE_MASK_HT_MCS GENMASK(4, 0) #define RTW89_MK_HT_RATE(nss, mcs) (FIELD_PREP(GENMASK(4, 3), nss) | \ FIELD_PREP(GENMASK(2, 0), mcs)) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 19a0c7ce0451..1940f4457677 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -2247,10 +2247,13 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) const struct rtw89_c2h_ra_rpt *c2h = (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; struct rtw89_ra_report *ra_report = &rtwsta->ra_report; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool format_v1 = chip->chip_gen == RTW89_CHIP_BE; u8 mode, rate, bw, giltf, mac_id; u16 legacy_bitrate; bool valid; u8 mcs = 0; + u8 t; mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); if (mac_id != rtwsta->mac_id) @@ -2261,6 +2264,15 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) giltf = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_GILTF); mode = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL); + if (format_v1) { + t = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MCSNSS_B7); + rate |= u8_encode_bits(t, BIT(7)); + t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW_B2); + bw |= u8_encode_bits(t, BIT(2)); + t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL_B2); + mode |= u8_encode_bits(t, BIT(2)); + } + if (mode == RTW89_RA_RPT_MODE_LEGACY) { valid = rtw89_ra_report_to_bitrate(rtwdev, rate, &legacy_bitrate); if (!valid) @@ -2287,16 +2299,24 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) break; case RTW89_RA_RPT_MODE_VHT: ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; - ra_report->txrate.mcs = FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate); - ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1; + ra_report->txrate.mcs = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) : + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS); + ra_report->txrate.nss = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 : + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1; if (giltf) ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; mcs = ra_report->txrate.mcs; break; case RTW89_RA_RPT_MODE_HE: ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS; - ra_report->txrate.mcs = FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate); - ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1; + ra_report->txrate.mcs = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) : + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS); + ra_report->txrate.nss = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 : + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1; if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08) ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_0_8; else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16) @@ -2309,8 +2329,11 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw); ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate); - ra_report->hw_rate = FIELD_PREP(RTW89_HW_RATE_MASK_MOD, mode) | - FIELD_PREP(RTW89_HW_RATE_MASK_VAL, rate); + ra_report->hw_rate = format_v1 ? + u16_encode_bits(mode, RTW89_HW_RATE_V1_MASK_MOD) | + u16_encode_bits(rate, RTW89_HW_RATE_V1_MASK_VAL) : + u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) | + u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); ra_report->might_fallback_legacy = mcs <= 2; sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; -- cgit From ae775faa875029a9f3a246ed0a4a97b0473171a7 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:51 +0800 Subject: wifi: rtw89: add to display hardware rates v1 histogram in debugfs The upcoming WiFi 7 chips support EHT rates, and hardware rate codes are changed too, so modify to adapt the changes. (EHT counters are still zeros in below example) RX count: Legacy: [0, 0, 0, 0] OFDM: [0, 0, 0, 0, 0, 0, 0, 0] HT 0: [0, 0, 0, 0, 0, 0, 0, 0] HT 1: [0, 0, 0, 0, 0, 0, 0, 0] VHT 1SS: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 0] VHT 2SS: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 0] HE 1SS: [0, 0, 42, 0, 43, 90, 75, 0, 26, 20, 260, 7] HE 2SS: [0, 96, 232, 84, 125, 184, 52, 0, 0, 0, 0, 0] EHT 1SS: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 0] EHT 2SS: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-10-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/debug.c | 35 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 24c109746788..f3f7abddd3c0 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -584,6 +584,7 @@ enum rtw89_hw_rate { RTW89_HW_RATE_V1_EHT_NSS4_MCS13 = 0x46D, RTW89_HW_RATE_NR, + RTW89_HW_RATE_INVAL, RTW89_HW_RATE_MASK_MOD = GENMASK(8, 7), RTW89_HW_RATE_MASK_VAL = GENMASK(6, 0), diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index ce5a9ac08145..f67af8aa2358 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3325,20 +3325,26 @@ rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat, pkt_stat->rx_rate_cnt[first_rate + i]); } +#define FIRST_RATE_SAME(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_ ## rate} +#define FIRST_RATE_ENUM(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_V1_ ## rate} +#define FIRST_RATE_GEV1(rate) {RTW89_HW_RATE_INVAL, RTW89_HW_RATE_V1_ ## rate} + static const struct rtw89_rx_rate_cnt_info { - enum rtw89_hw_rate first_rate; + enum rtw89_hw_rate first_rate[RTW89_CHIP_GEN_NUM]; int len; int ext; const char *rate_mode; } rtw89_rx_rate_cnt_infos[] = { - {RTW89_HW_RATE_CCK1, 4, 0, "Legacy:"}, - {RTW89_HW_RATE_OFDM6, 8, 0, "OFDM:"}, - {RTW89_HW_RATE_MCS0, 8, 0, "HT 0:"}, - {RTW89_HW_RATE_MCS8, 8, 0, "HT 1:"}, - {RTW89_HW_RATE_VHT_NSS1_MCS0, 10, 2, "VHT 1SS:"}, - {RTW89_HW_RATE_VHT_NSS2_MCS0, 10, 2, "VHT 2SS:"}, - {RTW89_HW_RATE_HE_NSS1_MCS0, 12, 0, "HE 1SS:"}, - {RTW89_HW_RATE_HE_NSS2_MCS0, 12, 0, "HE 2ss:"}, + {FIRST_RATE_SAME(CCK1), 4, 0, "Legacy:"}, + {FIRST_RATE_SAME(OFDM6), 8, 0, "OFDM:"}, + {FIRST_RATE_ENUM(MCS0), 8, 0, "HT 0:"}, + {FIRST_RATE_ENUM(MCS8), 8, 0, "HT 1:"}, + {FIRST_RATE_ENUM(VHT_NSS1_MCS0), 10, 2, "VHT 1SS:"}, + {FIRST_RATE_ENUM(VHT_NSS2_MCS0), 10, 2, "VHT 2SS:"}, + {FIRST_RATE_ENUM(HE_NSS1_MCS0), 12, 0, "HE 1SS:"}, + {FIRST_RATE_ENUM(HE_NSS2_MCS0), 12, 0, "HE 2SS:"}, + {FIRST_RATE_GEV1(EHT_NSS1_MCS0), 14, 2, "EHT 1SS:"}, + {FIRST_RATE_GEV1(EHT_NSS2_MCS0), 14, 0, "EHT 2SS:"}, }; static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) @@ -3347,7 +3353,9 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; struct rtw89_traffic_stats *stats = &rtwdev->stats; struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat; + const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_rx_rate_cnt_info *info; + enum rtw89_hw_rate first_rate; int i; seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n", @@ -3359,15 +3367,20 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) stats->rx_avg_len); seq_puts(m, "RX count:\n"); + for (i = 0; i < ARRAY_SIZE(rtw89_rx_rate_cnt_infos); i++) { info = &rtw89_rx_rate_cnt_infos[i]; + first_rate = info->first_rate[chip->chip_gen]; + if (first_rate >= RTW89_HW_RATE_NR) + continue; + seq_printf(m, "%10s [", info->rate_mode); rtw89_debug_append_rx_rate(m, pkt_stat, - info->first_rate, info->len); + first_rate, info->len); if (info->ext) { seq_puts(m, "]["); rtw89_debug_append_rx_rate(m, pkt_stat, - info->first_rate + info->len, info->ext); + first_rate + info->len, info->ext); } seq_puts(m, "]\n"); } -- cgit From 023d2f14abf806ae1231e567e8bded78e83abdc0 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 28 Jul 2023 15:02:52 +0800 Subject: wifi: rtw89: get data rate mode/NSS/MCS v1 from RX descriptor The data rate from RX descriptor also uses hardware rate v1 for WiFi 7 chips. The rate code contains three parts -- mode, NSS and MCS. For CCK/OFDM/HT rates, NSS/MCS parts are the same as before. VHT/HE/EHT rates are changed and listed as below: mode NSS MCS V0 [8:7] [6:4] [3:0] V1 [10:8] [7:5] [4:0] Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230728070252.66525-11-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 24 ++++++++-------- drivers/net/wireless/realtek/rtw89/phy.c | 2 +- drivers/net/wireless/realtek/rtw89/txrx.h | 47 +++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 69b181fa2966..ec244849e501 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1456,16 +1456,16 @@ static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev, bool ret; data_rate = desc_info->data_rate; - data_rate_mode = GET_DATA_RATE_MODE(data_rate); + data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate); if (data_rate_mode == DATA_RATE_MODE_NON_HT) { - rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); + rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate); /* rate_idx is still hardware value here */ } else if (data_rate_mode == DATA_RATE_MODE_HT) { - rate_idx = GET_DATA_RATE_HT_IDX(data_rate); + rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate); } else if (data_rate_mode == DATA_RATE_MODE_VHT) { - rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); + rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); } else if (data_rate_mode == DATA_RATE_MODE_HE) { - rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); + rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } @@ -1929,26 +1929,26 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rx_status->bw = rtw89_hw_to_rate_info_bw(desc_info->bw); data_rate = desc_info->data_rate; - data_rate_mode = GET_DATA_RATE_MODE(data_rate); + data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate); if (data_rate_mode == DATA_RATE_MODE_NON_HT) { rx_status->encoding = RX_ENC_LEGACY; - rx_status->rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); + rx_status->rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate); /* convert rate_idx after we get the correct band */ } else if (data_rate_mode == DATA_RATE_MODE_HT) { rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = GET_DATA_RATE_HT_IDX(data_rate); + rx_status->rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate); if (desc_info->gi_ltf) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; } else if (data_rate_mode == DATA_RATE_MODE_VHT) { rx_status->encoding = RX_ENC_VHT; - rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); - rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; + rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); + rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; if (desc_info->gi_ltf) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; } else if (data_rate_mode == DATA_RATE_MODE_HE) { rx_status->encoding = RX_ENC_HE; - rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); - rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; + rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); + rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 1940f4457677..abe0f5179a38 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -3014,7 +3014,7 @@ static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct rtw89_antdiv_stats *stats) { - if (GET_DATA_RATE_MODE(phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) { + if (rtw89_get_data_rate_mode(rtwdev, phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) { if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) { ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg); stats->pkt_cnt_cck++; diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index ec96da36eacc..02cff0f7d86b 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -8,19 +8,56 @@ #include "debug.h" #define DATA_RATE_MODE_CTRL_MASK GENMASK(8, 7) +#define DATA_RATE_MODE_CTRL_MASK_V1 GENMASK(10, 8) #define DATA_RATE_NOT_HT_IDX_MASK GENMASK(3, 0) #define DATA_RATE_MODE_NON_HT 0x0 #define DATA_RATE_HT_IDX_MASK GENMASK(4, 0) +#define DATA_RATE_HT_IDX_MASK_V1 GENMASK(4, 0) #define DATA_RATE_MODE_HT 0x1 #define DATA_RATE_VHT_HE_NSS_MASK GENMASK(6, 4) #define DATA_RATE_VHT_HE_IDX_MASK GENMASK(3, 0) +#define DATA_RATE_NSS_MASK_V1 GENMASK(7, 5) +#define DATA_RATE_MCS_MASK_V1 GENMASK(4, 0) #define DATA_RATE_MODE_VHT 0x2 #define DATA_RATE_MODE_HE 0x3 -#define GET_DATA_RATE_MODE(r) FIELD_GET(DATA_RATE_MODE_CTRL_MASK, r) -#define GET_DATA_RATE_NOT_HT_IDX(r) FIELD_GET(DATA_RATE_NOT_HT_IDX_MASK, r) -#define GET_DATA_RATE_HT_IDX(r) FIELD_GET(DATA_RATE_HT_IDX_MASK, r) -#define GET_DATA_RATE_VHT_HE_IDX(r) FIELD_GET(DATA_RATE_VHT_HE_IDX_MASK, r) -#define GET_DATA_RATE_NSS(r) FIELD_GET(DATA_RATE_VHT_HE_NSS_MASK, r) +#define DATA_RATE_MODE_EHT 0x4 + +static inline u8 rtw89_get_data_rate_mode(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_MODE_CTRL_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_MODE_CTRL_MASK); +} + +static inline u8 rtw89_get_data_not_ht_idx(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + return u16_get_bits(hw_rate, DATA_RATE_NOT_HT_IDX_MASK); +} + +static inline u8 rtw89_get_data_ht_mcs(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_HT_IDX_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_HT_IDX_MASK); +} + +static inline u8 rtw89_get_data_mcs(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_MCS_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_VHT_HE_IDX_MASK); +} + +static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_NSS_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_VHT_HE_NSS_MASK); +} /* TX WD BODY DWORD 0 */ #define RTW89_TXWD_BODY0_WP_OFFSET GENMASK(31, 24) -- cgit From 646462f860f12a2e24e6b2ed856cf6645c02397d Mon Sep 17 00:00:00 2001 From: Prasurjya Rohan Saikia Date: Mon, 10 Jul 2023 09:44:03 +0000 Subject: wifi: wilc1000: remove use of has_thrpt_enh3 flag The 'enhance throughput flow' algorithm is used by default. So older sections of the code are removed so as to always use this new algorithm. Signed-off-by: Prasurjya Rohan Saikia Acked-by: Ajay Kathat Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230710094401.235222-1-prasurjya.rohansaikia@microchip.com --- drivers/net/wireless/microchip/wilc1000/sdio.c | 103 +++---------------------- 1 file changed, 10 insertions(+), 93 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index a05bda7b9a3b..87948ba69a22 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -28,7 +28,6 @@ struct wilc_sdio { bool irq_gpio; u32 block_size; bool isinit; - int has_thrpt_enh3; u8 *cmd53_buf; }; @@ -722,21 +721,12 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) * make sure can read back chip id correctly **/ if (!resume) { - int rev; - ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid); if (ret) { dev_err(&func->dev, "Fail cmd read chip id...\n"); return ret; } dev_err(&func->dev, "chipid (%08x)\n", chipid); - rev = FIELD_GET(WILC_CHIP_REV_FIELD, chipid); - if (rev > FIELD_GET(WILC_CHIP_REV_FIELD, WILC_1000_BASE_ID_2A)) - sdio_priv->has_thrpt_enh3 = 1; - else - sdio_priv->has_thrpt_enh3 = 0; - dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", - sdio_priv->has_thrpt_enh3); } sdio_priv->isinit = true; @@ -809,102 +799,29 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; int ret; - int vmm_ctl; - - if (sdio_priv->has_thrpt_enh3) { - u32 reg = 0; - - if (sdio_priv->irq_gpio) - reg = val & (BIT(MAX_NUM_INT) - 1); - - /* select VMM table 0 */ - if (val & SEL_VMM_TBL0) - reg |= BIT(5); - /* select VMM table 1 */ - if (val & SEL_VMM_TBL1) - reg |= BIT(6); - /* enable VMM */ - if (val & EN_VMM) - reg |= BIT(7); - if (reg) { - struct sdio_cmd52 cmd; - - cmd.read_write = 1; - cmd.function = 0; - cmd.raw = 0; - cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; - cmd.data = reg; - - ret = wilc_sdio_cmd52(wilc, &cmd); - if (ret) { - dev_err(&func->dev, - "Failed cmd52, set (%02x) data (%d) ...\n", - cmd.address, __LINE__); - return ret; - } - } - return 0; - } - if (sdio_priv->irq_gpio) { - /* has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ - /* - * Cannot clear multiple interrupts. - * Must clear each interrupt individually. - */ - u32 flags; - int i; - - flags = val & (BIT(MAX_NUM_INT) - 1); - for (i = 0; i < NUM_INT_EXT && flags; i++) { - if (flags & BIT(i)) { - struct sdio_cmd52 cmd; - - cmd.read_write = 1; - cmd.function = 0; - cmd.raw = 0; - cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; - cmd.data = BIT(i); - - ret = wilc_sdio_cmd52(wilc, &cmd); - if (ret) { - dev_err(&func->dev, - "Failed cmd52, set (%02x) data (%d) ...\n", - cmd.address, __LINE__); - return ret; - } - flags &= ~BIT(i); - } - } + u32 reg = 0; - for (i = NUM_INT_EXT; i < MAX_NUM_INT && flags; i++) { - if (flags & BIT(i)) { - dev_err(&func->dev, - "Unexpected interrupt cleared %d...\n", - i); - flags &= ~BIT(i); - } - } - } + if (sdio_priv->irq_gpio) + reg = val & (BIT(MAX_NUM_INT) - 1); - vmm_ctl = 0; /* select VMM table 0 */ if (val & SEL_VMM_TBL0) - vmm_ctl |= BIT(0); + reg |= BIT(5); /* select VMM table 1 */ if (val & SEL_VMM_TBL1) - vmm_ctl |= BIT(1); + reg |= BIT(6); /* enable VMM */ if (val & EN_VMM) - vmm_ctl |= BIT(2); - - if (vmm_ctl) { + reg |= BIT(7); + if (reg) { struct sdio_cmd52 cmd; cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; - cmd.address = WILC_SDIO_VMM_TBL_CTRL_REG; - cmd.data = vmm_ctl; + cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; + cmd.data = reg; + ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, -- cgit From 11958528161731c58e105b501ed60b83a91ea941 Mon Sep 17 00:00:00 2001 From: Polaris Pi Date: Sun, 23 Jul 2023 07:07:41 +0000 Subject: wifi: mwifiex: Fix OOB and integer underflow when rx packets Make sure mwifiex_process_mgmt_packet, mwifiex_process_sta_rx_packet and mwifiex_process_uap_rx_packet, mwifiex_uap_queue_bridged_pkt and mwifiex_process_rx_packet not out-of-bounds access the skb->data buffer. Fixes: 2dbaf751b1de ("mwifiex: report received management frames to cfg80211") Signed-off-by: Polaris Pi Reviewed-by: Matthew Wang Reviewed-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230723070741.1544662-1-pinkperfect2021@gmail.com --- drivers/net/wireless/marvell/mwifiex/sta_rx.c | 11 ++++++++++- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 19 +++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/util.c | 10 +++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index 13659b02ba88..f2899d53a43f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -86,6 +86,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; + if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { + mwifiex_dbg(priv->adapter, ERROR, + "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", + skb->len, rx_pkt_off); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, sizeof(bridge_tunnel_header))) || (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, @@ -194,7 +202,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; - if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { + if ((rx_pkt_offset + rx_pkt_length) > skb->len || + sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) { mwifiex_dbg(adapter, ERROR, "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, rx_pkt_offset, rx_pkt_length); diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index e495f7eaea03..04ff051f5d18 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -103,6 +103,15 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, return; } + if (sizeof(*rx_pkt_hdr) + + le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) { + mwifiex_dbg(adapter, ERROR, + "wrong rx packet offset: len=%d,rx_pkt_offset=%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, sizeof(bridge_tunnel_header))) || (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, @@ -367,6 +376,16 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) + + sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) { + mwifiex_dbg(adapter, ERROR, + "wrong rx packet for struct ethhdr: len=%d, offset=%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source); if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 94c2d219835d..745b1d925b21 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -393,11 +393,15 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, } rx_pd = (struct rxpd *)skb->data; + pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) { + mwifiex_dbg(priv->adapter, ERROR, "invalid rx_pkt_length"); + return -1; + } skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); skb_pull(skb, sizeof(pkt_len)); - - pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + pkt_len -= sizeof(pkt_len); ieee_hdr = (void *)skb->data; if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { @@ -410,7 +414,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, skb->data + sizeof(struct ieee80211_hdr), pkt_len - sizeof(struct ieee80211_hdr)); - pkt_len -= ETH_ALEN + sizeof(pkt_len); + pkt_len -= ETH_ALEN; rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, -- cgit From 6fd879f9783bdbaea758681b9d4e2e7c306293fd Mon Sep 17 00:00:00 2001 From: Amisha Patel Date: Mon, 24 Jul 2023 16:40:00 +0000 Subject: wifi: wilc1000: add SPI commands retry mechanism In some situations like, chip wake-up with powersave enabled, SPI commands are failing temporarily. Reissuing commands after reset helps to overcome the failure. So, add the retry limit and reset command sequence API for read/write SPI commands. Signed-off-by: Amisha Patel Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230724163955.4583-1-amisha.patel@microchip.com --- drivers/net/wireless/microchip/wilc1000/spi.c | 148 ++++++++++++++++++-------- 1 file changed, 103 insertions(+), 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index b0fc5e68feec..77b4cdff73c3 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -74,6 +74,7 @@ static int wilc_spi_reset(struct wilc *wilc); #define CMD_SINGLE_READ 0xca #define CMD_RESET 0xcf +#define SPI_RETRY_MAX_LIMIT 10 #define SPI_ENABLE_VMM_RETRY_LIMIT 2 /* SPI response fields (section 11.1.2 in ATWILC1000 User Guide): */ @@ -830,59 +831,91 @@ static int wilc_spi_special_cmd(struct wilc *wilc, u8 cmd) return 0; } +static void wilc_spi_reset_cmd_sequence(struct wilc *wl, u8 attempt, u32 addr) +{ + struct spi_device *spi = to_spi_device(wl->dev); + struct wilc_spi *spi_priv = wl->bus_data; + + if (!spi_priv->probing_crc) + dev_err(&spi->dev, "Reset and retry %d %x\n", attempt, addr); + + usleep_range(1000, 1100); + wilc_spi_reset(wl); + usleep_range(1000, 1100); +} + static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) { struct spi_device *spi = to_spi_device(wilc->dev); int result; u8 cmd = CMD_SINGLE_READ; u8 clockless = 0; + u8 i; - if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) { + if (addr <= WILC_SPI_CLOCKLESS_ADDR_LIMIT) { /* Clockless register */ cmd = CMD_INTERNAL_READ; clockless = 1; } - result = wilc_spi_single_read(wilc, cmd, addr, data, clockless); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_single_read(wilc, cmd, addr, data, clockless); + if (!result) { + le32_to_cpus(data); + return 0; + } + + /* retry is not applicable for clockless registers */ + if (clockless) + break; + dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr); - return result; + wilc_spi_reset_cmd_sequence(wilc, i, addr); } - le32_to_cpus(data); - - return 0; + return result; } static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; if (size <= 4) return -EINVAL; - result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_READ, addr, buf, size); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_READ, addr, + buf, size); + if (!result) + return 0; + dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr); - return result; + + wilc_spi_reset_cmd_sequence(wilc, i, addr); } - return 0; + return result; } static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; - result = wilc_spi_write_cmd(wilc, CMD_INTERNAL_WRITE, adr, dat, 0); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_write_cmd(wilc, CMD_INTERNAL_WRITE, adr, + dat, 0); + if (!result) + return 0; dev_err(&spi->dev, "Failed internal write cmd...\n"); - return result; + + wilc_spi_reset_cmd_sequence(wilc, i, adr); } - return 0; + return result; } static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) @@ -890,17 +923,22 @@ static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; int result; + u8 i; - result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, data, 0); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, + data, 0); + if (!result) { + le32_to_cpus(data); + return 0; + } if (!spi_priv->probing_crc) dev_err(&spi->dev, "Failed internal read cmd...\n"); - return result; - } - le32_to_cpus(data); + wilc_spi_reset_cmd_sequence(wilc, i, adr); + } - return 0; + return result; } /******************************************** @@ -915,20 +953,27 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) int result; u8 cmd = CMD_SINGLE_WRITE; u8 clockless = 0; + u8 i; - if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) { + if (addr <= WILC_SPI_CLOCKLESS_ADDR_LIMIT) { /* Clockless register */ cmd = CMD_INTERNAL_WRITE; clockless = 1; } - result = wilc_spi_write_cmd(wilc, cmd, addr, data, clockless); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_write_cmd(wilc, cmd, addr, data, clockless); + if (!result) + return 0; + dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr); - return result; - } - return 0; + if (clockless) + break; + + wilc_spi_reset_cmd_sequence(wilc, i, addr); + } + return result; } static int spi_data_rsp(struct wilc *wilc, u8 cmd) @@ -981,6 +1026,7 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; /* * has to be greated than 4 @@ -988,26 +1034,38 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) if (size <= 4) return -EINVAL; - result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_WRITE, addr, NULL, size); - if (result) { - dev_err(&spi->dev, - "Failed cmd, write block (%08x)...\n", addr); - return result; - } + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_WRITE, addr, + NULL, size); + if (result) { + dev_err(&spi->dev, + "Failed cmd, write block (%08x)...\n", addr); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } - /* - * Data - */ - result = spi_data_write(wilc, buf, size); - if (result) { - dev_err(&spi->dev, "Failed block data write...\n"); - return result; - } + /* + * Data + */ + result = spi_data_write(wilc, buf, size); + if (result) { + dev_err(&spi->dev, "Failed block data write...\n"); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } - /* - * Data response - */ - return spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); + /* + * Data response + */ + result = spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); + if (result) { + dev_err(&spi->dev, "Failed block data rsp...\n"); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } + break; + } + return result; } /******************************************** -- cgit From e7899a90cebec045ce88505d496d8453174044c2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 24 Jul 2023 15:19:13 -0600 Subject: wifi: drivers: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230724211914.805876-1-robh@kernel.org --- drivers/net/wireless/ath/ath10k/ahb.c | 2 +- drivers/net/wireless/ath/ath11k/qmi.c | 1 - drivers/net/wireless/ath/wcn36xx/main.c | 3 +-- drivers/net/wireless/intersil/orinoco/airport.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 1 - drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + drivers/net/wireless/silabs/wfx/bus_sdio.c | 2 +- 8 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 4a006fb4d424..76efea2f1138 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -5,7 +5,7 @@ */ #include #include -#include +#include #include #include #include "core.h" diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index d4eaf7d2ba84..98efa0f299ca 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 8dbd115a393c..2bd1163177f0 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -19,9 +19,8 @@ #include #include #include +#include #include -#include -#include #include #include #include diff --git a/drivers/net/wireless/intersil/orinoco/airport.c b/drivers/net/wireless/intersil/orinoco/airport.c index a890bfa0d5cc..45ac00fdafa5 100644 --- a/drivers/net/wireless/intersil/orinoco/airport.c +++ b/drivers/net/wireless/intersil/orinoco/airport.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include "orinoco.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ac2049f49bb3..aec47de35f53 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "mt7915.h" #include "mac.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 32c137066e7f..701a27ffa4c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index f1b48cdda58f..5c980534f611 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -4,6 +4,7 @@ */ #include +#include #include #include "mt7996.h" #include "mac.h" diff --git a/drivers/net/wireless/silabs/wfx/bus_sdio.c b/drivers/net/wireless/silabs/wfx/bus_sdio.c index 51a0d58a9070..909d5f346a01 100644 --- a/drivers/net/wireless/silabs/wfx/bus_sdio.c +++ b/drivers/net/wireless/silabs/wfx/bus_sdio.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include -- cgit From c1861ff1d63d0a185df6e2f0ec21455467aeb16c Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:43 +0300 Subject: wifi: libertas: add missing calls to cancel_work_sync() Add missing 'cancel_work_sync()' in 'if_sdio_remove()' and on error handling path in 'if_sdio_probe()'. Signed-off-by: Dmitry Antipov Tested-by: Dan Williams Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/if_sdio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index a63c5e622ee3..a35b33e84670 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1233,6 +1233,7 @@ err_activate_card: flush_workqueue(card->workqueue); lbs_remove_card(priv); free: + cancel_work_sync(&card->packet_worker); destroy_workqueue(card->workqueue); err_queue: while (card->packets) { @@ -1277,6 +1278,7 @@ static void if_sdio_remove(struct sdio_func *func) lbs_stop_card(card->priv); lbs_remove_card(card->priv); + cancel_work_sync(&card->packet_worker); destroy_workqueue(card->workqueue); while (card->packets) { -- cgit From ce44fdf9c9d28e0d1ee99d77e11b182a7e5aa729 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:44 +0300 Subject: wifi: libertas: use convenient lists to manage SDIO packets Use convenient lists to manage SDIO packets, adjust 'struct if_sdio_packet', 'struct if_sdio_card' and related code accordingly. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-2-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/if_sdio.c | 37 +++++++++---------------- 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index a35b33e84670..c72081cf8a85 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -101,7 +101,7 @@ MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); struct if_sdio_packet { - struct if_sdio_packet *next; + struct list_head list; u16 nb; u8 buffer[] __aligned(4); }; @@ -119,7 +119,7 @@ struct if_sdio_card { u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; - struct if_sdio_packet *packets; + struct list_head packets; struct workqueue_struct *workqueue; struct work_struct packet_worker; @@ -404,9 +404,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) while (1) { spin_lock_irqsave(&card->lock, flags); - packet = card->packets; + packet = list_first_entry_or_null(&card->packets, + struct if_sdio_packet, list); if (packet) - card->packets = packet->next; + list_del(&packet->list); spin_unlock_irqrestore(&card->lock, flags); if (!packet) @@ -909,7 +910,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, { int ret; struct if_sdio_card *card; - struct if_sdio_packet *packet, *cur; + struct if_sdio_packet *packet; u16 size; unsigned long flags; @@ -934,7 +935,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv, goto out; } - packet->next = NULL; packet->nb = size; /* @@ -949,14 +949,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, spin_lock_irqsave(&card->lock, flags); - if (!card->packets) - card->packets = packet; - else { - cur = card->packets; - while (cur->next) - cur = cur->next; - cur->next = packet; - } + list_add_tail(&packet->list, &card->packets); switch (type) { case MVMS_CMD: @@ -1137,7 +1130,7 @@ static int if_sdio_probe(struct sdio_func *func, struct lbs_private *priv; int ret, i; unsigned int model; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; for (i = 0;i < func->card->num_info;i++) { if (sscanf(func->card->info[i], @@ -1178,6 +1171,8 @@ static int if_sdio_probe(struct sdio_func *func, } spin_lock_init(&card->lock); + INIT_LIST_HEAD(&card->packets); + card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0); if (unlikely(!card->workqueue)) { ret = -ENOMEM; @@ -1236,11 +1231,8 @@ free: cancel_work_sync(&card->packet_worker); destroy_workqueue(card->workqueue); err_queue: - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); @@ -1250,7 +1242,7 @@ err_queue: static void if_sdio_remove(struct sdio_func *func) { struct if_sdio_card *card; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; card = sdio_get_drvdata(func); @@ -1281,11 +1273,8 @@ static void if_sdio_remove(struct sdio_func *func) cancel_work_sync(&card->packet_worker); destroy_workqueue(card->workqueue); - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); } -- cgit From 2c531d28f8e938db0dfdee16f251b1ca55bc4a8b Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:45 +0300 Subject: wifi: libertas: simplify list operations in free_if_spi_card() Use 'list_for_each_entry_safe()' to simplify list operations in 'free_if_spi_card()'. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-3-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/if_spi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 1225fc0e3352..3d53e444ba19 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -76,16 +76,13 @@ struct if_spi_card { static void free_if_spi_card(struct if_spi_card *card) { - struct list_head *cursor, *next; - struct if_spi_packet *packet; + struct if_spi_packet *packet, *tmp; - list_for_each_safe(cursor, next, &card->cmd_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); + list_for_each_entry_safe(packet, tmp, &card->cmd_packet_list, list) { list_del(&packet->list); kfree(packet); } - list_for_each_safe(cursor, next, &card->data_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); + list_for_each_entry_safe(packet, tmp, &card->data_packet_list, list) { list_del(&packet->list); kfree(packet); } -- cgit From 6c968e90198fbb2d923c4e47b7303c3ad2c25a71 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:46 +0300 Subject: wifi: libertas: cleanup SDIO reset Embed SDIO reset worker in 'struct if_sdio_card' and so drop 'reset_host' and 'card_reset_work' static variables, adjust related code. Not sure whether it's possible to do something useful on 'mmc_add_host()' error, so just add 'dev_err()' to emit an error message. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-4-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/if_sdio.c | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index c72081cf8a85..524034699972 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -123,6 +123,7 @@ struct if_sdio_card { struct workqueue_struct *workqueue; struct work_struct packet_worker; + struct work_struct reset_worker; u8 rx_unit; }; @@ -1022,10 +1023,19 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) } -static struct mmc_host *reset_host; - static void if_sdio_reset_card_worker(struct work_struct *work) { + int ret; + const char *name; + struct device *dev; + struct if_sdio_card *card; + struct mmc_host *reset_host; + + card = container_of(work, struct if_sdio_card, reset_worker); + reset_host = card->func->card->host; + name = card->priv->dev->name; + dev = &card->func->dev; + /* * The actual reset operation must be run outside of lbs_thread. This * is because mmc_remove_host() will cause the device to be instantly @@ -1036,21 +1046,19 @@ static void if_sdio_reset_card_worker(struct work_struct *work) * instance for that reason. */ - pr_info("Resetting card..."); + dev_info(dev, "resetting card %s...", name); mmc_remove_host(reset_host); - mmc_add_host(reset_host); + ret = mmc_add_host(reset_host); + if (ret) + dev_err(dev, "%s: can't add mmc host, error %d\n", name, ret); } -static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker); static void if_sdio_reset_card(struct lbs_private *priv) { struct if_sdio_card *card = priv->card; - if (work_pending(&card_reset_work)) - return; - - reset_host = card->func->card->host; - schedule_work(&card_reset_work); + if (!work_pending(&card->reset_worker)) + schedule_work(&card->reset_worker); } static int if_sdio_power_save(struct lbs_private *priv) @@ -1178,6 +1186,8 @@ static int if_sdio_probe(struct sdio_func *func, ret = -ENOMEM; goto err_queue; } + + INIT_WORK(&card->reset_worker, if_sdio_reset_card_worker); INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); init_waitqueue_head(&card->pwron_waitq); @@ -1229,6 +1239,7 @@ err_activate_card: lbs_remove_card(priv); free: cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); err_queue: list_for_each_entry_safe(packet, tmp, &card->packets, list) @@ -1271,6 +1282,7 @@ static void if_sdio_remove(struct sdio_func *func) lbs_remove_card(card->priv); cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); list_for_each_entry_safe(packet, tmp, &card->packets, list) @@ -1394,8 +1406,6 @@ static void __exit if_sdio_exit_module(void) /* Set the flag as user is removing this module. */ user_rmmod = 1; - cancel_work_sync(&card_reset_work); - sdio_unregister_driver(&if_sdio_driver); } -- cgit From 3e14212f79fd05c4f5bdfa4eba5ae53f75900410 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:47 +0300 Subject: wifi: libertas: handle possible spu_write_u16() errors Check and handle (well, report at least, as it's done through the rest of the module) possible 'spu_write_u16()' errors in 'if_spi_e2h()'. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-5-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/if_spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 3d53e444ba19..8690b0114e23 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -826,11 +826,16 @@ static void if_spi_e2h(struct if_spi_card *card) goto out; /* re-enable the card event interrupt */ - spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, - ~IF_SPI_HICU_CARD_EVENT); + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, + ~IF_SPI_HICU_CARD_EVENT); + if (err) + goto out; /* generate a card interrupt */ - spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT); + err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, + IF_SPI_CIC_HOST_EVENT); + if (err) + goto out; lbs_queue_event(priv, cause & 0xff); out: -- cgit From f5343efdf5b5d66844ce041e5dcd585ee5697747 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 09:04:48 +0300 Subject: wifi: libertas: prefer kstrtoX() for simple integer conversions Prefer 'kstrtoX()' family of functions over 'sscanf()' to convert strings to integers and always check results of the conversions. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725060531.72968-6-dmantipov@yandex.ru --- drivers/net/wireless/marvell/libertas/mesh.c | 51 ++++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c index 90ffe8d1e0e8..2dd635935448 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.c +++ b/drivers/net/wireless/marvell/libertas/mesh.c @@ -188,8 +188,11 @@ static ssize_t anycast_mask_store(struct device *dev, uint32_t datum; int ret; + ret = kstrtouint(buf, 16, &datum); + if (ret) + return ret; + memset(&mesh_access, 0, sizeof(mesh_access)); - sscanf(buf, "%x", &datum); mesh_access.data[0] = cpu_to_le32(datum); ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); @@ -241,15 +244,14 @@ static ssize_t prb_rsp_limit_store(struct device *dev, int ret; unsigned long retry_limit; - memset(&mesh_access, 0, sizeof(mesh_access)); - mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); - ret = kstrtoul(buf, 10, &retry_limit); if (ret) return ret; if (retry_limit > 15) return -ENOTSUPP; + memset(&mesh_access, 0, sizeof(mesh_access)); + mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); mesh_access.data[1] = cpu_to_le32(retry_limit); ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, @@ -285,9 +287,12 @@ static ssize_t lbs_mesh_store(struct device *dev, const char *buf, size_t count) { struct lbs_private *priv = to_net_dev(dev)->ml_priv; - int enable; + int ret, enable; + + ret = kstrtoint(buf, 16, &enable); + if (ret) + return ret; - sscanf(buf, "%x", &enable); enable = !!enable; if (enable == !!priv->mesh_dev) return count; @@ -387,11 +392,13 @@ static ssize_t bootflag_store(struct device *dev, struct device_attribute *attr, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 1)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 1) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); cmd.length = cpu_to_le16(sizeof(uint32_t)); ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, @@ -438,11 +445,14 @@ static ssize_t boottime_store(struct device *dev, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 255) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); + /* A too small boot time will result in the device booting into * standalone (no-host) mode before the host can take control of it, * so the change will be hard to revert. This may be a desired @@ -497,11 +507,13 @@ static ssize_t channel_store(struct device *dev, struct device_attribute *attr, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if (ret != 1 || datum < 1 || datum > 11) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum < 1 || datum > 11) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); cmd.length = cpu_to_le16(sizeof(uint16_t)); ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, @@ -626,11 +638,14 @@ static ssize_t protocol_id_store(struct device *dev, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 255) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); + /* fetch all other Information Element parameters */ ret = mesh_get_default_parameters(dev, &defs); -- cgit From 005c9600003eabcb22336f37e149eed08f0a946a Mon Sep 17 00:00:00 2001 From: Atul Raut Date: Sun, 30 Jul 2023 16:14:42 -0700 Subject: net/macmace: Replace zero-length array with DECLARE_FLEX_ARRAY() helper Since zero-length arrays are deprecated, we are replacing them with C99 flexible-array members. As a result, instead of declaring a zero-length array, use the new DECLARE_FLEX_ARRAY() helper macro. This fixes warnings such as: ./drivers/net/ethernet/apple/macmace.c:80:4-8: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays) Signed-off-by: Atul Raut Link: https://lore.kernel.org/r/20230730231442.15003-1-rauji.raut@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/apple/macmace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c index 8fcaf1639920..8775c3234e91 100644 --- a/drivers/net/ethernet/apple/macmace.c +++ b/drivers/net/ethernet/apple/macmace.c @@ -77,7 +77,7 @@ struct mace_frame { u8 pad4; u32 pad5; u32 pad6; - u8 data[1]; + DECLARE_FLEX_ARRAY(u8, data); /* And frame continues.. */ }; -- cgit From 308d7982dcdc9259ef4a815fe08913087a2c0ea3 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Mon, 31 Jul 2023 10:06:54 +0300 Subject: virtio_net: extract interrupt coalescing settings to a structure Extract interrupt coalescing settings to a structure so that it could be reused in other data structures. Signed-off-by: Gavin Li Reviewed-by: Dragos Tatulea Reviewed-by: Jiri Pirko Acked-by: Jason Wang Acked-by: Michael S. Tsirkin Reviewed-by: Heng Qi Link: https://lore.kernel.org/r/20230731070656.96411-2-gavinl@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1270c8d23463..b1e2e63edd35 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -126,6 +126,11 @@ static const struct virtnet_stat_desc virtnet_rq_stats_desc[] = { #define VIRTNET_SQ_STATS_LEN ARRAY_SIZE(virtnet_sq_stats_desc) #define VIRTNET_RQ_STATS_LEN ARRAY_SIZE(virtnet_rq_stats_desc) +struct virtnet_interrupt_coalesce { + u32 max_packets; + u32 max_usecs; +}; + /* Internal representation of a send virtqueue */ struct send_queue { /* Virtqueue associated with this send _queue */ @@ -281,10 +286,8 @@ struct virtnet_info { u32 speed; /* Interrupt coalescing settings */ - u32 tx_usecs; - u32 rx_usecs; - u32 tx_max_packets; - u32 rx_max_packets; + struct virtnet_interrupt_coalesce intr_coal_tx; + struct virtnet_interrupt_coalesce intr_coal_rx; unsigned long guest_offloads; unsigned long guest_offloads_capable; @@ -3056,8 +3059,8 @@ static int virtnet_send_notf_coal_cmds(struct virtnet_info *vi, return -EINVAL; /* Save parameters */ - vi->tx_usecs = ec->tx_coalesce_usecs; - vi->tx_max_packets = ec->tx_max_coalesced_frames; + vi->intr_coal_tx.max_usecs = ec->tx_coalesce_usecs; + vi->intr_coal_tx.max_packets = ec->tx_max_coalesced_frames; vi->ctrl->coal_rx.rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs); vi->ctrl->coal_rx.rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames); @@ -3069,8 +3072,8 @@ static int virtnet_send_notf_coal_cmds(struct virtnet_info *vi, return -EINVAL; /* Save parameters */ - vi->rx_usecs = ec->rx_coalesce_usecs; - vi->rx_max_packets = ec->rx_max_coalesced_frames; + vi->intr_coal_rx.max_usecs = ec->rx_coalesce_usecs; + vi->intr_coal_rx.max_packets = ec->rx_max_coalesced_frames; return 0; } @@ -3132,10 +3135,10 @@ static int virtnet_get_coalesce(struct net_device *dev, struct virtnet_info *vi = netdev_priv(dev); if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_NOTF_COAL)) { - ec->rx_coalesce_usecs = vi->rx_usecs; - ec->tx_coalesce_usecs = vi->tx_usecs; - ec->tx_max_coalesced_frames = vi->tx_max_packets; - ec->rx_max_coalesced_frames = vi->rx_max_packets; + ec->rx_coalesce_usecs = vi->intr_coal_rx.max_usecs; + ec->tx_coalesce_usecs = vi->intr_coal_tx.max_usecs; + ec->tx_max_coalesced_frames = vi->intr_coal_tx.max_packets; + ec->rx_max_coalesced_frames = vi->intr_coal_rx.max_packets; } else { ec->rx_max_coalesced_frames = 1; @@ -4119,10 +4122,10 @@ static int virtnet_probe(struct virtio_device *vdev) } if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_NOTF_COAL)) { - vi->rx_usecs = 0; - vi->tx_usecs = 0; - vi->tx_max_packets = 0; - vi->rx_max_packets = 0; + vi->intr_coal_rx.max_usecs = 0; + vi->intr_coal_tx.max_usecs = 0; + vi->intr_coal_tx.max_packets = 0; + vi->intr_coal_rx.max_packets = 0; } if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) -- cgit From 394bd87764b615b0fc17d34127a1cc7da76ff49f Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Mon, 31 Jul 2023 10:06:55 +0300 Subject: virtio_net: support per queue interrupt coalesce command Add interrupt_coalesce config in send_queue and receive_queue to cache user config. Send per virtqueue interrupt moderation config to underlying device in order to have more efficient interrupt moderation and cpu utilization of guest VM. Additionally, address all the VQs when updating the global configuration, as now the individual VQs configuration can diverge from the global configuration. Signed-off-by: Gavin Li Reviewed-by: Dragos Tatulea Reviewed-by: Jiri Pirko Acked-by: Michael S. Tsirkin Reviewed-by: Heng Qi Acked-by: Jason Wang Link: https://lore.kernel.org/r/20230731070656.96411-3-gavinl@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 149 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b1e2e63edd35..77805796fddd 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -144,6 +144,8 @@ struct send_queue { struct virtnet_sq_stats stats; + struct virtnet_interrupt_coalesce intr_coal; + struct napi_struct napi; /* Record whether sq is in reset state. */ @@ -161,6 +163,8 @@ struct receive_queue { struct virtnet_rq_stats stats; + struct virtnet_interrupt_coalesce intr_coal; + /* Chain pages by the private ptr. */ struct page *pages; @@ -212,6 +216,7 @@ struct control_buf { struct virtio_net_ctrl_rss rss; struct virtio_net_ctrl_coal_tx coal_tx; struct virtio_net_ctrl_coal_rx coal_rx; + struct virtio_net_ctrl_coal_vq coal_vq; }; struct virtnet_info { @@ -3078,6 +3083,55 @@ static int virtnet_send_notf_coal_cmds(struct virtnet_info *vi, return 0; } +static int virtnet_send_ctrl_coal_vq_cmd(struct virtnet_info *vi, + u16 vqn, u32 max_usecs, u32 max_packets) +{ + struct scatterlist sgs; + + vi->ctrl->coal_vq.vqn = cpu_to_le16(vqn); + vi->ctrl->coal_vq.coal.max_usecs = cpu_to_le32(max_usecs); + vi->ctrl->coal_vq.coal.max_packets = cpu_to_le32(max_packets); + sg_init_one(&sgs, &vi->ctrl->coal_vq, sizeof(vi->ctrl->coal_vq)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL, + VIRTIO_NET_CTRL_NOTF_COAL_VQ_SET, + &sgs)) + return -EINVAL; + + return 0; +} + +static int virtnet_send_notf_coal_vq_cmds(struct virtnet_info *vi, + struct ethtool_coalesce *ec, + u16 queue) +{ + int err; + + if (ec->rx_coalesce_usecs || ec->rx_max_coalesced_frames) { + err = virtnet_send_ctrl_coal_vq_cmd(vi, rxq2vq(queue), + ec->rx_coalesce_usecs, + ec->rx_max_coalesced_frames); + if (err) + return err; + /* Save parameters */ + vi->rq[queue].intr_coal.max_usecs = ec->rx_coalesce_usecs; + vi->rq[queue].intr_coal.max_packets = ec->rx_max_coalesced_frames; + } + + if (ec->tx_coalesce_usecs || ec->tx_max_coalesced_frames) { + err = virtnet_send_ctrl_coal_vq_cmd(vi, txq2vq(queue), + ec->tx_coalesce_usecs, + ec->tx_max_coalesced_frames); + if (err) + return err; + /* Save parameters */ + vi->sq[queue].intr_coal.max_usecs = ec->tx_coalesce_usecs; + vi->sq[queue].intr_coal.max_packets = ec->tx_max_coalesced_frames; + } + + return 0; +} + static int virtnet_coal_params_supported(struct ethtool_coalesce *ec) { /* usecs coalescing is supported only if VIRTIO_NET_F_NOTF_COAL @@ -3093,22 +3147,42 @@ static int virtnet_coal_params_supported(struct ethtool_coalesce *ec) return 0; } +static int virtnet_should_update_vq_weight(int dev_flags, int weight, + int vq_weight, bool *should_update) +{ + if (weight ^ vq_weight) { + if (dev_flags & IFF_UP) + return -EBUSY; + *should_update = true; + } + + return 0; +} + static int virtnet_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec, struct kernel_ethtool_coalesce *kernel_coal, struct netlink_ext_ack *extack) { struct virtnet_info *vi = netdev_priv(dev); - int ret, i, napi_weight; + int ret, queue_number, napi_weight; bool update_napi = false; /* Can't change NAPI weight if the link is up */ napi_weight = ec->tx_max_coalesced_frames ? NAPI_POLL_WEIGHT : 0; - if (napi_weight ^ vi->sq[0].napi.weight) { - if (dev->flags & IFF_UP) - return -EBUSY; - else - update_napi = true; + for (queue_number = 0; queue_number < vi->max_queue_pairs; queue_number++) { + ret = virtnet_should_update_vq_weight(dev->flags, napi_weight, + vi->sq[queue_number].napi.weight, + &update_napi); + if (ret) + return ret; + + if (update_napi) { + /* All queues that belong to [queue_number, vi->max_queue_pairs] will be + * updated for the sake of simplicity, which might not be necessary + */ + break; + } } if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_NOTF_COAL)) @@ -3120,8 +3194,8 @@ static int virtnet_set_coalesce(struct net_device *dev, return ret; if (update_napi) { - for (i = 0; i < vi->max_queue_pairs; i++) - vi->sq[i].napi.weight = napi_weight; + for (; queue_number < vi->max_queue_pairs; queue_number++) + vi->sq[queue_number].napi.weight = napi_weight; } return ret; @@ -3149,6 +3223,63 @@ static int virtnet_get_coalesce(struct net_device *dev, return 0; } +static int virtnet_set_per_queue_coalesce(struct net_device *dev, + u32 queue, + struct ethtool_coalesce *ec) +{ + struct virtnet_info *vi = netdev_priv(dev); + int ret, napi_weight; + bool update_napi = false; + + if (queue >= vi->max_queue_pairs) + return -EINVAL; + + /* Can't change NAPI weight if the link is up */ + napi_weight = ec->tx_max_coalesced_frames ? NAPI_POLL_WEIGHT : 0; + ret = virtnet_should_update_vq_weight(dev->flags, napi_weight, + vi->sq[queue].napi.weight, + &update_napi); + if (ret) + return ret; + + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL)) + ret = virtnet_send_notf_coal_vq_cmds(vi, ec, queue); + else + ret = virtnet_coal_params_supported(ec); + + if (ret) + return ret; + + if (update_napi) + vi->sq[queue].napi.weight = napi_weight; + + return 0; +} + +static int virtnet_get_per_queue_coalesce(struct net_device *dev, + u32 queue, + struct ethtool_coalesce *ec) +{ + struct virtnet_info *vi = netdev_priv(dev); + + if (queue >= vi->max_queue_pairs) + return -EINVAL; + + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL)) { + ec->rx_coalesce_usecs = vi->rq[queue].intr_coal.max_usecs; + ec->tx_coalesce_usecs = vi->sq[queue].intr_coal.max_usecs; + ec->tx_max_coalesced_frames = vi->sq[queue].intr_coal.max_packets; + ec->rx_max_coalesced_frames = vi->rq[queue].intr_coal.max_packets; + } else { + ec->rx_max_coalesced_frames = 1; + + if (vi->sq[0].napi.weight) + ec->tx_max_coalesced_frames = 1; + } + + return 0; +} + static void virtnet_init_settings(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); @@ -3279,6 +3410,8 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .set_link_ksettings = virtnet_set_link_ksettings, .set_coalesce = virtnet_set_coalesce, .get_coalesce = virtnet_get_coalesce, + .set_per_queue_coalesce = virtnet_set_per_queue_coalesce, + .get_per_queue_coalesce = virtnet_get_per_queue_coalesce, .get_rxfh_key_size = virtnet_get_rxfh_key_size, .get_rxfh_indir_size = virtnet_get_rxfh_indir_size, .get_rxfh = virtnet_get_rxfh, -- cgit From 8af3bf668382eeaba90b15bb37d1bd23c6b55a1e Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Mon, 31 Jul 2023 10:06:56 +0300 Subject: virtio_net: enable per queue interrupt coalesce feature Enable per queue interrupt coalesce feature bit in driver and validate its dependency with control queue. Signed-off-by: Gavin Li Reviewed-by: Dragos Tatulea Reviewed-by: Jiri Pirko Acked-by: Michael S. Tsirkin Reviewed-by: Heng Qi Acked-by: Jason Wang Link: https://lore.kernel.org/r/20230731070656.96411-4-gavinl@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 77805796fddd..c615bbf24c0d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -4088,6 +4088,8 @@ static bool virtnet_validate_features(struct virtio_device *vdev) VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_HASH_REPORT, "VIRTIO_NET_F_CTRL_VQ") || VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_NOTF_COAL, + "VIRTIO_NET_F_CTRL_VQ") || + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_VQ_NOTF_COAL, "VIRTIO_NET_F_CTRL_VQ"))) { return false; } @@ -4512,6 +4514,7 @@ static struct virtio_device_id id_table[] = { VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \ VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT, VIRTIO_NET_F_NOTF_COAL, \ + VIRTIO_NET_F_VQ_NOTF_COAL, \ VIRTIO_NET_F_GUEST_HDRLEN static unsigned int features[] = { -- cgit From ac0687e821cffab24da4531372dc67ba2fac843d Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:09 +0300 Subject: net: phy: nxp-c45-tja11xx: use phylib master/slave implementation Remove the custom implementation of master/save setup and read status and use genphy_c45_config_aneg and genphy_c45_read_status since phylib has support for master/slave setup and master/slave status. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-2-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 77 +-------------------------------------- 1 file changed, 2 insertions(+), 75 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 029875a59ff8..41b8af0547e4 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -19,13 +19,6 @@ #define PHY_ID_TJA_1103 0x001BB010 -#define PMAPMD_B100T1_PMAPMD_CTL 0x0834 -#define B100T1_PMAPMD_CONFIG_EN BIT(15) -#define B100T1_PMAPMD_MASTER BIT(14) -#define MASTER_MODE (B100T1_PMAPMD_CONFIG_EN | \ - B100T1_PMAPMD_MASTER) -#define SLAVE_MODE (B100T1_PMAPMD_CONFIG_EN) - #define VEND1_DEVICE_CONTROL 0x0040 #define DEVICE_CONTROL_RESET BIT(15) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) @@ -988,72 +981,6 @@ static int nxp_c45_cable_test_get_status(struct phy_device *phydev, return nxp_c45_start_op(phydev); } -static int nxp_c45_setup_master_slave(struct phy_device *phydev) -{ - switch (phydev->master_slave_set) { - case MASTER_SLAVE_CFG_MASTER_FORCE: - case MASTER_SLAVE_CFG_MASTER_PREFERRED: - phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, - MASTER_MODE); - break; - case MASTER_SLAVE_CFG_SLAVE_PREFERRED: - case MASTER_SLAVE_CFG_SLAVE_FORCE: - phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, - SLAVE_MODE); - break; - case MASTER_SLAVE_CFG_UNKNOWN: - case MASTER_SLAVE_CFG_UNSUPPORTED: - return 0; - default: - phydev_warn(phydev, "Unsupported Master/Slave mode\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static int nxp_c45_read_master_slave(struct phy_device *phydev) -{ - int reg; - - phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; - phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; - - reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL); - if (reg < 0) - return reg; - - if (reg & B100T1_PMAPMD_MASTER) { - phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; - phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; - } else { - phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; - phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; - } - - return 0; -} - -static int nxp_c45_config_aneg(struct phy_device *phydev) -{ - return nxp_c45_setup_master_slave(phydev); -} - -static int nxp_c45_read_status(struct phy_device *phydev) -{ - int ret; - - ret = genphy_c45_read_status(phydev); - if (ret) - return ret; - - ret = nxp_c45_read_master_slave(phydev); - if (ret) - return ret; - - return 0; -} - static int nxp_c45_get_sqi(struct phy_device *phydev) { int reg; @@ -1355,11 +1282,11 @@ static struct phy_driver nxp_c45_driver[] = { .features = PHY_BASIC_T1_FEATURES, .probe = nxp_c45_probe, .soft_reset = nxp_c45_soft_reset, - .config_aneg = nxp_c45_config_aneg, + .config_aneg = genphy_c45_config_aneg, .config_init = nxp_c45_config_init, .config_intr = nxp_c45_config_intr, .handle_interrupt = nxp_c45_handle_interrupt, - .read_status = nxp_c45_read_status, + .read_status = genphy_c45_read_status, .suspend = genphy_c45_pma_suspend, .resume = genphy_c45_pma_resume, .get_sset_count = nxp_c45_get_sset_count, -- cgit From 643480a1a73d489a355e908dc317af889ace127a Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:10 +0300 Subject: net: phy: nxp-c45-tja11xx: remove RX BIST frame counters Remove RX BIST frame counters from the PHY statistics. In production mode, these counters are always read as 0. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-3-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 41b8af0547e4..f1f15a1b6cfc 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -81,9 +81,6 @@ #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 #define VEND1_LINK_DROP_COUNTER 0x8352 #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 -#define VEND1_R_GOOD_FRAME_CNT 0xA950 -#define VEND1_R_BAD_FRAME_CNT 0xA952 -#define VEND1_R_RXER_FRAME_CNT 0xA954 #define VEND1_RX_PREAMBLE_COUNT 0xAFCE #define VEND1_TX_PREAMBLE_COUNT 0xAFCF #define VEND1_RX_IPG_LENGTH 0xAFD0 @@ -809,12 +806,6 @@ static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = { VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) }, { "phy_link_failure_cnt", MDIO_MMD_VEND1, VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) }, - { "r_good_frame_cnt", MDIO_MMD_VEND1, - VEND1_R_GOOD_FRAME_CNT, 0, GENMASK(15, 0) }, - { "r_bad_frame_cnt", MDIO_MMD_VEND1, - VEND1_R_BAD_FRAME_CNT, 0, GENMASK(15, 0) }, - { "r_rxer_frame_cnt", MDIO_MMD_VEND1, - VEND1_R_RXER_FRAME_CNT, 0, GENMASK(15, 0) }, { "rx_preamble_count", MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, { "tx_preamble_count", MDIO_MMD_VEND1, -- cgit From 6c0c85da044e92543a40294f024235f60adc4315 Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:11 +0300 Subject: net: phy: nxp-c45-tja11xx: prepare the ground for TJA1120 Between TJA1120 and TJA1103 the hardware was improved, but some register addresses were changed and some bit fields were moved from one register to another. Introduce the nxp_c45_reg_field structure and its associated functions to abstract the differences between the PHYs. Remove the defined bits and register addresses that are not common between TJA1103 and TJA1120 and replace them with reg_fields and register addresses from phydev->drv->driver_data. Signed-off-by: Radu Pirea (NXP OSS) Link: https://lore.kernel.org/r/20230731091619.77961-4-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 574 +++++++++++++++++++++++++++----------- 1 file changed, 406 insertions(+), 168 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index f1f15a1b6cfc..d5981985b320 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -41,10 +41,8 @@ #define SQI_MASK GENMASK(2, 0) #define MAX_SQI SQI_MASK -#define VEND1_CABLE_TEST 0x8330 #define CABLE_TEST_ENABLE BIT(15) #define CABLE_TEST_START BIT(14) -#define CABLE_TEST_VALID BIT(13) #define CABLE_TEST_OK 0x00 #define CABLE_TEST_SHORTED 0x01 #define CABLE_TEST_OPEN 0x02 @@ -89,59 +87,18 @@ #define VEND1_PTP_CONFIG 0x1102 #define EXT_TRG_EDGE BIT(1) -#define PPS_OUT_POL BIT(2) -#define PPS_OUT_EN BIT(3) -#define VEND1_LTC_LOAD_CTRL 0x1105 -#define READ_LTC BIT(2) -#define LOAD_LTC BIT(0) - -#define VEND1_LTC_WR_NSEC_0 0x1106 -#define VEND1_LTC_WR_NSEC_1 0x1107 -#define VEND1_LTC_WR_SEC_0 0x1108 -#define VEND1_LTC_WR_SEC_1 0x1109 - -#define VEND1_LTC_RD_NSEC_0 0x110A -#define VEND1_LTC_RD_NSEC_1 0x110B -#define VEND1_LTC_RD_SEC_0 0x110C -#define VEND1_LTC_RD_SEC_1 0x110D - -#define VEND1_RATE_ADJ_SUBNS_0 0x110F -#define VEND1_RATE_ADJ_SUBNS_1 0x1110 #define CLK_RATE_ADJ_LD BIT(15) #define CLK_RATE_ADJ_DIR BIT(14) -#define VEND1_HW_LTC_LOCK_CTRL 0x1115 -#define HW_LTC_LOCK_EN BIT(0) - -#define VEND1_PTP_IRQ_EN 0x1131 -#define VEND1_PTP_IRQ_STATUS 0x1132 -#define PTP_IRQ_EGR_TS BIT(0) - #define VEND1_RX_TS_INSRT_CTRL 0x114D -#define RX_TS_INSRT_MODE2 0x02 +#define TJA1103_RX_TS_INSRT_MODE2 0x02 #define VEND1_EGR_RING_DATA_0 0x114E -#define VEND1_EGR_RING_DATA_1_SEQ_ID 0x114F -#define VEND1_EGR_RING_DATA_2_NSEC_15_0 0x1150 -#define VEND1_EGR_RING_DATA_3 0x1151 #define VEND1_EGR_RING_CTRL 0x1154 -#define VEND1_EXT_TRG_TS_DATA_0 0x1121 -#define VEND1_EXT_TRG_TS_DATA_1 0x1122 -#define VEND1_EXT_TRG_TS_DATA_2 0x1123 -#define VEND1_EXT_TRG_TS_DATA_3 0x1124 -#define VEND1_EXT_TRG_TS_DATA_4 0x1125 -#define VEND1_EXT_TRG_TS_CTRL 0x1126 - -#define RING_DATA_0_DOMAIN_NUMBER GENMASK(7, 0) -#define RING_DATA_0_MSG_TYPE GENMASK(11, 8) -#define RING_DATA_0_SEC_4_2 GENMASK(14, 2) #define RING_DATA_0_TS_VALID BIT(15) -#define RING_DATA_3_NSEC_29_16 GENMASK(13, 0) -#define RING_DATA_3_SEC_1_0 GENMASK(15, 14) -#define RING_DATA_5_SEC_16_5 GENMASK(15, 4) #define RING_DONE BIT(0) #define TS_SEC_MASK GENMASK(1, 0) @@ -152,18 +109,11 @@ #define VEND1_PORT_PTP_CONTROL 0x9000 #define PORT_PTP_CONTROL_BYPASS BIT(11) -#define VEND1_PTP_CLK_PERIOD 0x1104 #define PTP_CLK_PERIOD_100BT1 15ULL -#define VEND1_EVENT_MSG_FILT 0x1148 #define EVENT_MSG_FILT_ALL 0x0F #define EVENT_MSG_FILT_NONE 0x00 -#define VEND1_TX_PIPE_DLY_NS 0x1149 -#define VEND1_TX_PIPEDLY_SUBNS 0x114A -#define VEND1_RX_PIPE_DLY_NS 0x114B -#define VEND1_RX_PIPEDLY_SUBNS 0x114C - #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40 #define GPIO_FUNC_EN BIT(15) #define GPIO_FUNC_PTP BIT(6) @@ -181,8 +131,8 @@ #define MAX_ID_PS 2260U #define DEFAULT_ID_PS 2000U -#define PPM_TO_SUBNS_INC(ppb) div_u64(GENMASK_ULL(31, 0) * (ppb) * \ - PTP_CLK_PERIOD_100BT1, NSEC_PER_SEC) +#define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \ + (ppb) * (ptp_clk_period), NSEC_PER_SEC) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) @@ -191,6 +141,21 @@ struct nxp_c45_skb_cb { unsigned int type; }; +#define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size) \ + ((struct nxp_c45_reg_field) { \ + .reg = _reg, \ + .devad = _devad, \ + .offset = _offset, \ + .size = _size, \ + }) + +struct nxp_c45_reg_field { + u16 reg; + u8 devad; + u8 offset; + u8 size; +}; + struct nxp_c45_hwts { u32 nsec; u32 sec; @@ -199,7 +164,69 @@ struct nxp_c45_hwts { u8 msg_type; }; +struct nxp_c45_regmap { + /* PTP config regs. */ + u16 vend1_ptp_clk_period; + u16 vend1_event_msg_filt; + + /* LTC bits and regs. */ + struct nxp_c45_reg_field ltc_read; + struct nxp_c45_reg_field ltc_write; + struct nxp_c45_reg_field ltc_lock_ctrl; + u16 vend1_ltc_wr_nsec_0; + u16 vend1_ltc_wr_nsec_1; + u16 vend1_ltc_wr_sec_0; + u16 vend1_ltc_wr_sec_1; + u16 vend1_ltc_rd_nsec_0; + u16 vend1_ltc_rd_nsec_1; + u16 vend1_ltc_rd_sec_0; + u16 vend1_ltc_rd_sec_1; + u16 vend1_rate_adj_subns_0; + u16 vend1_rate_adj_subns_1; + + /* External trigger reg fields. */ + struct nxp_c45_reg_field irq_egr_ts_en; + struct nxp_c45_reg_field irq_egr_ts_status; + struct nxp_c45_reg_field domain_number; + struct nxp_c45_reg_field msg_type; + struct nxp_c45_reg_field sequence_id; + struct nxp_c45_reg_field sec_1_0; + struct nxp_c45_reg_field sec_4_2; + struct nxp_c45_reg_field nsec_15_0; + struct nxp_c45_reg_field nsec_29_16; + + /* PPS and EXT Trigger bits and regs. */ + struct nxp_c45_reg_field pps_enable; + struct nxp_c45_reg_field pps_polarity; + u16 vend1_ext_trg_data_0; + u16 vend1_ext_trg_data_1; + u16 vend1_ext_trg_data_2; + u16 vend1_ext_trg_data_3; + u16 vend1_ext_trg_ctrl; + + /* Cable test reg fields. */ + u16 cable_test; + struct nxp_c45_reg_field cable_test_valid; + struct nxp_c45_reg_field cable_test_result; +}; + +struct nxp_c45_phy_stats { + const char *name; + const struct nxp_c45_reg_field counter; +}; + +struct nxp_c45_phy_data { + const struct nxp_c45_regmap *regmap; + const struct nxp_c45_phy_stats *stats; + int n_stats; + u8 ptp_clk_period; + void (*counters_enable)(struct phy_device *phydev); + void (*ptp_init)(struct phy_device *phydev); + void (*ptp_enable)(struct phy_device *phydev, bool enable); +}; + struct nxp_c45_phy { + const struct nxp_c45_phy_data *phy_data; struct phy_device *phydev; struct mii_timestamper mii_ts; struct ptp_clock *ptp_clock; @@ -217,13 +244,86 @@ struct nxp_c45_phy { bool extts; }; -struct nxp_c45_phy_stats { - const char *name; - u8 mmd; - u16 reg; - u8 off; - u16 mask; -}; +static const +struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev) +{ + return phydev->drv->driver_data; +} + +static const +struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev) +{ + const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); + + return phy_data->regmap; +} + +static int nxp_c45_read_reg_field(struct phy_device *phydev, + const struct nxp_c45_reg_field *reg_field) +{ + u16 mask; + int ret; + + if (reg_field->size == 0) { + phydev_err(phydev, "Trying to read a reg field of size 0.\n"); + return -EINVAL; + } + + ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg); + if (ret < 0) + return ret; + + mask = reg_field->size == 1 ? BIT(reg_field->offset) : + GENMASK(reg_field->offset + reg_field->size - 1, + reg_field->offset); + ret &= mask; + ret >>= reg_field->offset; + + return ret; +} + +static int nxp_c45_write_reg_field(struct phy_device *phydev, + const struct nxp_c45_reg_field *reg_field, + u16 val) +{ + u16 mask; + u16 set; + + if (reg_field->size == 0) { + phydev_err(phydev, "Trying to write a reg field of size 0.\n"); + return -EINVAL; + } + + mask = reg_field->size == 1 ? BIT(reg_field->offset) : + GENMASK(reg_field->offset + reg_field->size - 1, + reg_field->offset); + set = val << reg_field->offset; + + return phy_modify_mmd_changed(phydev, reg_field->devad, + reg_field->reg, mask, set); +} + +static int nxp_c45_set_reg_field(struct phy_device *phydev, + const struct nxp_c45_reg_field *reg_field) +{ + if (reg_field->size != 1) { + phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); + return -EINVAL; + } + + return nxp_c45_write_reg_field(phydev, reg_field, 1); +} + +static int nxp_c45_clear_reg_field(struct phy_device *phydev, + const struct nxp_c45_reg_field *reg_field) +{ + if (reg_field->size != 1) { + phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); + return -EINVAL; + } + + return nxp_c45_write_reg_field(phydev, reg_field, 0); +} static bool nxp_c45_poll_txts(struct phy_device *phydev) { @@ -235,17 +335,17 @@ static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, struct ptp_system_timestamp *sts) { struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL, - READ_LTC); + nxp_c45_set_reg_field(priv->phydev, ®map->ltc_read); ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_LTC_RD_NSEC_0); + regmap->vend1_ltc_rd_nsec_0); ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_LTC_RD_NSEC_1) << 16; + regmap->vend1_ltc_rd_nsec_1) << 16; ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_LTC_RD_SEC_0); + regmap->vend1_ltc_rd_sec_0); ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_LTC_RD_SEC_1) << 16; + regmap->vend1_ltc_rd_sec_1) << 16; return 0; } @@ -267,17 +367,17 @@ static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_0, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0, ts->tv_nsec); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_1, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1, ts->tv_nsec >> 16); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_0, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0, ts->tv_sec); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_1, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1, ts->tv_sec >> 16); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL, - LOAD_LTC); + nxp_c45_set_reg_field(priv->phydev, ®map->ltc_write); return 0; } @@ -297,6 +397,8 @@ static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) { struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); + const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); + const struct nxp_c45_regmap *regmap = data->regmap; s32 ppb = scaled_ppm_to_ppb(scaled_ppm); u64 subns_inc_val; bool inc; @@ -305,16 +407,18 @@ static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) inc = ppb >= 0; ppb = abs(ppb); - subns_inc_val = PPM_TO_SUBNS_INC(ppb); + subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_0, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, + regmap->vend1_rate_adj_subns_0, subns_inc_val); subns_inc_val >>= 16; subns_inc_val |= CLK_RATE_ADJ_LD; if (inc) subns_inc_val |= CLK_RATE_ADJ_DIR; - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_1, + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, + regmap->vend1_rate_adj_subns_1, subns_inc_val); mutex_unlock(&priv->ptp_lock); @@ -358,21 +462,25 @@ static bool nxp_c45_match_ts(struct ptp_header *header, static void nxp_c45_get_extts(struct nxp_c45_phy *priv, struct timespec64 *extts) { + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); + extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EXT_TRG_TS_DATA_0); + regmap->vend1_ext_trg_data_0); extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EXT_TRG_TS_DATA_1) << 16; + regmap->vend1_ext_trg_data_1) << 16; extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EXT_TRG_TS_DATA_2); + regmap->vend1_ext_trg_data_2); extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EXT_TRG_TS_DATA_3) << 16; - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_CTRL, - RING_DONE); + regmap->vend1_ext_trg_data_3) << 16; + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, + regmap->vend1_ext_trg_ctrl, RING_DONE); } static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, struct nxp_c45_hwts *hwts) { + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); + struct phy_device *phydev = priv->phydev; bool valid; u16 reg; @@ -384,16 +492,18 @@ static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, if (!valid) goto nxp_c45_get_hwtxts_out; - hwts->domain_number = reg; - hwts->msg_type = (reg & RING_DATA_0_MSG_TYPE) >> 8; - hwts->sec = (reg & RING_DATA_0_SEC_4_2) >> 10; - hwts->sequence_id = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EGR_RING_DATA_1_SEQ_ID); - hwts->nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_EGR_RING_DATA_2_NSEC_15_0); - reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_3); - hwts->nsec |= (reg & RING_DATA_3_NSEC_29_16) << 16; - hwts->sec |= (reg & RING_DATA_3_SEC_1_0) >> 14; + hwts->domain_number = + nxp_c45_read_reg_field(phydev, ®map->domain_number); + hwts->msg_type = + nxp_c45_read_reg_field(phydev, ®map->msg_type); + hwts->sequence_id = + nxp_c45_read_reg_field(phydev, ®map->sequence_id); + hwts->nsec = + nxp_c45_read_reg_field(phydev, ®map->nsec_15_0); + hwts->nsec |= + nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16; + hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0); + hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2; nxp_c45_get_hwtxts_out: mutex_unlock(&priv->ptp_lock); @@ -498,6 +608,7 @@ static void nxp_c45_gpio_config(struct nxp_c45_phy *priv, static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, struct ptp_perout_request *perout, int on) { + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); struct phy_device *phydev = priv->phydev; int pin; @@ -509,10 +620,10 @@ static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, return pin; if (!on) { - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, - PPS_OUT_EN); - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, - PPS_OUT_POL); + nxp_c45_clear_reg_field(priv->phydev, + ®map->pps_enable); + nxp_c45_clear_reg_field(priv->phydev, + ®map->pps_polarity); nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); @@ -541,16 +652,16 @@ static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, } if (perout->phase.nsec == 0) - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, - VEND1_PTP_CONFIG, PPS_OUT_POL); + nxp_c45_clear_reg_field(priv->phydev, + ®map->pps_polarity); else - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, - VEND1_PTP_CONFIG, PPS_OUT_POL); + nxp_c45_set_reg_field(priv->phydev, + ®map->pps_polarity); } nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, PPS_OUT_EN); + nxp_c45_set_reg_field(priv->phydev, ®map->pps_enable); return 0; } @@ -725,6 +836,7 @@ static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, mii_ts); struct phy_device *phydev = priv->phydev; + const struct nxp_c45_phy_data *data; struct hwtstamp_config cfg; if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg))) @@ -733,6 +845,7 @@ static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON) return -ERANGE; + data = nxp_c45_get_data(phydev); priv->hwts_tx = cfg.tx_type; switch (cfg.rx_filter) { @@ -750,27 +863,24 @@ static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, } if (priv->hwts_rx || priv->hwts_tx) { - phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT, + phy_write_mmd(phydev, MDIO_MMD_VEND1, + data->regmap->vend1_event_msg_filt, EVENT_MSG_FILT_ALL); - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, - VEND1_PORT_PTP_CONTROL, - PORT_PTP_CONTROL_BYPASS); + data->ptp_enable(phydev, true); } else { - phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT, + phy_write_mmd(phydev, MDIO_MMD_VEND1, + data->regmap->vend1_event_msg_filt, EVENT_MSG_FILT_NONE); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_PTP_CONTROL, - PORT_PTP_CONTROL_BYPASS); + data->ptp_enable(phydev, false); } if (nxp_c45_poll_txts(priv->phydev)) goto nxp_c45_no_ptp_irq; if (priv->hwts_tx) - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, - VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS); + nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en); else - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, - VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS); + nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en); nxp_c45_no_ptp_irq: return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; @@ -795,57 +905,79 @@ static int nxp_c45_ts_info(struct mii_timestamper *mii_ts, return 0; } -static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = { - { "phy_symbol_error_cnt", MDIO_MMD_VEND1, - VEND1_SYMBOL_ERROR_COUNTER, 0, GENMASK(15, 0) }, - { "phy_link_status_drop_cnt", MDIO_MMD_VEND1, - VEND1_LINK_DROP_COUNTER, 8, GENMASK(13, 8) }, - { "phy_link_availability_drop_cnt", MDIO_MMD_VEND1, - VEND1_LINK_DROP_COUNTER, 0, GENMASK(5, 0) }, - { "phy_link_loss_cnt", MDIO_MMD_VEND1, - VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) }, - { "phy_link_failure_cnt", MDIO_MMD_VEND1, - VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) }, - { "rx_preamble_count", MDIO_MMD_VEND1, - VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, - { "tx_preamble_count", MDIO_MMD_VEND1, - VEND1_TX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, - { "rx_ipg_length", MDIO_MMD_VEND1, - VEND1_RX_IPG_LENGTH, 0, GENMASK(8, 0) }, - { "tx_ipg_length", MDIO_MMD_VEND1, - VEND1_TX_IPG_LENGTH, 0, GENMASK(8, 0) }, +static const struct nxp_c45_phy_stats common_hw_stats[] = { + { "phy_link_status_drop_cnt", + NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), }, + { "phy_link_availability_drop_cnt", + NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), }, + { "phy_link_loss_cnt", + NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), }, + { "phy_link_failure_cnt", + NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), }, + { "phy_symbol_error_cnt", + NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) }, +}; + +static const struct nxp_c45_phy_stats tja1103_hw_stats[] = { + { "rx_preamble_count", + NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), }, + { "tx_preamble_count", + NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), }, + { "rx_ipg_length", + NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), }, + { "tx_ipg_length", + NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), }, }; static int nxp_c45_get_sset_count(struct phy_device *phydev) { - return ARRAY_SIZE(nxp_c45_hw_stats); + const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); + + return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0); } static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) { + const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); + size_t count = nxp_c45_get_sset_count(phydev); + size_t idx; size_t i; - for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { - strncpy(data + i * ETH_GSTRING_LEN, - nxp_c45_hw_stats[i].name, ETH_GSTRING_LEN); + for (i = 0; i < count; i++) { + if (i < ARRAY_SIZE(common_hw_stats)) { + strscpy(data + i * ETH_GSTRING_LEN, + common_hw_stats[i].name, ETH_GSTRING_LEN); + continue; + } + idx = i - ARRAY_SIZE(common_hw_stats); + strscpy(data + i * ETH_GSTRING_LEN, + phy_data->stats[idx].name, ETH_GSTRING_LEN); } } static void nxp_c45_get_stats(struct phy_device *phydev, struct ethtool_stats *stats, u64 *data) { + const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); + size_t count = nxp_c45_get_sset_count(phydev); + const struct nxp_c45_reg_field *reg_field; + size_t idx; size_t i; int ret; - for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { - ret = phy_read_mmd(phydev, nxp_c45_hw_stats[i].mmd, - nxp_c45_hw_stats[i].reg); - if (ret < 0) { - data[i] = U64_MAX; + for (i = 0; i < count; i++) { + if (i < ARRAY_SIZE(common_hw_stats)) { + reg_field = &common_hw_stats[i].counter; } else { - data[i] = ret & nxp_c45_hw_stats[i].mask; - data[i] >>= nxp_c45_hw_stats[i].off; + idx = i - ARRAY_SIZE(common_hw_stats); + reg_field = &phy_data->stats[idx].counter; } + + ret = nxp_c45_read_reg_field(phydev, reg_field); + if (ret < 0) + data[i] = U64_MAX; + else + data[i] = ret; } } @@ -884,6 +1016,7 @@ static int nxp_c45_config_intr(struct phy_device *phydev) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) { + const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); struct nxp_c45_phy *priv = phydev->priv; irqreturn_t ret = IRQ_NONE; struct nxp_c45_hwts hwts; @@ -901,8 +1034,8 @@ static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) * The irq signal will be asserted until the EGR TS FIFO will be * emptied. */ - irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_IRQ_STATUS); - if (irq & PTP_IRQ_EGR_TS) { + irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status); + if (irq) { while (nxp_c45_get_hwtxts(priv, &hwts)) nxp_c45_process_txts(priv, &hwts); @@ -929,24 +1062,28 @@ static int nxp_c45_soft_reset(struct phy_device *phydev) static int nxp_c45_cable_test_start(struct phy_device *phydev) { - return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, - CABLE_TEST_ENABLE | CABLE_TEST_START); + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); + + return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, + CABLE_TEST_ENABLE | CABLE_TEST_START); } static int nxp_c45_cable_test_get_status(struct phy_device *phydev, bool *finished) { + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); int ret; u8 cable_test_result; - ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST); - if (!(ret & CABLE_TEST_VALID)) { + ret = nxp_c45_read_reg_field(phydev, ®map->cable_test_valid); + if (!ret) { *finished = false; return 0; } *finished = true; - cable_test_result = ret & GENMASK(2, 0); + cable_test_result = nxp_c45_read_reg_field(phydev, + ®map->cable_test_result); switch (cable_test_result) { case CABLE_TEST_OK: @@ -966,7 +1103,7 @@ static int nxp_c45_cable_test_get_status(struct phy_device *phydev, ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); } - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, CABLE_TEST_ENABLE); return nxp_c45_start_op(phydev); @@ -1005,6 +1142,28 @@ static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) return 0; } +static void nxp_c45_counters_enable(struct phy_device *phydev) +{ + const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, + COUNTER_EN); + + data->counters_enable(phydev); +} + +static void nxp_c45_ptp_init(struct phy_device *phydev) +{ + const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); + + phy_write_mmd(phydev, MDIO_MMD_VEND1, + data->regmap->vend1_ptp_clk_period, + data->ptp_clk_period); + nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl); + + data->ptp_init(phydev); +} + static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) { /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. @@ -1182,31 +1341,14 @@ static int nxp_c45_config_init(struct phy_device *phydev) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, PHY_CONFIG_AUTO); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, - COUNTER_EN); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, - COUNTER_EN); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, - COUNTER_EN); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, - COUNTER_EN); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, - COUNTER_EN); - ret = nxp_c45_set_phy_mode(phydev); if (ret) return ret; phydev->autoneg = AUTONEG_DISABLE; - phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK_PERIOD, - PTP_CLK_PERIOD_100BT1); - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_HW_LTC_LOCK_CTRL, - HW_LTC_LOCK_EN); - phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, - RX_TS_INSRT_MODE2); - phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, - PTP_ENABLE); + nxp_c45_counters_enable(phydev); + nxp_c45_ptp_init(phydev); return nxp_c45_start_op(phydev); } @@ -1266,11 +1408,107 @@ static void nxp_c45_remove(struct phy_device *phydev) skb_queue_purge(&priv->rx_queue); } +static void tja1103_counters_enable(struct phy_device *phydev) +{ + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, + COUNTER_EN); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, + COUNTER_EN); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, + COUNTER_EN); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, + COUNTER_EN); +} + +static void tja1103_ptp_init(struct phy_device *phydev) +{ + phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, + TJA1103_RX_TS_INSRT_MODE2); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, + PTP_ENABLE); +} + +static void tja1103_ptp_enable(struct phy_device *phydev, bool enable) +{ + if (enable) + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_PTP_CONTROL, + PORT_PTP_CONTROL_BYPASS); + else + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_PTP_CONTROL, + PORT_PTP_CONTROL_BYPASS); +} + +static const struct nxp_c45_regmap tja1103_regmap = { + .vend1_ptp_clk_period = 0x1104, + .vend1_event_msg_filt = 0x1148, + .pps_enable = + NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1), + .pps_polarity = + NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1), + .ltc_lock_ctrl = + NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1), + .ltc_read = + NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1), + .ltc_write = + NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1), + .vend1_ltc_wr_nsec_0 = 0x1106, + .vend1_ltc_wr_nsec_1 = 0x1107, + .vend1_ltc_wr_sec_0 = 0x1108, + .vend1_ltc_wr_sec_1 = 0x1109, + .vend1_ltc_rd_nsec_0 = 0x110A, + .vend1_ltc_rd_nsec_1 = 0x110B, + .vend1_ltc_rd_sec_0 = 0x110C, + .vend1_ltc_rd_sec_1 = 0x110D, + .vend1_rate_adj_subns_0 = 0x110F, + .vend1_rate_adj_subns_1 = 0x1110, + .irq_egr_ts_en = + NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1), + .irq_egr_ts_status = + NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1), + .domain_number = + NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8), + .msg_type = + NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4), + .sequence_id = + NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16), + .sec_1_0 = + NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2), + .sec_4_2 = + NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3), + .nsec_15_0 = + NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16), + .nsec_29_16 = + NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14), + .vend1_ext_trg_data_0 = 0x1121, + .vend1_ext_trg_data_1 = 0x1122, + .vend1_ext_trg_data_2 = 0x1123, + .vend1_ext_trg_data_3 = 0x1124, + .vend1_ext_trg_ctrl = 0x1126, + .cable_test = 0x8330, + .cable_test_valid = + NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1), + .cable_test_result = + NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3), +}; + +static const struct nxp_c45_phy_data tja1103_phy_data = { + .regmap = &tja1103_regmap, + .stats = tja1103_hw_stats, + .n_stats = ARRAY_SIZE(tja1103_hw_stats), + .ptp_clk_period = PTP_CLK_PERIOD_100BT1, + .counters_enable = tja1103_counters_enable, + .ptp_init = tja1103_ptp_init, + .ptp_enable = tja1103_ptp_enable, +}; + static struct phy_driver nxp_c45_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), .name = "NXP C45 TJA1103", .features = PHY_BASIC_T1_FEATURES, + .driver_data = &tja1103_phy_data, .probe = nxp_c45_probe, .soft_reset = nxp_c45_soft_reset, .config_aneg = genphy_c45_config_aneg, -- cgit From 369da333569eb82c9ce5e63f5f224c7416b251b6 Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:12 +0300 Subject: net: phy: nxp-c45-tja11xx: use get_features PHY_BASIC_T1_FEATURES are not the right features supported by TJA1103 anymore. For example ethtool reports: [root@alarm ~]# ethtool end0 Settings for end0: Supported ports: [ TP ] Supported link modes: 100baseT1/Full 10baseT1L/Full 10baseT1L/Full is not supported by TJA1103 and supported ports list is not completed. The PHY also have a MII port. genphy_c45_pma_read_abilities implementation can detect the PHY features and they look like this. [root@alarm ~]# ethtool end0 Settings for end0: Supported ports: [ TP MII ] Supported link modes: 100baseT1/Full Supported pause frame use: Symmetric Supports auto-negotiation: No Supported FEC modes: Not reported Advertised link modes: 100baseT1/Full Advertised pause frame use: Symmetric Advertised auto-negotiation: No Advertised FEC modes: Not reported Speed: 100Mb/s Duplex: Full Auto-negotiation: off master-slave cfg: forced master master-slave status: master Port: Twisted Pair PHYAD: 1 Transceiver: external MDI-X: Unknown Supports Wake-on: g Wake-on: d Link detected: yes SQI: 7/7 Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-5-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index d5981985b320..573083f0550f 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -1353,6 +1353,14 @@ static int nxp_c45_config_init(struct phy_device *phydev) return nxp_c45_start_op(phydev); } +static int nxp_c45_get_features(struct phy_device *phydev) +{ + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported); + + return genphy_c45_pma_read_abilities(phydev); +} + static int nxp_c45_probe(struct phy_device *phydev) { struct nxp_c45_phy *priv; @@ -1507,7 +1515,7 @@ static struct phy_driver nxp_c45_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), .name = "NXP C45 TJA1103", - .features = PHY_BASIC_T1_FEATURES, + .get_features = nxp_c45_get_features, .driver_data = &tja1103_phy_data, .probe = nxp_c45_probe, .soft_reset = nxp_c45_soft_reset, -- cgit From f1fe5dff2b8aa85acdab84eb9feae634ac92c54d Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:13 +0300 Subject: net: phy: nxp-c45-tja11xx: add TJA1120 support Add TJA1120 driver entry and its driver_data. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-6-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/Kconfig | 2 +- drivers/net/phy/nxp-c45-tja11xx.c | 159 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 67aaeb75301f..107880d13d21 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -306,7 +306,7 @@ config NXP_C45_TJA11XX_PHY depends on PTP_1588_CLOCK_OPTIONAL help Enable support for NXP C45 TJA11XX PHYs. - Currently supports only the TJA1103 PHY. + Currently supports the TJA1103 and TJA1120 PHYs. config NXP_TJA11XX_PHY tristate "NXP TJA11xx PHYs support" diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 573083f0550f..dbfaf1e07ad5 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -18,12 +18,17 @@ #include #define PHY_ID_TJA_1103 0x001BB010 +#define PHY_ID_TJA_1120 0x001BB031 #define VEND1_DEVICE_CONTROL 0x0040 #define DEVICE_CONTROL_RESET BIT(15) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) #define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13) +#define VEND1_DEVICE_CONFIG 0x0048 + +#define TJA1120_VEND1_EXT_TS_MODE 0x1012 + #define VEND1_PHY_IRQ_ACK 0x80A0 #define VEND1_PHY_IRQ_EN 0x80A1 #define VEND1_PHY_IRQ_STATUS 0x80A2 @@ -76,6 +81,14 @@ #define MII_BASIC_CONFIG_RMII 0x5 #define MII_BASIC_CONFIG_MII 0x4 +#define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351 +#define EXTENDED_CNT_EN BIT(15) +#define VEND1_MONITOR_STATUS 0xAC80 +#define MONITOR_RESET BIT(15) +#define VEND1_MONITOR_CONFIG 0xAC86 +#define LOST_FRAMES_CNT_EN BIT(9) +#define ALL_FRAMES_CNT_EN BIT(8) + #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 #define VEND1_LINK_DROP_COUNTER 0x8352 #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 @@ -94,6 +107,10 @@ #define VEND1_RX_TS_INSRT_CTRL 0x114D #define TJA1103_RX_TS_INSRT_MODE2 0x02 +#define TJA1120_RX_TS_INSRT_CTRL 0x9012 +#define TJA1120_RX_TS_INSRT_EN BIT(15) +#define TJA1120_TS_INSRT_MODE BIT(4) + #define VEND1_EGR_RING_DATA_0 0x114E #define VEND1_EGR_RING_CTRL 0x1154 @@ -110,6 +127,7 @@ #define PORT_PTP_CONTROL_BYPASS BIT(11) #define PTP_CLK_PERIOD_100BT1 15ULL +#define PTP_CLK_PERIOD_1000BT1 8ULL #define EVENT_MSG_FILT_ALL 0x0F #define EVENT_MSG_FILT_NONE 0x00 @@ -929,6 +947,27 @@ static const struct nxp_c45_phy_stats tja1103_hw_stats[] = { NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), }, }; +static const struct nxp_c45_phy_stats tja1120_hw_stats[] = { + { "phy_symbol_error_cnt_ext", + NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) }, + { "tx_frames_xtd", + NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), }, + { "tx_frames", + NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), }, + { "rx_frames_xtd", + NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), }, + { "rx_frames", + NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), }, + { "tx_lost_frames_xtd", + NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), }, + { "tx_lost_frames", + NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), }, + { "rx_lost_frames_xtd", + NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), }, + { "rx_lost_frames", + NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), }, +}; + static int nxp_c45_get_sset_count(struct phy_device *phydev) { const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); @@ -1511,6 +1550,101 @@ static const struct nxp_c45_phy_data tja1103_phy_data = { .ptp_enable = tja1103_ptp_enable, }; +static void tja1120_counters_enable(struct phy_device *phydev) +{ + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD, + EXTENDED_CNT_EN); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS, + MONITOR_RESET); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG, + ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN); +} + +static void tja1120_ptp_init(struct phy_device *phydev) +{ + phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL, + TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE); + phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE, + TJA1120_TS_INSRT_MODE); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG, + PTP_ENABLE); +} + +static void tja1120_ptp_enable(struct phy_device *phydev, bool enable) +{ + if (enable) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_FUNC_ENABLES, + PTP_ENABLE); + else + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_FUNC_ENABLES, + PTP_ENABLE); +} + +static const struct nxp_c45_regmap tja1120_regmap = { + .vend1_ptp_clk_period = 0x1020, + .vend1_event_msg_filt = 0x9010, + .pps_enable = + NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1), + .pps_polarity = + NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1), + .ltc_lock_ctrl = + NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1), + .ltc_read = + NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1), + .ltc_write = + NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1), + .vend1_ltc_wr_nsec_0 = 0x1040, + .vend1_ltc_wr_nsec_1 = 0x1041, + .vend1_ltc_wr_sec_0 = 0x1042, + .vend1_ltc_wr_sec_1 = 0x1043, + .vend1_ltc_rd_nsec_0 = 0x1048, + .vend1_ltc_rd_nsec_1 = 0x1049, + .vend1_ltc_rd_sec_0 = 0x104A, + .vend1_ltc_rd_sec_1 = 0x104B, + .vend1_rate_adj_subns_0 = 0x1030, + .vend1_rate_adj_subns_1 = 0x1031, + .irq_egr_ts_en = + NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1), + .irq_egr_ts_status = + NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1), + .domain_number = + NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8), + .msg_type = + NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4), + .sequence_id = + NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16), + .sec_1_0 = + NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2), + .sec_4_2 = + NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3), + .nsec_15_0 = + NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16), + .nsec_29_16 = + NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14), + .vend1_ext_trg_data_0 = 0x1071, + .vend1_ext_trg_data_1 = 0x1072, + .vend1_ext_trg_data_2 = 0x1073, + .vend1_ext_trg_data_3 = 0x1074, + .vend1_ext_trg_ctrl = 0x1075, + .cable_test = 0x8360, + .cable_test_valid = + NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1), + .cable_test_result = + NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3), +}; + +static const struct nxp_c45_phy_data tja1120_phy_data = { + .regmap = &tja1120_regmap, + .stats = tja1120_hw_stats, + .n_stats = ARRAY_SIZE(tja1120_hw_stats), + .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, + .counters_enable = tja1120_counters_enable, + .ptp_init = tja1120_ptp_init, + .ptp_enable = tja1120_ptp_enable, +}; + static struct phy_driver nxp_c45_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), @@ -1536,12 +1670,37 @@ static struct phy_driver nxp_c45_driver[] = { .get_sqi_max = nxp_c45_get_sqi_max, .remove = nxp_c45_remove, }, + { + PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), + .name = "NXP C45 TJA1120", + .get_features = nxp_c45_get_features, + .driver_data = &tja1120_phy_data, + .probe = nxp_c45_probe, + .soft_reset = nxp_c45_soft_reset, + .config_aneg = genphy_c45_config_aneg, + .config_init = nxp_c45_config_init, + .config_intr = nxp_c45_config_intr, + .handle_interrupt = nxp_c45_handle_interrupt, + .read_status = genphy_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = genphy_c45_pma_resume, + .get_sset_count = nxp_c45_get_sset_count, + .get_strings = nxp_c45_get_strings, + .get_stats = nxp_c45_get_stats, + .cable_test_start = nxp_c45_cable_test_start, + .cable_test_get_status = nxp_c45_cable_test_get_status, + .set_loopback = genphy_c45_loopback, + .get_sqi = nxp_c45_get_sqi, + .get_sqi_max = nxp_c45_get_sqi_max, + .remove = nxp_c45_remove, + }, }; module_phy_driver(nxp_c45_driver); static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, + { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) }, { /*sentinel*/ }, }; -- cgit From b0b2247d815d0f6806b702022052e208c3c2d56a Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:14 +0300 Subject: net: phy: nxp-c45-tja11xx: enable LTC sampling on both ext_ts edges The external trigger configuration for TJA1120 has changed. The PHY supports sampling of the LTC on rising and on falling edge. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-7-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 60 +++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index dbfaf1e07ad5..8393c17a83cc 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -101,6 +101,10 @@ #define VEND1_PTP_CONFIG 0x1102 #define EXT_TRG_EDGE BIT(1) +#define TJA1120_SYNC_TRIG_FILTER 0x1010 +#define PTP_TRIG_RISE_TS BIT(3) +#define PTP_TRIG_FALLING_TS BIT(2) + #define CLK_RATE_ADJ_LD BIT(15) #define CLK_RATE_ADJ_DIR BIT(14) @@ -238,6 +242,7 @@ struct nxp_c45_phy_data { const struct nxp_c45_phy_stats *stats; int n_stats; u8 ptp_clk_period; + bool ext_ts_both_edges; void (*counters_enable)(struct phy_device *phydev); void (*ptp_init)(struct phy_device *phydev); void (*ptp_enable)(struct phy_device *phydev, bool enable); @@ -684,9 +689,48 @@ static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, return 0; } +static void nxp_c45_set_rising_or_falling(struct phy_device *phydev, + struct ptp_extts_request *extts) +{ + if (extts->flags & PTP_RISING_EDGE) + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PTP_CONFIG, EXT_TRG_EDGE); + + if (extts->flags & PTP_FALLING_EDGE) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PTP_CONFIG, EXT_TRG_EDGE); +} + +static void nxp_c45_set_rising_and_falling(struct phy_device *phydev, + struct ptp_extts_request *extts) +{ + /* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In + * this case external ts will be enabled on rising edge. + */ + if (extts->flags & PTP_RISING_EDGE || + extts->flags == PTP_ENABLE_FEATURE) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_SYNC_TRIG_FILTER, + PTP_TRIG_RISE_TS); + else + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_SYNC_TRIG_FILTER, + PTP_TRIG_RISE_TS); + + if (extts->flags & PTP_FALLING_EDGE) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_SYNC_TRIG_FILTER, + PTP_TRIG_FALLING_TS); + else + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_SYNC_TRIG_FILTER, + PTP_TRIG_FALLING_TS); +} + static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, struct ptp_extts_request *extts, int on) { + const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); int pin; if (extts->flags & ~(PTP_ENABLE_FEATURE | @@ -697,7 +741,8 @@ static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, /* Sampling on both edges is not supported */ if ((extts->flags & PTP_RISING_EDGE) && - (extts->flags & PTP_FALLING_EDGE)) + (extts->flags & PTP_FALLING_EDGE) && + !data->ext_ts_both_edges) return -EOPNOTSUPP; pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index); @@ -711,13 +756,10 @@ static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, return 0; } - if (extts->flags & PTP_RISING_EDGE) - phy_clear_bits_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_PTP_CONFIG, EXT_TRG_EDGE); - - if (extts->flags & PTP_FALLING_EDGE) - phy_set_bits_mmd(priv->phydev, MDIO_MMD_VEND1, - VEND1_PTP_CONFIG, EXT_TRG_EDGE); + if (data->ext_ts_both_edges) + nxp_c45_set_rising_and_falling(priv->phydev, extts); + else + nxp_c45_set_rising_or_falling(priv->phydev, extts); nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG); priv->extts = true; @@ -1545,6 +1587,7 @@ static const struct nxp_c45_phy_data tja1103_phy_data = { .stats = tja1103_hw_stats, .n_stats = ARRAY_SIZE(tja1103_hw_stats), .ptp_clk_period = PTP_CLK_PERIOD_100BT1, + .ext_ts_both_edges = false, .counters_enable = tja1103_counters_enable, .ptp_init = tja1103_ptp_init, .ptp_enable = tja1103_ptp_enable, @@ -1640,6 +1683,7 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { .stats = tja1120_hw_stats, .n_stats = ARRAY_SIZE(tja1120_hw_stats), .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, + .ext_ts_both_edges = true, .counters_enable = tja1120_counters_enable, .ptp_init = tja1120_ptp_init, .ptp_enable = tja1120_ptp_enable, -- cgit From bdb4c5b8852029d9a82f366885071ba27d254366 Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:15 +0300 Subject: net: phy: nxp-c45-tja11xx: read egress ts on TJA1120 The egress timestamp FIFO/circular buffer work different on TJA1120 than TJA1103. For TJA1103 the new timestamp should be manually moved from the FIFO to the hardware buffer before checking if the timestamp is valid. For TJA1120 the hardware will move automatically the new timestamp from the FIFO to the buffer and the user should check the valid bit, read the timestamp and unlock the buffer by writing any of the buffer registers(which are read only). Another change for the TJA1120 is the behaviour of the EGR TS IRQ bit. This bit was a self-clear bit for TJA1103, but now should be cleared before reading the timestamp. Signed-off-by: Radu Pirea (NXP OSS) Link: https://lore.kernel.org/r/20230731091619.77961-8-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 110 +++++++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 8393c17a83cc..e596ffcf8683 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -29,6 +29,11 @@ #define TJA1120_VEND1_EXT_TS_MODE 0x1012 +#define TJA1120_EGRESS_TS_DATA_S 0x9060 +#define TJA1120_EGRESS_TS_END 0x9067 +#define TJA1120_TS_VALID BIT(0) +#define TJA1120_MORE_TS BIT(15) + #define VEND1_PHY_IRQ_ACK 0x80A0 #define VEND1_PHY_IRQ_EN 0x80A1 #define VEND1_PHY_IRQ_STATUS 0x80A2 @@ -59,6 +64,12 @@ #define VEND1_PORT_ABILITIES 0x8046 #define PTP_ABILITY BIT(3) +#define VEND1_PORT_FUNC_IRQ_EN 0x807A +#define PTP_IRQS BIT(3) + +#define VEND1_PTP_IRQ_ACK 0x9008 +#define EGR_TS_IRQ BIT(1) + #define VEND1_PORT_INFRA_CONTROL 0xAC00 #define PORT_INFRA_CONTROL_EN BIT(14) @@ -158,6 +169,8 @@ #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) +struct nxp_c45_phy; + struct nxp_c45_skb_cb { struct ptp_header *header; unsigned int type; @@ -243,7 +256,10 @@ struct nxp_c45_phy_data { int n_stats; u8 ptp_clk_period; bool ext_ts_both_edges; + bool ack_ptp_irq; void (*counters_enable)(struct phy_device *phydev); + bool (*get_egressts)(struct nxp_c45_phy *priv, + struct nxp_c45_hwts *hwts); void (*ptp_init)(struct phy_device *phydev); void (*ptp_enable)(struct phy_device *phydev, bool enable); }; @@ -499,21 +515,11 @@ static void nxp_c45_get_extts(struct nxp_c45_phy *priv, regmap->vend1_ext_trg_ctrl, RING_DONE); } -static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, - struct nxp_c45_hwts *hwts) +static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv, + struct nxp_c45_hwts *hwts) { const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); struct phy_device *phydev = priv->phydev; - bool valid; - u16 reg; - - mutex_lock(&priv->ptp_lock); - phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, - RING_DONE); - reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); - valid = !!(reg & RING_DATA_0_TS_VALID); - if (!valid) - goto nxp_c45_get_hwtxts_out; hwts->domain_number = nxp_c45_read_reg_field(phydev, ®map->domain_number); @@ -527,12 +533,72 @@ static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16; hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0); hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2; +} + +static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, + struct nxp_c45_hwts *hwts) +{ + bool valid; + u16 reg; + mutex_lock(&priv->ptp_lock); + phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, + RING_DONE); + reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); + valid = !!(reg & RING_DATA_0_TS_VALID); + if (!valid) + goto nxp_c45_get_hwtxts_out; + + nxp_c45_read_egress_ts(priv, hwts); nxp_c45_get_hwtxts_out: mutex_unlock(&priv->ptp_lock); return valid; } +static bool tja1120_egress_ts_is_valid(struct phy_device *phydev) +{ + bool valid; + u16 reg; + + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S); + valid = !!(reg & TJA1120_TS_VALID); + + return valid; +} + +static bool tja1120_get_hwtxts(struct nxp_c45_phy *priv, + struct nxp_c45_hwts *hwts) +{ + struct phy_device *phydev = priv->phydev; + bool more_ts; + bool valid; + u16 reg; + + mutex_lock(&priv->ptp_lock); + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_END); + more_ts = !!(reg & TJA1120_MORE_TS); + valid = tja1120_egress_ts_is_valid(phydev); + if (!valid) { + if (!more_ts) + goto tja1120_get_hwtxts_out; + + /* Bug workaround for TJA1120 engineering samples: move the + * new timestamp from the FIFO to the buffer. + */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_EGRESS_TS_END, TJA1120_TS_VALID); + valid = tja1120_egress_ts_is_valid(phydev); + if (!valid) + goto tja1120_get_hwtxts_out; + } + nxp_c45_read_egress_ts(priv, hwts); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S, + TJA1120_TS_VALID); +tja1120_get_hwtxts_out: + mutex_unlock(&priv->ptp_lock); + return valid; +} + static void nxp_c45_process_txts(struct nxp_c45_phy *priv, struct nxp_c45_hwts *txts) { @@ -571,6 +637,7 @@ static void nxp_c45_process_txts(struct nxp_c45_phy *priv, static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) { struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); + const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); bool poll_txts = nxp_c45_poll_txts(priv->phydev); struct skb_shared_hwtstamps *shhwtstamps_rx; struct ptp_clock_event event; @@ -582,7 +649,7 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) u32 ts_raw; while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { - txts_valid = nxp_c45_get_hwtxts(priv, &hwts); + txts_valid = data->get_egressts(priv, &hwts); if (unlikely(!txts_valid)) { /* Still more skbs in the queue */ reschedule = true; @@ -1111,13 +1178,16 @@ static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) ret = IRQ_HANDLED; } - /* There is no need for ACK. - * The irq signal will be asserted until the EGR TS FIFO will be - * emptied. - */ irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status); if (irq) { - while (nxp_c45_get_hwtxts(priv, &hwts)) + /* If ack_ptp_irq is false, the IRQ bit is self-clear and will + * be cleared when the EGR TS FIFO is empty. Otherwise, the + * IRQ bit should be cleared before reading the timestamp, + */ + if (data->ack_ptp_irq) + phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PTP_IRQ_ACK, EGR_TS_IRQ); + while (data->get_egressts(priv, &hwts)) nxp_c45_process_txts(priv, &hwts); ret = IRQ_HANDLED; @@ -1588,7 +1658,9 @@ static const struct nxp_c45_phy_data tja1103_phy_data = { .n_stats = ARRAY_SIZE(tja1103_hw_stats), .ptp_clk_period = PTP_CLK_PERIOD_100BT1, .ext_ts_both_edges = false, + .ack_ptp_irq = false, .counters_enable = tja1103_counters_enable, + .get_egressts = nxp_c45_get_hwtxts, .ptp_init = tja1103_ptp_init, .ptp_enable = tja1103_ptp_enable, }; @@ -1684,7 +1756,9 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { .n_stats = ARRAY_SIZE(tja1120_hw_stats), .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, .ext_ts_both_edges = true, + .ack_ptp_irq = true, .counters_enable = tja1120_counters_enable, + .get_egressts = tja1120_get_hwtxts, .ptp_init = tja1120_ptp_init, .ptp_enable = tja1120_ptp_enable, }; -- cgit From 425c8348df7b868bc25dce85758e5dc3d63de91d Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:16 +0300 Subject: net: phy: nxp-c45-tja11xx: handle FUSA irq TJA1120 and TJA1103 have a set of functional safety hardware tests executed after every reset, and when the tests are done, the IRQ line is asserted. For the moment, the purpose of these handlers is to acknowledge the IRQ and not to check the FUSA tests status. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-9-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 79 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index e596ffcf8683..a52067da9dbf 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -29,6 +29,11 @@ #define TJA1120_VEND1_EXT_TS_MODE 0x1012 +#define TJA1120_GLOBAL_INFRA_IRQ_ACK 0x2C08 +#define TJA1120_GLOBAL_INFRA_IRQ_EN 0x2C0A +#define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C +#define TJA1120_DEV_BOOT_DONE BIT(1) + #define TJA1120_EGRESS_TS_DATA_S 0x9060 #define TJA1120_EGRESS_TS_END 0x9067 #define TJA1120_TS_VALID BIT(0) @@ -39,6 +44,9 @@ #define VEND1_PHY_IRQ_STATUS 0x80A2 #define PHY_IRQ_LINK_EVENT BIT(1) +#define VEND1_ALWAYS_ACCESSIBLE 0x801F +#define FUSA_PASS BIT(4) + #define VEND1_PHY_CONTROL 0x8100 #define PHY_CONFIG_EN BIT(14) #define PHY_START_OP BIT(0) @@ -262,6 +270,8 @@ struct nxp_c45_phy_data { struct nxp_c45_hwts *hwts); void (*ptp_init)(struct phy_device *phydev); void (*ptp_enable)(struct phy_device *phydev, bool enable); + void (*nmi_handler)(struct phy_device *phydev, + irqreturn_t *irq_status); }; struct nxp_c45_phy { @@ -1162,6 +1172,37 @@ static int nxp_c45_config_intr(struct phy_device *phydev) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); } +static int tja1103_config_intr(struct phy_device *phydev) +{ + int ret; + + /* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */ + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE, + FUSA_PASS); + if (ret) + return ret; + + return nxp_c45_config_intr(phydev); +} + +static int tja1120_config_intr(struct phy_device *phydev) +{ + int ret; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_GLOBAL_INFRA_IRQ_EN, + TJA1120_DEV_BOOT_DONE); + else + ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_GLOBAL_INFRA_IRQ_EN, + TJA1120_DEV_BOOT_DONE); + if (ret) + return ret; + + return nxp_c45_config_intr(phydev); +} + static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) { const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); @@ -1193,6 +1234,8 @@ static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) ret = IRQ_HANDLED; } + data->nmi_handler(phydev, &ret); + return ret; } @@ -1599,6 +1642,21 @@ static void tja1103_ptp_enable(struct phy_device *phydev, bool enable) PORT_PTP_CONTROL_BYPASS); } +static void tja1103_nmi_handler(struct phy_device *phydev, + irqreturn_t *irq_status) +{ + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, + VEND1_ALWAYS_ACCESSIBLE); + if (ret & FUSA_PASS) { + phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_ALWAYS_ACCESSIBLE, + FUSA_PASS); + *irq_status = IRQ_HANDLED; + } +} + static const struct nxp_c45_regmap tja1103_regmap = { .vend1_ptp_clk_period = 0x1104, .vend1_event_msg_filt = 0x1148, @@ -1663,6 +1721,7 @@ static const struct nxp_c45_phy_data tja1103_phy_data = { .get_egressts = nxp_c45_get_hwtxts, .ptp_init = tja1103_ptp_init, .ptp_enable = tja1103_ptp_enable, + .nmi_handler = tja1103_nmi_handler, }; static void tja1120_counters_enable(struct phy_device *phydev) @@ -1697,6 +1756,21 @@ static void tja1120_ptp_enable(struct phy_device *phydev, bool enable) PTP_ENABLE); } +static void tja1120_nmi_handler(struct phy_device *phydev, + irqreturn_t *irq_status) +{ + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_GLOBAL_INFRA_IRQ_STATUS); + if (ret & TJA1120_DEV_BOOT_DONE) { + phy_write_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_GLOBAL_INFRA_IRQ_ACK, + TJA1120_DEV_BOOT_DONE); + *irq_status = IRQ_HANDLED; + } +} + static const struct nxp_c45_regmap tja1120_regmap = { .vend1_ptp_clk_period = 0x1020, .vend1_event_msg_filt = 0x9010, @@ -1761,6 +1835,7 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { .get_egressts = tja1120_get_hwtxts, .ptp_init = tja1120_ptp_init, .ptp_enable = tja1120_ptp_enable, + .nmi_handler = tja1120_nmi_handler, }; static struct phy_driver nxp_c45_driver[] = { @@ -1773,7 +1848,7 @@ static struct phy_driver nxp_c45_driver[] = { .soft_reset = nxp_c45_soft_reset, .config_aneg = genphy_c45_config_aneg, .config_init = nxp_c45_config_init, - .config_intr = nxp_c45_config_intr, + .config_intr = tja1103_config_intr, .handle_interrupt = nxp_c45_handle_interrupt, .read_status = genphy_c45_read_status, .suspend = genphy_c45_pma_suspend, @@ -1797,7 +1872,7 @@ static struct phy_driver nxp_c45_driver[] = { .soft_reset = nxp_c45_soft_reset, .config_aneg = genphy_c45_config_aneg, .config_init = nxp_c45_config_init, - .config_intr = nxp_c45_config_intr, + .config_intr = tja1120_config_intr, .handle_interrupt = nxp_c45_handle_interrupt, .read_status = genphy_c45_read_status, .suspend = genphy_c45_pma_suspend, -- cgit From c552c110d4794fc12e0faa4d1cc928fccdfce3f2 Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:17 +0300 Subject: net: phy: nxp-c45-tja11xx: run cable test with the PHY in test mode For TJA1120, the enable bit for cable test is not writable if the PHY is not in test mode. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-10-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index a52067da9dbf..92a2eca2a02c 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -145,6 +145,7 @@ #define VEND1_PORT_FUNC_ENABLES 0x8048 #define PTP_ENABLE BIT(3) +#define PHY_TEST_ENABLE BIT(0) #define VEND1_PORT_PTP_CONTROL 0x9000 #define PORT_PTP_CONTROL_BYPASS BIT(11) @@ -1258,6 +1259,8 @@ static int nxp_c45_cable_test_start(struct phy_device *phydev) { const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, CABLE_TEST_ENABLE | CABLE_TEST_START); } @@ -1299,6 +1302,8 @@ static int nxp_c45_cable_test_get_status(struct phy_device *phydev, phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, CABLE_TEST_ENABLE); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); return nxp_c45_start_op(phydev); } -- cgit From 08e6547c8468863734a847154aee390f2a44befe Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:18 +0300 Subject: net: phy: nxp-c45-tja11xx: read ext trig ts on TJA1120 On TJA1120, the external trigger timestamp now has a VALID bit. This changes the logic and we can't use the TJA1103 procedure. For TJA1103, we can always read a valid timestamp from the registers, compare the new timestamp with the old timestamp and, if they are not the same, an event occurred. This logic cannot be applied for TJA1120 because the timestamp is 0 if the VALID bit is not set. Signed-off-by: Radu Pirea (NXP OSS) Link: https://lore.kernel.org/r/20230731091619.77961-11-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 64 +++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 92a2eca2a02c..48657307ffb5 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -34,6 +34,8 @@ #define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C #define TJA1120_DEV_BOOT_DONE BIT(1) +#define TJA1120_VEND1_PTP_TRIG_DATA_S 0x1070 + #define TJA1120_EGRESS_TS_DATA_S 0x9060 #define TJA1120_EGRESS_TS_END 0x9067 #define TJA1120_TS_VALID BIT(0) @@ -269,6 +271,7 @@ struct nxp_c45_phy_data { void (*counters_enable)(struct phy_device *phydev); bool (*get_egressts)(struct nxp_c45_phy *priv, struct nxp_c45_hwts *hwts); + bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts); void (*ptp_init)(struct phy_device *phydev); void (*ptp_enable)(struct phy_device *phydev, bool enable); void (*nmi_handler)(struct phy_device *phydev, @@ -509,7 +512,7 @@ static bool nxp_c45_match_ts(struct ptp_header *header, header->domain_number == hwts->domain_number; } -static void nxp_c45_get_extts(struct nxp_c45_phy *priv, +static bool nxp_c45_get_extts(struct nxp_c45_phy *priv, struct timespec64 *extts) { const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); @@ -524,6 +527,53 @@ static void nxp_c45_get_extts(struct nxp_c45_phy *priv, regmap->vend1_ext_trg_data_3) << 16; phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ext_trg_ctrl, RING_DONE); + + return true; +} + +static bool tja1120_extts_is_valid(struct phy_device *phydev) +{ + bool valid; + int reg; + + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_VEND1_PTP_TRIG_DATA_S); + valid = !!(reg & TJA1120_TS_VALID); + + return valid; +} + +static bool tja1120_get_extts(struct nxp_c45_phy *priv, + struct timespec64 *extts) +{ + const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); + struct phy_device *phydev = priv->phydev; + bool more_ts; + bool valid; + u16 reg; + + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, + regmap->vend1_ext_trg_ctrl); + more_ts = !!(reg & TJA1120_MORE_TS); + + valid = tja1120_extts_is_valid(phydev); + if (!valid) { + if (!more_ts) + goto tja1120_get_extts_out; + + /* Bug workaround for TJA1120 engineering samples: move the new + * timestamp from the FIFO to the buffer. + */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, + regmap->vend1_ext_trg_ctrl, RING_DONE); + valid = tja1120_extts_is_valid(phydev); + if (!valid) + goto tja1120_get_extts_out; + } + + nxp_c45_get_extts(priv, extts); +tja1120_get_extts_out: + return valid; } static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv, @@ -656,12 +706,12 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) bool reschedule = false; struct timespec64 ts; struct sk_buff *skb; - bool txts_valid; + bool ts_valid; u32 ts_raw; while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { - txts_valid = data->get_egressts(priv, &hwts); - if (unlikely(!txts_valid)) { + ts_valid = data->get_egressts(priv, &hwts); + if (unlikely(!ts_valid)) { /* Still more skbs in the queue */ reschedule = true; break; @@ -683,8 +733,8 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) } if (priv->extts) { - nxp_c45_get_extts(priv, &ts); - if (timespec64_compare(&ts, &priv->extts_ts) != 0) { + ts_valid = data->get_extts(priv, &ts); + if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) { priv->extts_ts = ts; event.index = priv->extts_index; event.type = PTP_CLOCK_EXTTS; @@ -1724,6 +1774,7 @@ static const struct nxp_c45_phy_data tja1103_phy_data = { .ack_ptp_irq = false, .counters_enable = tja1103_counters_enable, .get_egressts = nxp_c45_get_hwtxts, + .get_extts = nxp_c45_get_extts, .ptp_init = tja1103_ptp_init, .ptp_enable = tja1103_ptp_enable, .nmi_handler = tja1103_nmi_handler, @@ -1838,6 +1889,7 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { .ack_ptp_irq = true, .counters_enable = tja1120_counters_enable, .get_egressts = tja1120_get_hwtxts, + .get_extts = tja1120_get_extts, .ptp_init = tja1120_ptp_init, .ptp_enable = tja1120_ptp_enable, .nmi_handler = tja1120_nmi_handler, -- cgit From 68c6af72047ca77e6b56bf5ae550f980a0ed704d Mon Sep 17 00:00:00 2001 From: "Radu Pirea (NXP OSS)" Date: Mon, 31 Jul 2023 12:16:19 +0300 Subject: net: phy: nxp-c45-tja11xx: reset PCS if the link goes down During PTP testing on early TJA1120 engineering samples I observed that if the link is lost and recovered, the tx timestamps will be randomly lost. To avoid this HW issue, the PCS should be reset. Resetting the PCS will break the link and we should reset the PCS on LINK UP -> LINK DOWN transition, otherwise we will trigger and infinite loop of LINK UP -> LINK DOWN events. Signed-off-by: Radu Pirea (NXP OSS) Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20230731091619.77961-12-radu-nicolae.pirea@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 48657307ffb5..7ab080ff02df 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -56,6 +56,9 @@ #define VEND1_PHY_CONFIG 0x8108 #define PHY_CONFIG_AUTO BIT(0) +#define TJA1120_EPHY_RESETS 0x810A +#define EPHY_PCS_RESET BIT(3) + #define VEND1_SIGNAL_QUALITY 0x8320 #define SQI_VALID BIT(14) #define SQI_MASK GENMASK(2, 0) @@ -1371,6 +1374,19 @@ static int nxp_c45_get_sqi(struct phy_device *phydev) return reg; } +static void tja1120_link_change_notify(struct phy_device *phydev) +{ + /* Bug workaround for TJA1120 enegineering samples: fix egress + * timestamps lost after link recovery. + */ + if (phydev->state == PHY_NOLINK) { + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_EPHY_RESETS, EPHY_PCS_RESET); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + TJA1120_EPHY_RESETS, EPHY_PCS_RESET); + } +} + static int nxp_c45_get_sqi_max(struct phy_device *phydev) { return MAX_SQI; @@ -1932,6 +1948,7 @@ static struct phy_driver nxp_c45_driver[] = { .config_intr = tja1120_config_intr, .handle_interrupt = nxp_c45_handle_interrupt, .read_status = genphy_c45_read_status, + .link_change_notify = tja1120_link_change_notify, .suspend = genphy_c45_pma_suspend, .resume = genphy_c45_pma_resume, .get_sset_count = nxp_c45_get_sset_count, -- cgit From db31e6f170f33e19d6b204acc265a23c86b654a1 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Wed, 2 Aug 2023 11:09:00 +0800 Subject: can: c_can: Do not check for 0 return after calling platform_get_irq() It is not possible for platform_get_irq() to return 0. Use the return value from platform_get_irq(). Signed-off-by: Ruan Jinjie Link: https://lore.kernel.org/all/20230802030900.2271322-1-ruanjinjie@huawei.com Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 925930b6c4ca..f44ba2600415 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -285,8 +285,8 @@ static int c_can_plat_probe(struct platform_device *pdev) /* get the platform data */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - ret = -ENODEV; + if (irq < 0) { + ret = irq; goto exit; } -- cgit From 10857e6779054f79a7569eaaaa85dfa71b73acc1 Mon Sep 17 00:00:00 2001 From: Rohan G Thomas Date: Mon, 31 Jul 2023 19:50:41 +0800 Subject: net: stmmac: XGMAC support for mdio C22 addr > 3 For XGMAC versions < 2.2 number of supported mdio C22 addresses is restricted to 3. From XGMAC version 2.2 there are no restrictions on the C22 addresses, it supports all valid mdio addresses(0 to 31). Signed-off-by: Rohan G Thomas Acked-by: Jose Abreu Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 36 +++++++++++++++-------- 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 57f2137bbe9d..c67171975d5c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -35,6 +35,7 @@ #define DWMAC_CORE_5_10 0x51 #define DWMAC_CORE_5_20 0x52 #define DWXGMAC_CORE_2_10 0x21 +#define DWXGMAC_CORE_2_20 0x22 #define DWXLGMAC_CORE_2_00 0x20 /* Device ID */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 3db1cb0fd160..dd9e2fec5328 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -62,11 +62,16 @@ static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr, static void stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr, int phyreg, u32 *hw_addr) { - u32 tmp; + u32 tmp = 0; + if (priv->synopsys_id < DWXGMAC_CORE_2_20) { + /* Until ver 2.20 XGMAC does not support C22 addr >= 4. Those + * bits above bit 3 of XGMAC_MDIO_C22P register are reserved. + */ + tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P); + tmp &= ~MII_XGMAC_C22P_MASK; + } /* Set port as Clause 22 */ - tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P); - tmp &= ~MII_XGMAC_C22P_MASK; tmp |= BIT(phyaddr); writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P); @@ -132,8 +137,9 @@ static int stmmac_xgmac2_mdio_read_c22(struct mii_bus *bus, int phyaddr, priv = netdev_priv(ndev); - /* HW does not support C22 addr >= 4 */ - if (phyaddr > MII_XGMAC_MAX_C22ADDR) + /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */ + if (priv->synopsys_id < DWXGMAC_CORE_2_20 && + phyaddr > MII_XGMAC_MAX_C22ADDR) return -ENODEV; stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); @@ -209,8 +215,9 @@ static int stmmac_xgmac2_mdio_write_c22(struct mii_bus *bus, int phyaddr, priv = netdev_priv(ndev); - /* HW does not support C22 addr >= 4 */ - if (phyaddr > MII_XGMAC_MAX_C22ADDR) + /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */ + if (priv->synopsys_id < DWXGMAC_CORE_2_20 && + phyaddr > MII_XGMAC_MAX_C22ADDR) return -ENODEV; stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); @@ -551,13 +558,18 @@ int stmmac_mdio_register(struct net_device *ndev) new_bus->read_c45 = &stmmac_xgmac2_mdio_read_c45; new_bus->write_c45 = &stmmac_xgmac2_mdio_write_c45; - /* Right now only C22 phys are supported */ - max_addr = MII_XGMAC_MAX_C22ADDR + 1; + if (priv->synopsys_id < DWXGMAC_CORE_2_20) { + /* Right now only C22 phys are supported */ + max_addr = MII_XGMAC_MAX_C22ADDR + 1; - /* Check if DT specified an unsupported phy addr */ - if (priv->plat->phy_addr > MII_XGMAC_MAX_C22ADDR) - dev_err(dev, "Unsupported phy_addr (max=%d)\n", + /* Check if DT specified an unsupported phy addr */ + if (priv->plat->phy_addr > MII_XGMAC_MAX_C22ADDR) + dev_err(dev, "Unsupported phy_addr (max=%d)\n", MII_XGMAC_MAX_C22ADDR); + } else { + /* XGMAC version 2.20 onwards support 32 phy addr */ + max_addr = PHY_MAX_ADDR; + } } else { new_bus->read = &stmmac_mdio_read_c22; new_bus->write = &stmmac_mdio_write_c22; -- cgit From a67fa91130ca3c20d2529b7c98ea6e8ef7addfa5 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 31 Jul 2023 16:41:10 +0200 Subject: net: stmmac: dwmac-oxnas: remove obsolete dwmac glue driver Due to lack of maintenance and stall of development for a few years now, and since no new features will ever be added upstream, remove support for OX810 and OX820 ethernet. Acked-by: Linus Walleij Acked-by: Arnd Bergmann Acked-by: Daniel Golle Acked-by: Andy Shevchenko Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 - drivers/net/ethernet/stmicro/stmmac/Makefile | 1 - drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 244 ---------------------- 3 files changed, 256 deletions(-) delete mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 5583f0b055ec..06c6871f8788 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -121,17 +121,6 @@ config DWMAC_MESON the stmmac device driver. This driver is used for Meson6, Meson8, Meson8b and GXBB SoCs. -config DWMAC_OXNAS - tristate "Oxford Semiconductor OXNAS dwmac support" - default ARCH_OXNAS - depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST) - select MFD_SYSCON - help - Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs. - - This selects the Oxford Semiconductor OXNASSoC glue layer support for - the stmmac device driver. This driver is used for OX820. - config DWMAC_QCOM_ETHQOS tristate "Qualcomm ETHQOS support" default ARCH_QCOM diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 7dd3d388068b..5b57aee19267 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o -obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c deleted file mode 100644 index f91753565d60..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Oxford Semiconductor OXNAS DWMAC glue layer - * - * Copyright (C) 2016 Neil Armstrong - * Copyright (C) 2014 Daniel Golle - * Copyright (C) 2013 Ma Haijun - * Copyright (C) 2012 John Crispin - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stmmac_platform.h" - -/* System Control regmap offsets */ -#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78 -#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100 - -/* Control Register */ -#define DWMAC_CKEN_RX_IN 14 -#define DWMAC_CKEN_RXN_OUT 13 -#define DWMAC_CKEN_RX_OUT 12 -#define DWMAC_CKEN_TX_IN 10 -#define DWMAC_CKEN_TXN_OUT 9 -#define DWMAC_CKEN_TX_OUT 8 -#define DWMAC_RX_SOURCE 7 -#define DWMAC_TX_SOURCE 6 -#define DWMAC_LOW_TX_SOURCE 4 -#define DWMAC_AUTO_TX_SOURCE 3 -#define DWMAC_RGMII 2 -#define DWMAC_SIMPLE_MUX 1 -#define DWMAC_CKEN_GTX 0 - -/* Delay register */ -#define DWMAC_TX_VARDELAY_SHIFT 0 -#define DWMAC_TXN_VARDELAY_SHIFT 8 -#define DWMAC_RX_VARDELAY_SHIFT 16 -#define DWMAC_RXN_VARDELAY_SHIFT 24 -#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT) -#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT) -#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT) -#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT) - -struct oxnas_dwmac; - -struct oxnas_dwmac_data { - int (*setup)(struct oxnas_dwmac *dwmac); -}; - -struct oxnas_dwmac { - struct device *dev; - struct clk *clk; - struct regmap *regmap; - const struct oxnas_dwmac_data *data; -}; - -static int oxnas_dwmac_setup_ox810se(struct oxnas_dwmac *dwmac) -{ - unsigned int value; - int ret; - - ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value); - if (ret < 0) - return ret; - - /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ - value |= BIT(DWMAC_CKEN_GTX) | - /* Use simple mux for 25/125 Mhz clock switching */ - BIT(DWMAC_SIMPLE_MUX); - - regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value); - - return 0; -} - -static int oxnas_dwmac_setup_ox820(struct oxnas_dwmac *dwmac) -{ - unsigned int value; - int ret; - - ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value); - if (ret < 0) - return ret; - - /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ - value |= BIT(DWMAC_CKEN_GTX) | - /* Use simple mux for 25/125 Mhz clock switching */ - BIT(DWMAC_SIMPLE_MUX) | - /* set auto switch tx clock source */ - BIT(DWMAC_AUTO_TX_SOURCE) | - /* enable tx & rx vardelay */ - BIT(DWMAC_CKEN_TX_OUT) | - BIT(DWMAC_CKEN_TXN_OUT) | - BIT(DWMAC_CKEN_TX_IN) | - BIT(DWMAC_CKEN_RX_OUT) | - BIT(DWMAC_CKEN_RXN_OUT) | - BIT(DWMAC_CKEN_RX_IN); - regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value); - - /* set tx & rx vardelay */ - value = DWMAC_TX_VARDELAY(4) | - DWMAC_TXN_VARDELAY(2) | - DWMAC_RX_VARDELAY(10) | - DWMAC_RXN_VARDELAY(8); - regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value); - - return 0; -} - -static int oxnas_dwmac_init(struct platform_device *pdev, void *priv) -{ - struct oxnas_dwmac *dwmac = priv; - int ret; - - /* Reset HW here before changing the glue configuration */ - ret = device_reset(dwmac->dev); - if (ret) - return ret; - - ret = clk_prepare_enable(dwmac->clk); - if (ret) - return ret; - - ret = dwmac->data->setup(dwmac); - if (ret) - clk_disable_unprepare(dwmac->clk); - - return ret; -} - -static void oxnas_dwmac_exit(struct platform_device *pdev, void *priv) -{ - struct oxnas_dwmac *dwmac = priv; - - clk_disable_unprepare(dwmac->clk); -} - -static int oxnas_dwmac_probe(struct platform_device *pdev) -{ - struct plat_stmmacenet_data *plat_dat; - struct stmmac_resources stmmac_res; - struct oxnas_dwmac *dwmac; - int ret; - - ret = stmmac_get_platform_resources(pdev, &stmmac_res); - if (ret) - return ret; - - plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - - dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) { - ret = -ENOMEM; - goto err_remove_config_dt; - } - - dwmac->data = (const struct oxnas_dwmac_data *)of_device_get_match_data(&pdev->dev); - if (!dwmac->data) { - ret = -EINVAL; - goto err_remove_config_dt; - } - - dwmac->dev = &pdev->dev; - plat_dat->bsp_priv = dwmac; - plat_dat->init = oxnas_dwmac_init; - plat_dat->exit = oxnas_dwmac_exit; - - dwmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "oxsemi,sys-ctrl"); - if (IS_ERR(dwmac->regmap)) { - dev_err(&pdev->dev, "failed to have sysctrl regmap\n"); - ret = PTR_ERR(dwmac->regmap); - goto err_remove_config_dt; - } - - dwmac->clk = devm_clk_get(&pdev->dev, "gmac"); - if (IS_ERR(dwmac->clk)) { - ret = PTR_ERR(dwmac->clk); - goto err_remove_config_dt; - } - - ret = oxnas_dwmac_init(pdev, plat_dat->bsp_priv); - if (ret) - goto err_remove_config_dt; - - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - if (ret) - goto err_dwmac_exit; - - - return 0; - -err_dwmac_exit: - oxnas_dwmac_exit(pdev, plat_dat->bsp_priv); -err_remove_config_dt: - stmmac_remove_config_dt(pdev, plat_dat); - - return ret; -} - -static const struct oxnas_dwmac_data ox810se_dwmac_data = { - .setup = oxnas_dwmac_setup_ox810se, -}; - -static const struct oxnas_dwmac_data ox820_dwmac_data = { - .setup = oxnas_dwmac_setup_ox820, -}; - -static const struct of_device_id oxnas_dwmac_match[] = { - { - .compatible = "oxsemi,ox810se-dwmac", - .data = &ox810se_dwmac_data, - }, - { - .compatible = "oxsemi,ox820-dwmac", - .data = &ox820_dwmac_data, - }, - { } -}; -MODULE_DEVICE_TABLE(of, oxnas_dwmac_match); - -static struct platform_driver oxnas_dwmac_driver = { - .probe = oxnas_dwmac_probe, - .remove_new = stmmac_pltfr_remove, - .driver = { - .name = "oxnas-dwmac", - .pm = &stmmac_pltfr_pm_ops, - .of_match_table = oxnas_dwmac_match, - }, -}; -module_platform_driver(oxnas_dwmac_driver); - -MODULE_AUTHOR("Neil Armstrong "); -MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer"); -MODULE_LICENSE("GPL v2"); -- cgit From 73b4c04e2e9af8075b87475cb7486f561dcecebd Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Tue, 1 Aug 2023 07:11:01 +0530 Subject: octeontx2-pf: TC flower offload support for SPI field Driver support to offload TC flower rules which matches against SPI field of IPSEC packets (AH/ESP). Signed-off-by: Ratheesh Kannoth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 4 ++++ drivers/net/ethernet/marvell/octeontx2/af/npc.h | 1 + .../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 4 ++++ .../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 11 +++++++++ .../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 27 ++++++++++++++++++++++ 5 files changed, 47 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index ed66c5989102..a8f3c8faf8af 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1451,6 +1451,10 @@ struct flow_msg { __be32 ip4dst; __be32 ip6dst[4]; }; + union { + __be32 spi; + }; + u8 tos; u8 ip_ver; u8 ip_proto; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h index 9beeead56d7b..534f20c0c5df 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h @@ -204,6 +204,7 @@ enum key_fields { NPC_DPORT_UDP, NPC_SPORT_SCTP, NPC_DPORT_SCTP, + NPC_IPSEC_SPI, NPC_HEADER_FIELDS_MAX, NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */ NPC_PF_FUNC, /* Valid when Tx */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 3b26893efdf8..7cd33edca365 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -2827,6 +2827,10 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s, seq_printf(s, "%d ", ntohs(rule->packet.dport)); seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.dport)); break; + case NPC_IPSEC_SPI: + seq_printf(s, "0x%x ", ntohl(rule->packet.spi)); + seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.spi)); + break; default: seq_puts(s, "\n"); break; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 9c365cc3e736..bb715e616fad 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -41,6 +41,7 @@ static const char * const npc_flow_names[] = { [NPC_SPORT_SCTP] = "sctp source port", [NPC_DPORT_SCTP] = "sctp destination port", [NPC_LXMB] = "Mcast/Bcast header ", + [NPC_IPSEC_SPI] = "SPI ", [NPC_UNKNOWN] = "unknown", }; @@ -513,6 +514,10 @@ do { \ NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2); NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2); NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6); + + NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4); + NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LE, NPC_LT_LE_ESP, 0, 4); + /* SMAC follows the DMAC(which is 6 bytes) */ NPC_SCAN_HDR(NPC_SMAC, NPC_LID_LA, la_ltype, la_start + 6, 6); /* PF_FUNC is 2 bytes at 0th byte of NPC_LT_LA_IH_NIX_ETHER */ @@ -564,6 +569,9 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf) if (!npc_check_field(rvu, blkaddr, NPC_LB, intf)) *features &= ~BIT_ULL(NPC_OUTER_VID); + if (*features & (BIT_ULL(NPC_IPPROTO_AH) | BIT_ULL(NPC_IPPROTO_ESP))) + *features |= BIT_ULL(NPC_IPSEC_SPI); + /* for vlan ethertypes corresponding layer type should be in the key */ if (npc_check_field(rvu, blkaddr, NPC_LB, intf)) *features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG) | @@ -930,6 +938,9 @@ do { \ NPC_WRITE_FLOW(NPC_DPORT_SCTP, dport, ntohs(pkt->dport), 0, ntohs(mask->dport), 0); + NPC_WRITE_FLOW(NPC_IPSEC_SPI, spi, ntohl(pkt->spi), 0, + ntohl(mask->spi), 0); + NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0, ntohs(mask->vlan_tci), 0); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 5a44e9b96fc0..4bb511e3cbe5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -461,6 +461,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT(FLOW_DISSECTOR_KEY_IPSEC) | BIT_ULL(FLOW_DISSECTOR_KEY_IP)))) { netdev_info(nic->netdev, "unsupported flow used key 0x%llx", dissector->used_keys); @@ -482,6 +483,8 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, match.key->ip_proto != IPPROTO_UDP && match.key->ip_proto != IPPROTO_SCTP && match.key->ip_proto != IPPROTO_ICMP && + match.key->ip_proto != IPPROTO_ESP && + match.key->ip_proto != IPPROTO_AH && match.key->ip_proto != IPPROTO_ICMPV6)) { netdev_info(nic->netdev, "ip_proto=0x%x not supported\n", @@ -501,6 +504,10 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, req->features |= BIT_ULL(NPC_IPPROTO_ICMP); else if (ip_proto == IPPROTO_ICMPV6) req->features |= BIT_ULL(NPC_IPPROTO_ICMP6); + else if (ip_proto == IPPROTO_ESP) + req->features |= BIT_ULL(NPC_IPPROTO_ESP); + else if (ip_proto == IPPROTO_AH) + req->features |= BIT_ULL(NPC_IPPROTO_AH); } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { @@ -545,6 +552,26 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, } } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPSEC)) { + struct flow_match_ipsec match; + + flow_rule_match_ipsec(rule, &match); + if (!match.mask->spi) { + NL_SET_ERR_MSG_MOD(extack, "spi index not specified"); + return -EOPNOTSUPP; + } + if (ip_proto != IPPROTO_ESP && + ip_proto != IPPROTO_AH) { + NL_SET_ERR_MSG_MOD(extack, + "SPI index is valid only for ESP/AH proto"); + return -EOPNOTSUPP; + } + + flow_spec->spi = match.key->spi; + flow_mask->spi = match.mask->spi; + req->features |= BIT_ULL(NPC_IPSEC_SPI); + } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { struct flow_match_ip match; -- cgit From 745d7e38e95d782053188be0a8e262ca02bcd6c4 Mon Sep 17 00:00:00 2001 From: Ante Knezic Date: Tue, 1 Aug 2023 08:48:15 +0200 Subject: net: dsa: mv88e6xxx: Add erratum 3.14 for 88E6390X and 88E6190X Fixes XAUI/RXAUI lane alignment errors. Issue causes dropped packets when trying to communicate over fiber via SERDES lanes of port 9 and 10. Errata document applies only to 88E6190X and 88E6390X devices. Requires poking in undocumented registers. Signed-off-by: Ante Knezic Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/pcs-639x.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx/pcs-639x.c b/drivers/net/dsa/mv88e6xxx/pcs-639x.c index 98dd49dac421..ba373656bfe1 100644 --- a/drivers/net/dsa/mv88e6xxx/pcs-639x.c +++ b/drivers/net/dsa/mv88e6xxx/pcs-639x.c @@ -20,6 +20,7 @@ struct mv88e639x_pcs { struct mdio_device mdio; struct phylink_pcs sgmii_pcs; struct phylink_pcs xg_pcs; + bool erratum_3_14; bool supports_5g; phy_interface_t interface; unsigned int irq; @@ -205,13 +206,53 @@ static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, mv88e639x_sgmii_pcs_control_pwr(mpcs, false); } +static int mv88e6390_erratum_3_14(struct mv88e639x_pcs *mpcs) +{ + const int lanes[] = { MV88E6390_PORT9_LANE0, MV88E6390_PORT9_LANE1, + MV88E6390_PORT9_LANE2, MV88E6390_PORT9_LANE3, + MV88E6390_PORT10_LANE0, MV88E6390_PORT10_LANE1, + MV88E6390_PORT10_LANE2, MV88E6390_PORT10_LANE3 }; + int err, i; + + /* 88e6190x and 88e6390x errata 3.14: + * After chip reset, SERDES reconfiguration or SERDES core + * Software Reset, the SERDES lanes may not be properly aligned + * resulting in CRC errors + */ + + for (i = 0; i < ARRAY_SIZE(lanes); i++) { + err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i], + MDIO_MMD_PHYXS, + 0xf054, 0x400C); + if (err) + return err; + + err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i], + MDIO_MMD_PHYXS, + 0xf054, 0x4000); + if (err) + return err; + } + + return 0; +} + static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs, phy_interface_t interface) { struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); + int err; mv88e639x_sgmii_pcs_control_pwr(mpcs, true); + if (mpcs->erratum_3_14) { + err = mv88e6390_erratum_3_14(mpcs); + if (err) + dev_err(mpcs->mdio.dev.parent, + "failed to apply erratum 3.14: %pe\n", + ERR_PTR(err)); + } + return 0; } @@ -524,6 +565,10 @@ static int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops; mpcs->xg_pcs.neg_mode = true; + if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6190X || + chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6390X) + mpcs->erratum_3_14 = true; + err = mv88e639x_pcs_setup_irq(mpcs, chip, port); if (err) goto err_free; -- cgit From 61f4d2044aeb702fea236101883b59ea270ab2f7 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:19 +0530 Subject: net: ti: icssg-prueth: Add Firmware Interface for ICSSG Ethernet driver. Add firmware interface related headers and macros for ICSSG Ethernet driver. These macros will be later used by the ICSSG ethernet driver. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_switch_map.h | 234 +++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_switch_map.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h new file mode 100644 index 000000000000..424a7e945ea8 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_SWITCH_MAP_H +#define __NET_TI_ICSSG_SWITCH_MAP_H + +/************************* Ethernet Switch Constants *********************/ + +/* if bucket size is changed in firmware then this too should be changed + * because it directly impacts FDB ageing calculation + */ +#define NUMBER_OF_FDB_BUCKET_ENTRIES (4) + +/* This is fixed in ICSSG */ +#define SIZE_OF_FDB (2048) + +#define FW_LINK_SPEED_1G (0x00) +#define FW_LINK_SPEED_100M (0x01) +#define FW_LINK_SPEED_10M (0x02) +#define FW_LINK_SPEED_HD (0x80) + +/* Time after which FDB entries are checked for aged out values. + * Values are in nanoseconds + */ +#define FDB_AGEING_TIMEOUT_OFFSET 0x0014 + +/* Default VLAN tag for Host Port */ +#define HOST_PORT_DF_VLAN_OFFSET 0x001C + +/* Same as HOST_PORT_DF_VLAN_OFFSET */ +#define EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET HOST_PORT_DF_VLAN_OFFSET + +/* Default VLAN tag for P1 Port */ +#define P1_PORT_DF_VLAN_OFFSET 0x0020 + +/* Same as P1_PORT_DF_VLAN_OFFSET */ +#define EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET P1_PORT_DF_VLAN_OFFSET + +/* default VLAN tag for P2 Port */ +#define P2_PORT_DF_VLAN_OFFSET 0x0024 + +/* Same as P2_PORT_DF_VLAN_OFFSET */ +#define EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET P2_PORT_DF_VLAN_OFFSET + +/* VLAN-FID Table offset. 4096 VIDs. 2B per VID = 8KB = 0x2000 */ +#define VLAN_STATIC_REG_TABLE_OFFSET 0x0100 + +/* VLAN-FID Table offset for EMAC */ +#define EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET VLAN_STATIC_REG_TABLE_OFFSET + +/* Packet descriptor Q reserved memory */ +#define PORT_DESC0_HI 0x2104 + +/* Packet descriptor Q reserved memory */ +#define PORT_DESC0_LO 0x2F6C + +/* Packet descriptor Q reserved memory */ +#define PORT_DESC1_HI 0x3DD4 + +/* Packet descriptor Q reserved memory */ +#define PORT_DESC1_LO 0x4C3C + +/* Packet descriptor Q reserved memory */ +#define HOST_DESC0_HI 0x5AA4 + +/* Packet descriptor Q reserved memory */ +#define HOST_DESC0_LO 0x5F0C + +/* Packet descriptor Q reserved memory */ +#define HOST_DESC1_HI 0x6374 + +/* Packet descriptor Q reserved memory */ +#define HOST_DESC1_LO 0x67DC + +/* Special packet descriptor Q reserved memory */ +#define HOST_SPPD0 0x7AAC + +/* Special acket descriptor Q reserved memory */ +#define HOST_SPPD1 0x7EAC + +/* IEP count cycle counter*/ +#define TIMESYNC_FW_WC_CYCLECOUNT_OFFSET 0x83EC + +/* IEP count hi roll over count */ +#define TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET 0x83F4 + +/* IEP count hi sw counter */ +#define TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET 0x83F8 + +/* Set clock descriptor */ +#define TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET 0x83FC + +/* IEP count syncout reduction factor */ +#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET 0x843C + +/* IEP count syncout reduction counter */ +#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_COUNT_OFFSET 0x8440 + +/* IEP count syncout start time cycle counter */ +#define TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET 0x8444 + +/* Control variable to generate SYNC1 */ +#define TIMESYNC_FW_WC_ISOM_PIN_SIGNAL_EN_OFFSET 0x844C + +/* SystemTime Sync0 periodicity */ +#define TIMESYNC_FW_ST_SYNCOUT_PERIOD_OFFSET 0x8450 + +/* pktTxDelay for P1 = link speed dependent p1 mac delay + p1 phy delay */ +#define TIMESYNC_FW_WC_PKTTXDELAY_P1_OFFSET 0x8454 + +/* pktTxDelay for P2 = link speed dependent p2 mac delay + p2 phy delay */ +#define TIMESYNC_FW_WC_PKTTXDELAY_P2_OFFSET 0x8458 + +/* Set clock operation done signal for next task */ +#define TIMESYNC_FW_SIG_PNFW_OFFSET 0x845C + +/* Set clock operation done signal for next task */ +#define TIMESYNC_FW_SIG_TIMESYNCFW_OFFSET 0x8460 + +/* New list is copied at this time */ +#define TAS_CONFIG_CHANGE_TIME 0x000C + +/* config change error counter */ +#define TAS_CONFIG_CHANGE_ERROR_COUNTER 0x0014 + +/* TAS List update pending flag */ +#define TAS_CONFIG_PENDING 0x0018 + +/* TAS list update trigger flag */ +#define TAS_CONFIG_CHANGE 0x0019 + +/* List length for new TAS schedule */ +#define TAS_ADMIN_LIST_LENGTH 0x001A + +/* Currently active TAS list index */ +#define TAS_ACTIVE_LIST_INDEX 0x001B + +/* Cycle time for the new TAS schedule */ +#define TAS_ADMIN_CYCLE_TIME 0x001C + +/* Cycle counts remaining till the TAS list update */ +#define TAS_CONFIG_CHANGE_CYCLE_COUNT 0x0020 + +/* Base Flow ID for sending Packets to Host for Slice0 */ +#define PSI_L_REGULAR_FLOW_ID_BASE_OFFSET 0x0024 + +/* Same as PSI_L_REGULAR_FLOW_ID_BASE_OFFSET */ +#define EMAC_ICSSG_SWITCH_PSI_L_REGULAR_FLOW_ID_BASE_OFFSET PSI_L_REGULAR_FLOW_ID_BASE_OFFSET + +/* Base Flow ID for sending mgmt and Tx TS to Host for Slice0 */ +#define PSI_L_MGMT_FLOW_ID_OFFSET 0x0026 + +/* Same as PSI_L_MGMT_FLOW_ID_OFFSET */ +#define EMAC_ICSSG_SWITCH_PSI_L_MGMT_FLOW_ID_BASE_OFFSET PSI_L_MGMT_FLOW_ID_OFFSET + +/* Queue number for Special Packets written here */ +#define SPL_PKT_DEFAULT_PRIORITY 0x0028 + +/* Express Preemptible Queue Mask */ +#define EXPRESS_PRE_EMPTIVE_Q_MASK 0x0029 + +/* Port1/Port2 Default Queue number for untagged Packets, only 1B is used */ +#define QUEUE_NUM_UNTAGGED 0x002A + +/* Stores the table used for priority regeneration. 1B per PCP/Queue */ +#define PORT_Q_PRIORITY_REGEN_OFFSET 0x002C + +/* For marking Packet as priority/express (this feature is disabled) or + * cut-through/S&F. + */ +#define EXPRESS_PRE_EMPTIVE_Q_MAP 0x0034 + +/* Stores the table used for priority mapping. 1B per PCP/Queue */ +#define PORT_Q_PRIORITY_MAPPING_OFFSET 0x003C + +/* Used to notify the FW of the current link speed */ +#define PORT_LINK_SPEED_OFFSET 0x00A8 + +/* TAS gate mask for windows list0 */ +#define TAS_GATE_MASK_LIST0 0x0100 + +/* TAS gate mask for windows list1 */ +#define TAS_GATE_MASK_LIST1 0x0350 + +/* Memory to Enable/Disable Preemption on TX side */ +#define PRE_EMPTION_ENABLE_TX 0x05A0 + +/* Active State of Preemption on TX side */ +#define PRE_EMPTION_ACTIVE_TX 0x05A1 + +/* Memory to Enable/Disable Verify State Machine Preemption */ +#define PRE_EMPTION_ENABLE_VERIFY 0x05A2 + +/* Verify Status of State Machine */ +#define PRE_EMPTION_VERIFY_STATUS 0x05A3 + +/* Non Final Fragment Size supported by Link Partner */ +#define PRE_EMPTION_ADD_FRAG_SIZE_REMOTE 0x05A4 + +/* Non Final Fragment Size supported by Firmware */ +#define PRE_EMPTION_ADD_FRAG_SIZE_LOCAL 0x05A6 + +/* Time in ms the State machine waits for respond Packet */ +#define PRE_EMPTION_VERIFY_TIME 0x05A8 + +/* Memory used for R30 related management commands */ +#define MGR_R30_CMD_OFFSET 0x05AC + +/* HW Buffer Pool0 base address */ +#define BUFFER_POOL_0_ADDR_OFFSET 0x05BC + +/* 16B for Host Egress MSMC Q (Pre-emptible) context */ +#define HOST_RX_Q_PRE_CONTEXT_OFFSET 0x0684 + +/* Buffer for 8 FDB entries to be added by 'Add Multiple FDB entries IOCTL' */ +#define FDB_CMD_BUFFER 0x0894 + +/* TAS queue max sdu length list */ +#define TAS_QUEUE_MAX_SDU_LIST 0x08FA + +/* Used by FW to generate random number with the SEED value */ +#define HD_RAND_SEED_OFFSET 0x0934 + +/* 16B for Host Egress MSMC Q (Express) context */ +#define HOST_RX_Q_EXP_CONTEXT_OFFSET 0x0940 + +/* Start of 32 bits PA_STAT counters */ +#define PA_STAT_32b_START_OFFSET 0x0080 + +#endif /* __NET_TI_ICSSG_SWITCH_MAP_H */ -- cgit From b6ba7752149de52fde1253d1b203a96e1ee89afc Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:20 +0530 Subject: net: ti: icssg-prueth: Add mii helper apis and macros Add MII helper APIs and MACROs. These APIs and MACROs will be later used by ICSSG Ethernet driver. Also introduce icssg_prueth.h which has definition of prueth related structures. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_mii_cfg.c | 120 ++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_mii_rt.h | 151 ++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 197 ++++++++++++++++++++++++++ 3 files changed, 468 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_mii_cfg.c create mode 100644 drivers/net/ethernet/ti/icssg/icssg_mii_rt.h create mode 100644 drivers/net/ethernet/ti/icssg/icssg_prueth.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_mii_cfg.c b/drivers/net/ethernet/ti/icssg/icssg_mii_cfg.c new file mode 100644 index 000000000000..92718ae40d7e --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_mii_cfg.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet Driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include +#include +#include + +#include "icssg_mii_rt.h" +#include "icssg_prueth.h" + +void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 ipg) +{ + u32 val; + + if (mii == ICSS_MII0) { + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, ipg); + } else { + regmap_read(mii_rt, PRUSS_MII_RT_TX_IPG0, &val); + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG1, ipg); + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, val); + } +} + +void icssg_mii_update_mtu(struct regmap *mii_rt, int mii, int mtu) +{ + mtu += (ETH_HLEN + ETH_FCS_LEN); + if (mii == ICSS_MII0) { + regmap_update_bits(mii_rt, + PRUSS_MII_RT_RX_FRMS0, + PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK, + (mtu - 1) << PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT); + } else { + regmap_update_bits(mii_rt, + PRUSS_MII_RT_RX_FRMS1, + PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK, + (mtu - 1) << PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT); + } +} + +void icssg_update_rgmii_cfg(struct regmap *miig_rt, struct prueth_emac *emac) +{ + u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0; + int slice = prueth_emac_slice(emac); + u32 inband_en_mask, inband_val = 0; + + gig_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 : + RGMII_CFG_GIG_EN_MII1; + if (emac->speed == SPEED_1000) + gig_val = gig_en_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val); + + inband_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_INBAND_EN_MII0 : + RGMII_CFG_INBAND_EN_MII1; + if (emac->speed == SPEED_10 && phy_interface_mode_is_rgmii(emac->phy_if)) + inband_val = inband_en_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband_en_mask, inband_val); + + full_duplex_mask = (slice == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 : + RGMII_CFG_FULL_DUPLEX_MII1; + if (emac->duplex == DUPLEX_FULL) + full_duplex_val = full_duplex_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask, + full_duplex_val); +} + +void icssg_miig_set_interface_mode(struct regmap *miig_rt, int mii, phy_interface_t phy_if) +{ + u32 val, mask, shift; + + mask = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE : ICSSG_CFG_MII1_MODE; + shift = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE_SHIFT : ICSSG_CFG_MII1_MODE_SHIFT; + + val = MII_MODE_RGMII; + if (phy_if == PHY_INTERFACE_MODE_MII) + val = MII_MODE_MII; + + val <<= shift; + regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, mask, val); + regmap_read(miig_rt, ICSSG_CFG_OFFSET, &val); +} + +u32 icssg_rgmii_cfg_get_bitfield(struct regmap *miig_rt, u32 mask, u32 shift) +{ + u32 val; + + regmap_read(miig_rt, RGMII_CFG_OFFSET, &val); + val &= mask; + val >>= shift; + + return val; +} + +u32 icssg_rgmii_get_speed(struct regmap *miig_rt, int mii) +{ + u32 shift = RGMII_CFG_SPEED_MII0_SHIFT, mask = RGMII_CFG_SPEED_MII0; + + if (mii == ICSS_MII1) { + shift = RGMII_CFG_SPEED_MII1_SHIFT; + mask = RGMII_CFG_SPEED_MII1; + } + + return icssg_rgmii_cfg_get_bitfield(miig_rt, mask, shift); +} + +u32 icssg_rgmii_get_fullduplex(struct regmap *miig_rt, int mii) +{ + u32 shift = RGMII_CFG_FULLDUPLEX_MII0_SHIFT; + u32 mask = RGMII_CFG_FULLDUPLEX_MII0; + + if (mii == ICSS_MII1) { + shift = RGMII_CFG_FULLDUPLEX_MII1_SHIFT; + mask = RGMII_CFG_FULLDUPLEX_MII1; + } + + return icssg_rgmii_cfg_get_bitfield(miig_rt, mask, shift); +} diff --git a/drivers/net/ethernet/ti/icssg/icssg_mii_rt.h b/drivers/net/ethernet/ti/icssg/icssg_mii_rt.h new file mode 100644 index 000000000000..55a59bf5299c --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_mii_rt.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* PRU-ICSS MII_RT register definitions + * + * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com + */ + +#ifndef __NET_PRUSS_MII_RT_H__ +#define __NET_PRUSS_MII_RT_H__ + +#include +#include + +/* PRUSS_MII_RT Registers */ +#define PRUSS_MII_RT_RXCFG0 0x0 +#define PRUSS_MII_RT_RXCFG1 0x4 +#define PRUSS_MII_RT_TXCFG0 0x10 +#define PRUSS_MII_RT_TXCFG1 0x14 +#define PRUSS_MII_RT_TX_CRC0 0x20 +#define PRUSS_MII_RT_TX_CRC1 0x24 +#define PRUSS_MII_RT_TX_IPG0 0x30 +#define PRUSS_MII_RT_TX_IPG1 0x34 +#define PRUSS_MII_RT_PRS0 0x38 +#define PRUSS_MII_RT_PRS1 0x3c +#define PRUSS_MII_RT_RX_FRMS0 0x40 +#define PRUSS_MII_RT_RX_FRMS1 0x44 +#define PRUSS_MII_RT_RX_PCNT0 0x48 +#define PRUSS_MII_RT_RX_PCNT1 0x4c +#define PRUSS_MII_RT_RX_ERR0 0x50 +#define PRUSS_MII_RT_RX_ERR1 0x54 + +/* PRUSS_MII_RT_RXCFG0/1 bits */ +#define PRUSS_MII_RT_RXCFG_RX_ENABLE BIT(0) +#define PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS BIT(1) +#define PRUSS_MII_RT_RXCFG_RX_CUT_PREAMBLE BIT(2) +#define PRUSS_MII_RT_RXCFG_RX_MUX_SEL BIT(3) +#define PRUSS_MII_RT_RXCFG_RX_L2_EN BIT(4) +#define PRUSS_MII_RT_RXCFG_RX_BYTE_SWAP BIT(5) +#define PRUSS_MII_RT_RXCFG_RX_AUTO_FWD_PRE BIT(6) +#define PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS BIT(9) + +/* PRUSS_MII_RT_TXCFG0/1 bits */ +#define PRUSS_MII_RT_TXCFG_TX_ENABLE BIT(0) +#define PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE BIT(1) +#define PRUSS_MII_RT_TXCFG_TX_EN_MODE BIT(2) +#define PRUSS_MII_RT_TXCFG_TX_BYTE_SWAP BIT(3) +#define PRUSS_MII_RT_TXCFG_TX_MUX_SEL BIT(8) +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_SEQUENCE BIT(9) +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_ESC_ERR BIT(10) +#define PRUSS_MII_RT_TXCFG_TX_32_MODE_EN BIT(11) +#define PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN BIT(12) /* SR2.0 onwards */ + +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_SHIFT 16 +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_MASK GENMASK(25, 16) + +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_SHIFT 28 +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_MASK GENMASK(30, 28) + +/* PRUSS_MII_RT_TX_IPG0/1 bits */ +#define PRUSS_MII_RT_TX_IPG_IPG_SHIFT 0 +#define PRUSS_MII_RT_TX_IPG_IPG_MASK GENMASK(9, 0) + +/* PRUSS_MII_RT_PRS0/1 bits */ +#define PRUSS_MII_RT_PRS_COL BIT(0) +#define PRUSS_MII_RT_PRS_CRS BIT(1) + +/* PRUSS_MII_RT_RX_FRMS0/1 bits */ +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_SHIFT 0 +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_MASK GENMASK(15, 0) + +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT 16 +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK GENMASK(31, 16) + +/* Min/Max in MII_RT_RX_FRMS */ +/* For EMAC and Switch */ +#define PRUSS_MII_RT_RX_FRMS_MAX (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM (64) + +/* for HSR and PRP */ +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_LRE (PRUSS_MII_RT_RX_FRMS_MAX + \ + ICSS_LRE_TAG_RCT_SIZE) +/* PRUSS_MII_RT_RX_PCNT0/1 bits */ +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_SHIFT 0 +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_MASK GENMASK(3, 0) + +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_SHIFT 4 +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_MASK GENMASK(7, 4) + +/* PRUSS_MII_RT_RX_ERR0/1 bits */ +#define PRUSS_MII_RT_RX_ERR_MIN_PCNT_ERR BIT(0) +#define PRUSS_MII_RT_RX_ERR_MAX_PCNT_ERR BIT(1) +#define PRUSS_MII_RT_RX_ERR_MIN_FRM_ERR BIT(2) +#define PRUSS_MII_RT_RX_ERR_MAX_FRM_ERR BIT(3) + +#define ICSSG_CFG_OFFSET 0 +#define RGMII_CFG_OFFSET 4 + +/* Constant to choose between MII0 and MII1 */ +#define ICSS_MII0 0 +#define ICSS_MII1 1 + +/* ICSSG_CFG Register bits */ +#define ICSSG_CFG_SGMII_MODE BIT(16) +#define ICSSG_CFG_TX_PRU_EN BIT(11) +#define ICSSG_CFG_RX_SFD_TX_SOF_EN BIT(10) +#define ICSSG_CFG_RTU_PRU_PSI_SHARE_EN BIT(9) +#define ICSSG_CFG_IEP1_TX_EN BIT(8) +#define ICSSG_CFG_MII1_MODE GENMASK(6, 5) +#define ICSSG_CFG_MII1_MODE_SHIFT 5 +#define ICSSG_CFG_MII0_MODE GENMASK(4, 3) +#define ICSSG_CFG_MII0_MODE_SHIFT 3 +#define ICSSG_CFG_RX_L2_G_EN BIT(2) +#define ICSSG_CFG_TX_L2_EN BIT(1) +#define ICSSG_CFG_TX_L1_EN BIT(0) + +enum mii_mode { + MII_MODE_MII = 0, + MII_MODE_RGMII +}; + +/* RGMII CFG Register bits */ +#define RGMII_CFG_INBAND_EN_MII0 BIT(16) +#define RGMII_CFG_GIG_EN_MII0 BIT(17) +#define RGMII_CFG_INBAND_EN_MII1 BIT(20) +#define RGMII_CFG_GIG_EN_MII1 BIT(21) +#define RGMII_CFG_FULL_DUPLEX_MII0 BIT(18) +#define RGMII_CFG_FULL_DUPLEX_MII1 BIT(22) +#define RGMII_CFG_SPEED_MII0 GENMASK(2, 1) +#define RGMII_CFG_SPEED_MII1 GENMASK(6, 5) +#define RGMII_CFG_SPEED_MII0_SHIFT 1 +#define RGMII_CFG_SPEED_MII1_SHIFT 5 +#define RGMII_CFG_FULLDUPLEX_MII0 BIT(3) +#define RGMII_CFG_FULLDUPLEX_MII1 BIT(7) +#define RGMII_CFG_FULLDUPLEX_MII0_SHIFT 3 +#define RGMII_CFG_FULLDUPLEX_MII1_SHIFT 7 +#define RGMII_CFG_SPEED_10M 0 +#define RGMII_CFG_SPEED_100M 1 +#define RGMII_CFG_SPEED_1G 2 + +struct regmap; +struct prueth_emac; + +void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 ipg); +void icssg_mii_update_mtu(struct regmap *mii_rt, int mii, int mtu); +void icssg_update_rgmii_cfg(struct regmap *miig_rt, struct prueth_emac *emac); +u32 icssg_rgmii_cfg_get_bitfield(struct regmap *miig_rt, u32 mask, u32 shift); +u32 icssg_rgmii_get_speed(struct regmap *miig_rt, int mii); +u32 icssg_rgmii_get_fullduplex(struct regmap *miig_rt, int mii); +void icssg_miig_set_interface_mode(struct regmap *miig_rt, int mii, phy_interface_t phy_if); + +#endif /* __NET_PRUSS_MII_RT_H__ */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h new file mode 100644 index 000000000000..8512f19a9b4d --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_PRUETH_H +#define __NET_TI_ICSSG_PRUETH_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "icssg_switch_map.h" + +#define ICSS_SLICE0 0 +#define ICSS_SLICE1 1 + +#define ICSSG_MAX_RFLOWS 8 /* per slice */ + +/* In switch mode there are 3 real ports i.e. 3 mac addrs. + * however Linux sees only the host side port. The other 2 ports + * are the switch ports. + * In emac mode there are 2 real ports i.e. 2 mac addrs. + * Linux sees both the ports. + */ +enum prueth_port { + PRUETH_PORT_HOST = 0, /* host side port */ + PRUETH_PORT_MII0, /* physical port RG/SG MII 0 */ + PRUETH_PORT_MII1, /* physical port RG/SG MII 1 */ + PRUETH_PORT_INVALID, /* Invalid prueth port */ +}; + +enum prueth_mac { + PRUETH_MAC0 = 0, + PRUETH_MAC1, + PRUETH_NUM_MACS, + PRUETH_MAC_INVALID, +}; + +struct prueth_tx_chn { + struct device *dma_dev; + struct napi_struct napi_tx; + struct k3_cppi_desc_pool *desc_pool; + struct k3_udma_glue_tx_channel *tx_chn; + struct prueth_emac *emac; + u32 id; + u32 descs_num; + unsigned int irq; + char name[32]; +}; + +struct prueth_rx_chn { + struct device *dev; + struct device *dma_dev; + struct k3_cppi_desc_pool *desc_pool; + struct k3_udma_glue_rx_channel *rx_chn; + u32 descs_num; + unsigned int irq[ICSSG_MAX_RFLOWS]; /* separate irq per flow */ + char name[32]; +}; + +/* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3) + * and lower three are lower priority channels or threads. + */ +#define PRUETH_MAX_TX_QUEUES 4 + +/* data for each emac port */ +struct prueth_emac { + bool fw_running; + struct prueth *prueth; + struct net_device *ndev; + u8 mac_addr[6]; + struct napi_struct napi_rx; + u32 msg_enable; + + int link; + int speed; + int duplex; + + const char *phy_id; + struct device_node *phy_node; + phy_interface_t phy_if; + enum prueth_port port_id; + + /* DMA related */ + struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES]; + struct completion tdown_complete; + atomic_t tdown_cnt; + struct prueth_rx_chn rx_chns; + int rx_flow_id_base; + int tx_ch_num; + + spinlock_t lock; /* serialize access */ + + unsigned long state; + struct completion cmd_complete; + /* Mutex to serialize access to firmware command interface */ + struct mutex cmd_lock; + struct work_struct rx_mode_work; + struct workqueue_struct *cmd_wq; + + struct pruss_mem_region dram; +}; + +/** + * struct prueth_pdata - PRUeth platform data + * @fdqring_mode: Free desc queue mode + * @quirk_10m_link_issue: 10M link detect errata + */ +struct prueth_pdata { + enum k3_ring_mode fdqring_mode; + u32 quirk_10m_link_issue:1; +}; + +/** + * struct prueth - PRUeth structure + * @dev: device + * @pruss: pruss handle + * @pru: rproc instances of PRUs + * @rtu: rproc instances of RTUs + * @txpru: rproc instances of TX_PRUs + * @shram: PRUSS shared RAM region + * @sram_pool: MSMC RAM pool for buffers + * @msmcram: MSMC RAM region + * @eth_node: DT node for the port + * @emac: private EMAC data structure + * @registered_netdevs: list of registered netdevs + * @miig_rt: regmap to mii_g_rt block + * @mii_rt: regmap to mii_rt block + * @pru_id: ID for each of the PRUs + * @pdev: pointer to ICSSG platform device + * @pdata: pointer to platform data for ICSSG driver + * @icssg_hwcmdseq: seq counter or HWQ messages + * @emacs_initialized: num of EMACs/ext ports that are up/running + */ +struct prueth { + struct device *dev; + struct pruss *pruss; + struct rproc *pru[PRUSS_NUM_PRUS]; + struct rproc *rtu[PRUSS_NUM_PRUS]; + struct rproc *txpru[PRUSS_NUM_PRUS]; + struct pruss_mem_region shram; + struct gen_pool *sram_pool; + struct pruss_mem_region msmcram; + + struct device_node *eth_node[PRUETH_NUM_MACS]; + struct prueth_emac *emac[PRUETH_NUM_MACS]; + struct net_device *registered_netdevs[PRUETH_NUM_MACS]; + struct regmap *miig_rt; + struct regmap *mii_rt; + + enum pruss_pru_id pru_id[PRUSS_NUM_PRUS]; + struct platform_device *pdev; + struct prueth_pdata pdata; + u8 icssg_hwcmdseq; + + int emacs_initialized; +}; + +/* get PRUSS SLICE number from prueth_emac */ +static inline int prueth_emac_slice(struct prueth_emac *emac) +{ + switch (emac->port_id) { + case PRUETH_PORT_MII0: + return ICSS_SLICE0; + case PRUETH_PORT_MII1: + return ICSS_SLICE1; + default: + return -EINVAL; + } +} + +#endif /* __NET_TI_ICSSG_PRUETH_H */ -- cgit From e9b4ece7d74b52bc5800afd4dfe32a8960a9d491 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:21 +0530 Subject: net: ti: icssg-prueth: Add Firmware config and classification APIs. Add icssg_config.h / .c and icssg_classifier.c files. These are firmware configuration and classification related files. These will be used by ICSSG ethernet driver. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_classifier.c | 367 ++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_config.c | 450 +++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_config.h | 200 ++++++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 15 + 4 files changed, 1032 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_classifier.c create mode 100644 drivers/net/ethernet/ti/icssg/icssg_config.c create mode 100644 drivers/net/ethernet/ti/icssg/icssg_config.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_classifier.c b/drivers/net/ethernet/ti/icssg/icssg_classifier.c new file mode 100644 index 000000000000..6df53ab17fbc --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_classifier.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet Driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include +#include +#include + +#include "icssg_prueth.h" + +#define ICSSG_NUM_CLASSIFIERS 16 +#define ICSSG_NUM_FT1_SLOTS 8 +#define ICSSG_NUM_FT3_SLOTS 16 + +#define ICSSG_NUM_CLASSIFIERS_IN_USE 5 + +/* Filter 1 - FT1 */ +#define FT1_NUM_SLOTS 8 +#define FT1_SLOT_SIZE 0x10 /* bytes */ + +/* offsets from FT1 slot base i.e. slot 1 start */ +#define FT1_DA0 0x0 +#define FT1_DA1 0x4 +#define FT1_DA0_MASK 0x8 +#define FT1_DA1_MASK 0xc + +#define FT1_N_REG(slize, n, reg) \ + (offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg)) + +#define FT1_LEN_MASK GENMASK(19, 16) +#define FT1_LEN_SHIFT 16 +#define FT1_LEN(len) (((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK) +#define FT1_START_MASK GENMASK(14, 0) +#define FT1_START(start) ((start) & FT1_START_MASK) +#define FT1_MATCH_SLOT(n) (GENMASK(23, 16) & (BIT(n) << 16)) + +/* FT1 config type */ +enum ft1_cfg_type { + FT1_CFG_TYPE_DISABLED = 0, + FT1_CFG_TYPE_EQ, + FT1_CFG_TYPE_GT, + FT1_CFG_TYPE_LT, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +/* Filter 3 - FT3 */ +#define FT3_NUM_SLOTS 16 +#define FT3_SLOT_SIZE 0x20 /* bytes */ + +/* offsets from FT3 slot n's base */ +#define FT3_START 0 +#define FT3_START_AUTO 0x4 +#define FT3_START_OFFSET 0x8 +#define FT3_JUMP_OFFSET 0xc +#define FT3_LEN 0x10 +#define FT3_CFG 0x14 +#define FT3_T 0x18 +#define FT3_T_MASK 0x1c + +#define FT3_N_REG(slize, n, reg) \ + (offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg)) + +/* offsets from rx_class n's base */ +#define RX_CLASS_AND_EN 0 +#define RX_CLASS_OR_EN 0x4 +#define RX_CLASS_NUM_SLOTS 16 +#define RX_CLASS_EN_SIZE 0x8 /* bytes */ + +#define RX_CLASS_N_REG(slice, n, reg) \ + (offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg)) + +/* RX Class Gates */ +#define RX_CLASS_GATES_SIZE 0x4 /* bytes */ + +#define RX_CLASS_GATES_N_REG(slice, n) \ + (offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n)) + +#define RX_CLASS_GATES_ALLOW_MASK BIT(6) +#define RX_CLASS_GATES_RAW_MASK BIT(5) +#define RX_CLASS_GATES_PHASE_MASK BIT(4) + +/* RX Class traffic data matching bits */ +#define RX_CLASS_FT_UC BIT(31) +#define RX_CLASS_FT_MC BIT(30) +#define RX_CLASS_FT_BC BIT(29) +#define RX_CLASS_FT_FW BIT(28) +#define RX_CLASS_FT_RCV BIT(27) +#define RX_CLASS_FT_VLAN BIT(26) +#define RX_CLASS_FT_DA_P BIT(25) +#define RX_CLASS_FT_DA_I BIT(24) +#define RX_CLASS_FT_FT1_MATCH_MASK GENMASK(23, 16) +#define RX_CLASS_FT_FT1_MATCH_SHIFT 16 +#define RX_CLASS_FT_FT3_MATCH_MASK GENMASK(15, 0) +#define RX_CLASS_FT_FT3_MATCH_SHIFT 0 + +#define RX_CLASS_FT_FT1_MATCH(slot) \ + ((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & \ + RX_CLASS_FT_FT1_MATCH_MASK) + +/* RX class type */ +enum rx_class_sel_type { + RX_CLASS_SEL_TYPE_OR = 0, + RX_CLASS_SEL_TYPE_AND = 1, + RX_CLASS_SEL_TYPE_OR_AND_AND = 2, + RX_CLASS_SEL_TYPE_OR_OR_AND = 3, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +#define RX_CLASS_SEL_SHIFT(n) (2 * (n)) +#define RX_CLASS_SEL_MASK(n) (0x3 << RX_CLASS_SEL_SHIFT((n))) + +#define ICSSG_CFG_OFFSET 0 +#define MAC_INTERFACE_0 0x18 +#define MAC_INTERFACE_1 0x1c + +#define ICSSG_CFG_RX_L2_G_EN BIT(2) + +/* These are register offsets per PRU */ +struct miig_rt_offsets { + u32 mac0; + u32 mac1; + u32 ft1_start_len; + u32 ft1_cfg; + u32 ft1_slot_base; + u32 ft3_slot_base; + u32 ft3_p_base; + u32 ft_rx_ptr; + u32 rx_class_base; + u32 rx_class_cfg1; + u32 rx_class_cfg2; + u32 rx_class_gates_base; + u32 rx_green; + u32 rx_rate_cfg_base; + u32 rx_rate_src_sel0; + u32 rx_rate_src_sel1; + u32 tx_rate_cfg_base; + u32 stat_base; + u32 tx_hsr_tag; + u32 tx_hsr_seq; + u32 tx_vlan_type; + u32 tx_vlan_ins; +}; + +/* These are the offset values for miig_rt_offsets registers */ +static const struct miig_rt_offsets offs[] = { + /* PRU0 */ + { + 0x8, + 0xc, + 0x80, + 0x84, + 0x88, + 0x108, + 0x308, + 0x408, + 0x40c, + 0x48c, + 0x490, + 0x494, + 0x4d4, + 0x4e4, + 0x504, + 0x508, + 0x50c, + 0x54c, + 0x63c, + 0x640, + 0x644, + 0x648, + }, + /* PRU1 */ + { + 0x10, + 0x14, + 0x64c, + 0x650, + 0x654, + 0x6d4, + 0x8d4, + 0x9d4, + 0x9d8, + 0xa58, + 0xa5c, + 0xa60, + 0xaa0, + 0xab0, + 0xad0, + 0xad4, + 0xad8, + 0xb18, + 0xc08, + 0xc0c, + 0xc10, + 0xc14, + }, +}; + +static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice, + u16 start, u8 len) +{ + u32 offset, val; + + offset = offs[slice].ft1_start_len; + val = FT1_LEN(len) | FT1_START(start); + regmap_write(miig_rt, offset, val); +} + +static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice, + int n, const u8 *addr) +{ + u32 offset; + + offset = FT1_N_REG(slice, n, FT1_DA0); + regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 | + addr[2] << 16 | addr[3] << 24)); + offset = FT1_N_REG(slice, n, FT1_DA1); + regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8)); +} + +static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice, + int n, const u8 *addr) +{ + u32 offset; + + offset = FT1_N_REG(slice, n, FT1_DA0_MASK); + regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 | + addr[2] << 16 | addr[3] << 24)); + offset = FT1_N_REG(slice, n, FT1_DA1_MASK); + regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8)); +} + +static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n, + enum ft1_cfg_type type) +{ + u32 offset; + + offset = offs[slice].ft1_cfg; + regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n), + type << FT1_CFG_SHIFT(n)); +} + +static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n, + enum rx_class_sel_type type) +{ + u32 offset; + + offset = offs[slice].rx_class_cfg1; + regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n), + type << RX_CLASS_SEL_SHIFT(n)); +} + +static void rx_class_set_and(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN); + regmap_write(miig_rt, offset, data); +} + +static void rx_class_set_or(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN); + regmap_write(miig_rt, offset, data); +} + +void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac) +{ + regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 | + mac[2] << 16 | mac[3] << 24)); + regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8)); +} + +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac) +{ + regmap_write(miig_rt, offs[slice].mac0, (u32)(mac[0] | mac[1] << 8 | + mac[2] << 16 | mac[3] << 24)); + regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8)); +} + +/* disable all RX traffic */ +void icssg_class_disable(struct regmap *miig_rt, int slice) +{ + u32 data, offset; + int n; + + /* Enable RX_L2_G */ + regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN, + ICSSG_CFG_RX_L2_G_EN); + + for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) { + /* AND_EN = 0 */ + rx_class_set_and(miig_rt, slice, n, 0); + /* OR_EN = 0 */ + rx_class_set_or(miig_rt, slice, n, 0); + + /* set CFG1 to OR */ + rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR); + + /* configure gate */ + offset = RX_CLASS_GATES_N_REG(slice, n); + regmap_read(miig_rt, offset, &data); + /* clear class_raw so we go through filters */ + data &= ~RX_CLASS_GATES_RAW_MASK; + /* set allow and phase mask */ + data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK; + regmap_write(miig_rt, offset, data); + } + + /* FT1 Disabled */ + for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) { + const u8 addr[] = { 0, 0, 0, 0, 0, 0, }; + + rx_class_ft1_cfg_set_type(miig_rt, slice, n, + FT1_CFG_TYPE_DISABLED); + rx_class_ft1_set_da(miig_rt, slice, n, addr); + rx_class_ft1_set_da_mask(miig_rt, slice, n, addr); + } + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti) +{ + u32 data; + + /* defaults */ + icssg_class_disable(miig_rt, slice); + + /* Setup Classifier */ + /* match on Broadcast or MAC_PRU address */ + data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P; + + /* multicast */ + if (allmulti) + data |= RX_CLASS_FT_MC; + + rx_class_set_or(miig_rt, slice, 0, data); + + /* set CFG1 for OR_OR_AND for classifier */ + rx_class_sel_set_type(miig_rt, slice, 0, RX_CLASS_SEL_TYPE_OR_OR_AND); + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +/* required for SAV check */ +void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr) +{ + const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, }; + + rx_class_ft1_set_start_len(miig_rt, slice, 0, 6); + rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr); + rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr); + rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ); +} diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c new file mode 100644 index 000000000000..ab648d3efe85 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0 +/* ICSSG Ethernet driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com + */ + +#include +#include +#include +#include "icssg_config.h" +#include "icssg_prueth.h" +#include "icssg_switch_map.h" +#include "icssg_mii_rt.h" + +/* TX IPG Values to be set for 100M link speed. These values are + * in ocp_clk cycles. So need change if ocp_clk is changed for a specific + * h/w design. + */ + +/* IPG is in core_clk cycles */ +#define MII_RT_TX_IPG_100M 0x17 +#define MII_RT_TX_IPG_1G 0xb + +#define ICSSG_QUEUES_MAX 64 +#define ICSSG_QUEUE_OFFSET 0xd00 +#define ICSSG_QUEUE_PEEK_OFFSET 0xe00 +#define ICSSG_QUEUE_CNT_OFFSET 0xe40 +#define ICSSG_QUEUE_RESET_OFFSET 0xf40 + +#define ICSSG_NUM_TX_QUEUES 8 + +#define RECYCLE_Q_SLICE0 16 +#define RECYCLE_Q_SLICE1 17 + +#define ICSSG_NUM_OTHER_QUEUES 5 /* port, host and special queues */ + +#define PORT_HI_Q_SLICE0 32 +#define PORT_LO_Q_SLICE0 33 +#define HOST_HI_Q_SLICE0 34 +#define HOST_LO_Q_SLICE0 35 +#define HOST_SPL_Q_SLICE0 40 /* Special Queue */ + +#define PORT_HI_Q_SLICE1 36 +#define PORT_LO_Q_SLICE1 37 +#define HOST_HI_Q_SLICE1 38 +#define HOST_LO_Q_SLICE1 39 +#define HOST_SPL_Q_SLICE1 41 /* Special Queue */ + +#define MII_RXCFG_DEFAULT (PRUSS_MII_RT_RXCFG_RX_ENABLE | \ + PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \ + PRUSS_MII_RT_RXCFG_RX_L2_EN | \ + PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS) + +#define MII_TXCFG_DEFAULT (PRUSS_MII_RT_TXCFG_TX_ENABLE | \ + PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \ + PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \ + PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN) + +#define ICSSG_CFG_DEFAULT (ICSSG_CFG_TX_L1_EN | \ + ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \ + ICSSG_CFG_TX_PRU_EN | \ + ICSSG_CFG_SGMII_MODE) + +#define FDB_GEN_CFG1 0x60 +#define SMEM_VLAN_OFFSET 8 +#define SMEM_VLAN_OFFSET_MASK GENMASK(25, 8) + +#define FDB_GEN_CFG2 0x64 +#define FDB_VLAN_EN BIT(6) +#define FDB_HOST_EN BIT(2) +#define FDB_PRU1_EN BIT(1) +#define FDB_PRU0_EN BIT(0) +#define FDB_EN_ALL (FDB_PRU0_EN | FDB_PRU1_EN | \ + FDB_HOST_EN | FDB_VLAN_EN) + +/** + * struct map - ICSSG Queue Map + * @queue: Queue number + * @pd_addr_start: Packet descriptor queue reserved memory + * @flags: Flags + * @special: Indicates whether this queue is a special queue or not + */ +struct map { + int queue; + u32 pd_addr_start; + u32 flags; + bool special; +}; + +/* Hardware queue map for ICSSG */ +static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = { + { + { PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 }, + { PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 }, + { HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 }, + { HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 }, + { HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 }, + }, + { + { PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 }, + { PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 }, + { HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 }, + { HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 }, + { HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 }, + }, +}; + +static void icssg_config_mii_init(struct prueth_emac *emac) +{ + u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg; + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + struct regmap *mii_rt; + + mii_rt = prueth->mii_rt; + + rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 : + PRUSS_MII_RT_RXCFG1; + txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : + PRUSS_MII_RT_TXCFG1; + pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : + PRUSS_MII_RT_RX_PCNT1; + + rxcfg = MII_RXCFG_DEFAULT; + txcfg = MII_TXCFG_DEFAULT; + + if (slice == ICSS_MII1) + rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL; + + /* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need + * to be swapped also comparing to RGMII mode. + */ + if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0) + txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; + else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1) + txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; + + regmap_write(mii_rt, rxcfg_reg, rxcfg); + regmap_write(mii_rt, txcfg_reg, txcfg); + regmap_write(mii_rt, pcnt_reg, 0x1); +} + +static void icssg_miig_queues_init(struct prueth *prueth, int slice) +{ + struct regmap *miig_rt = prueth->miig_rt; + void __iomem *smem = prueth->shram.va; + u8 pd[ICSSG_SPECIAL_PD_SIZE]; + int queue = 0, i, j; + u32 *pdword; + + /* reset hwqueues */ + if (slice) + queue = ICSSG_NUM_TX_QUEUES; + + for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) { + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); + queue++; + } + + queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0; + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); + + for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) { + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, + hwq_map[slice][i].queue); + } + + /* initialize packet descriptors in SMEM */ + /* push pakcet descriptors to hwqueues */ + + pdword = (u32 *)pd; + for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) { + const struct map *mp; + int pd_size, num_pds; + u32 pdaddr; + + mp = &hwq_map[slice][j]; + if (mp->special) { + pd_size = ICSSG_SPECIAL_PD_SIZE; + num_pds = ICSSG_NUM_SPECIAL_PDS; + } else { + pd_size = ICSSG_NORMAL_PD_SIZE; + num_pds = ICSSG_NUM_NORMAL_PDS; + } + + for (i = 0; i < num_pds; i++) { + memset(pd, 0, pd_size); + + pdword[0] &= ICSSG_FLAG_MASK; + pdword[0] |= mp->flags; + pdaddr = mp->pd_addr_start + i * pd_size; + + memcpy_toio(smem + pdaddr, pd, pd_size); + queue = mp->queue; + regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, + pdaddr); + } + } +} + +void icssg_config_ipg(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + + switch (emac->speed) { + case SPEED_1000: + icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G); + break; + case SPEED_100: + icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); + break; + default: + /* Other links speeds not supported */ + netdev_err(emac->ndev, "Unsupported link speed\n"); + return; + } +} + +static void emac_r30_cmd_init(struct prueth_emac *emac) +{ + struct icssg_r30_cmd __iomem *p; + int i; + + p = emac->dram.va + MGR_R30_CMD_OFFSET; + + for (i = 0; i < 4; i++) + writel(EMAC_NONE, &p->cmd[i]); +} + +static int emac_r30_is_done(struct prueth_emac *emac) +{ + const struct icssg_r30_cmd __iomem *p; + u32 cmd; + int i; + + p = emac->dram.va + MGR_R30_CMD_OFFSET; + + for (i = 0; i < 4; i++) { + cmd = readl(&p->cmd[i]); + if (cmd != EMAC_NONE) + return 0; + } + + return 1; +} + +static int prueth_emac_buffer_setup(struct prueth_emac *emac) +{ + struct icssg_buffer_pool_cfg __iomem *bpool_cfg; + struct icssg_rxq_ctx __iomem *rxq_ctx; + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + u32 addr; + int i; + + /* Layout to have 64KB aligned buffer pool + * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| + */ + + addr = lower_32_bits(prueth->msmcram.pa); + if (slice) + addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + + if (addr % SZ_64K) { + dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); + return -EINVAL; + } + + bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; + /* workaround for f/w bug. bpool 0 needs to be initilalized */ + writel(addr, &bpool_cfg[0].addr); + writel(0, &bpool_cfg[0].len); + + for (i = PRUETH_EMAC_BUF_POOL_START; + i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; + i++) { + writel(addr, &bpool_cfg[i].addr); + writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); + addr += PRUETH_EMAC_BUF_POOL_SIZE; + } + + if (!slice) + addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + else + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; + + /* Pre-emptible RX buffer queue */ + rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; + for (i = 0; i < 3; i++) + writel(addr, &rxq_ctx->start[i]); + + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + writel(addr, &rxq_ctx->end); + + /* Express RX buffer queue */ + rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; + for (i = 0; i < 3; i++) + writel(addr, &rxq_ctx->start[i]); + + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + writel(addr, &rxq_ctx->end); + + return 0; +} + +static void icssg_init_emac_mode(struct prueth *prueth) +{ + /* When the device is configured as a bridge and it is being brought + * back to the emac mode, the host mac address has to be set as 0. + */ + u8 mac[ETH_ALEN] = { 0 }; + + if (prueth->emacs_initialized) + return; + + regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, + SMEM_VLAN_OFFSET_MASK, 0); + regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0); + /* Clear host MAC address */ + icssg_class_set_host_mac_addr(prueth->miig_rt, mac); +} + +int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) +{ + void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET; + struct icssg_flow_cfg __iomem *flow_cfg; + int ret; + + icssg_init_emac_mode(prueth); + + memset_io(config, 0, TAS_GATE_MASK_LIST0); + icssg_miig_queues_init(prueth, slice); + + emac->speed = SPEED_1000; + emac->duplex = DUPLEX_FULL; + if (!phy_interface_mode_is_rgmii(emac->phy_if)) { + emac->speed = SPEED_100; + emac->duplex = DUPLEX_FULL; + } + regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, + ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); + icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if); + icssg_config_mii_init(emac); + icssg_config_ipg(emac); + icssg_update_rgmii_cfg(prueth->miig_rt, emac); + + /* set GPI mode */ + pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice], + PRUSS_GPI_MODE_MII); + + /* enable XFR shift for PRU and RTU */ + pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true); + pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true); + + /* set C28 to 0x100 */ + pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8); + pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8); + pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8); + + flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; + writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow); + writew(0, &flow_cfg->mgm_base_flow); + writeb(0, config + SPL_PKT_DEFAULT_PRIORITY); + writeb(0, config + QUEUE_NUM_UNTAGGED); + + ret = prueth_emac_buffer_setup(emac); + if (ret) + return ret; + + emac_r30_cmd_init(emac); + + return 0; +} + +/* Bitmask for ICSSG r30 commands */ +static const struct icssg_r30_cmd emac_r32_bitmask[] = { + {{0xffff0004, 0xffff0100, 0xffff0100, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ + {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ + {{0xffbb0000, 0xfcff0000, 0xdcff0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ + {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ + {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ + {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ + {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ + {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ + {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ + {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ + {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ + {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ + {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ + {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ +}; + +int emac_set_port_state(struct prueth_emac *emac, + enum icssg_port_state_cmd cmd) +{ + struct icssg_r30_cmd __iomem *p; + int ret = -ETIMEDOUT; + int done = 0; + int i; + + p = emac->dram.va + MGR_R30_CMD_OFFSET; + + if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { + netdev_err(emac->ndev, "invalid port command\n"); + return -EINVAL; + } + + /* only one command at a time allowed to firmware */ + mutex_lock(&emac->cmd_lock); + + for (i = 0; i < 4; i++) + writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); + + /* wait for done */ + ret = read_poll_timeout(emac_r30_is_done, done, done == 1, + 1000, 10000, false, emac); + + if (ret == -ETIMEDOUT) + netdev_err(emac->ndev, "timeout waiting for command done\n"); + + mutex_unlock(&emac->cmd_lock); + + return ret; +} + +void icssg_config_set_speed(struct prueth_emac *emac) +{ + u8 fw_speed; + + switch (emac->speed) { + case SPEED_1000: + fw_speed = FW_LINK_SPEED_1G; + break; + case SPEED_100: + fw_speed = FW_LINK_SPEED_100M; + break; + default: + /* Other links speeds not supported */ + netdev_err(emac->ndev, "Unsupported link speed\n"); + return; + } + + writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); +} diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h new file mode 100644 index 000000000000..43eb0922172a --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_CONFIG_H +#define __NET_TI_ICSSG_CONFIG_H + +struct icssg_buffer_pool_cfg { + __le32 addr; + __le32 len; +} __packed; + +struct icssg_flow_cfg { + __le16 rx_base_flow; + __le16 mgm_base_flow; +} __packed; + +#define PRUETH_PKT_TYPE_CMD 0x10 +#define PRUETH_NAV_PS_DATA_SIZE 16 /* Protocol specific data size */ +#define PRUETH_NAV_SW_DATA_SIZE 16 /* SW related data size */ +#define PRUETH_MAX_TX_DESC 512 +#define PRUETH_MAX_RX_DESC 512 +#define PRUETH_MAX_RX_FLOWS 1 /* excluding default flow */ +#define PRUETH_RX_FLOW_DATA 0 + +#define PRUETH_EMAC_BUF_POOL_SIZE SZ_8K +#define PRUETH_EMAC_POOLS_PER_SLICE 24 +#define PRUETH_EMAC_BUF_POOL_START 8 +#define PRUETH_NUM_BUF_POOLS 8 +#define PRUETH_EMAC_RX_CTX_BUF_SIZE SZ_16K /* per slice */ +#define MSMC_RAM_SIZE \ + (2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \ + PRUETH_EMAC_RX_CTX_BUF_SIZE * 2)) + +struct icssg_rxq_ctx { + __le32 start[3]; + __le32 end; +} __packed; + +/* Load time Fiwmware Configuration */ + +#define ICSSG_FW_MGMT_CMD_HEADER 0x81 +#define ICSSG_FW_MGMT_FDB_CMD_TYPE 0x03 +#define ICSSG_FW_MGMT_CMD_TYPE 0x04 +#define ICSSG_FW_MGMT_PKT 0x80000000 + +struct icssg_r30_cmd { + u32 cmd[4]; +} __packed; + +enum icssg_port_state_cmd { + ICSSG_EMAC_PORT_DISABLE = 0, + ICSSG_EMAC_PORT_BLOCK, + ICSSG_EMAC_PORT_FORWARD, + ICSSG_EMAC_PORT_FORWARD_WO_LEARNING, + ICSSG_EMAC_PORT_ACCEPT_ALL, + ICSSG_EMAC_PORT_ACCEPT_TAGGED, + ICSSG_EMAC_PORT_ACCEPT_UNTAGGED_N_PRIO, + ICSSG_EMAC_PORT_TAS_TRIGGER, + ICSSG_EMAC_PORT_TAS_ENABLE, + ICSSG_EMAC_PORT_TAS_RESET, + ICSSG_EMAC_PORT_TAS_DISABLE, + ICSSG_EMAC_PORT_UC_FLOODING_ENABLE, + ICSSG_EMAC_PORT_UC_FLOODING_DISABLE, + ICSSG_EMAC_PORT_MC_FLOODING_ENABLE, + ICSSG_EMAC_PORT_MC_FLOODING_DISABLE, + ICSSG_EMAC_PORT_PREMPT_TX_ENABLE, + ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, + ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, + ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, + ICSSG_EMAC_PORT_MAX_COMMANDS +}; + +#define EMAC_NONE 0xffff0000 +#define EMAC_PRU0_P_DI 0xffff0004 +#define EMAC_PRU1_P_DI 0xffff0040 +#define EMAC_TX_P_DI 0xffff0100 + +#define EMAC_PRU0_P_EN 0xfffb0000 +#define EMAC_PRU1_P_EN 0xffbf0000 +#define EMAC_TX_P_EN 0xfeff0000 + +#define EMAC_P_BLOCK 0xffff0040 +#define EMAC_TX_P_BLOCK 0xffff0200 +#define EMAC_P_UNBLOCK 0xffbf0000 +#define EMAC_TX_P_UNBLOCK 0xfdff0000 +#define EMAC_LEAN_EN 0xfff70000 +#define EMAC_LEAN_DI 0xffff0008 + +#define EMAC_ACCEPT_ALL 0xffff0001 +#define EMAC_ACCEPT_TAG 0xfffe0002 +#define EMAC_ACCEPT_PRIOR 0xfffc0000 + +/* Config area lies in DRAM */ +#define ICSSG_CONFIG_OFFSET 0x0 + +/* Config area lies in shared RAM */ +#define ICSSG_CONFIG_OFFSET_SLICE0 0 +#define ICSSG_CONFIG_OFFSET_SLICE1 0x8000 + +#define ICSSG_NUM_NORMAL_PDS 64 +#define ICSSG_NUM_SPECIAL_PDS 16 + +#define ICSSG_NORMAL_PD_SIZE 8 +#define ICSSG_SPECIAL_PD_SIZE 20 + +#define ICSSG_FLAG_MASK 0xff00ffff + +struct icssg_setclock_desc { + u8 request; + u8 restore; + u8 acknowledgment; + u8 cmp_status; + u32 margin; + u32 cyclecounter0_set; + u32 cyclecounter1_set; + u32 iepcount_set; + u32 rsvd1; + u32 rsvd2; + u32 CMP0_current; + u32 iepcount_current; + u32 difference; + u32 cyclecounter0_new; + u32 cyclecounter1_new; + u32 CMP0_new; +} __packed; + +#define ICSSG_CMD_POP_SLICE0 56 +#define ICSSG_CMD_POP_SLICE1 60 + +#define ICSSG_CMD_PUSH_SLICE0 57 +#define ICSSG_CMD_PUSH_SLICE1 61 + +#define ICSSG_RSP_POP_SLICE0 58 +#define ICSSG_RSP_POP_SLICE1 62 + +#define ICSSG_RSP_PUSH_SLICE0 56 +#define ICSSG_RSP_PUSH_SLICE1 60 + +#define ICSSG_TS_POP_SLICE0 59 +#define ICSSG_TS_POP_SLICE1 63 + +#define ICSSG_TS_PUSH_SLICE0 40 +#define ICSSG_TS_PUSH_SLICE1 41 + +/* FDB FID_C2 flag definitions */ +/* Indicates host port membership.*/ +#define ICSSG_FDB_ENTRY_P0_MEMBERSHIP BIT(0) +/* Indicates that MAC ID is connected to physical port 1 */ +#define ICSSG_FDB_ENTRY_P1_MEMBERSHIP BIT(1) +/* Indicates that MAC ID is connected to physical port 2 */ +#define ICSSG_FDB_ENTRY_P2_MEMBERSHIP BIT(2) +/* Ageable bit is set for learned entries and cleared for static entries */ +#define ICSSG_FDB_ENTRY_AGEABLE BIT(3) +/* If set for DA then packet is determined to be a special packet */ +#define ICSSG_FDB_ENTRY_BLOCK BIT(4) +/* If set for DA then the SA from the packet is not learned */ +#define ICSSG_FDB_ENTRY_SECURE BIT(5) +/* If set, it means packet has been seen recently with source address + FID + * matching MAC address/FID of entry + */ +#define ICSSG_FDB_ENTRY_TOUCHED BIT(6) +/* Set if entry is valid */ +#define ICSSG_FDB_ENTRY_VALID BIT(7) + +/** + * struct prueth_vlan_tbl - VLAN table entries struct in ICSSG SMEM + * @fid_c1: membership and forwarding rules flag to this table. See + * above to defines for bit definitions + * @fid: FDB index for this VID (there is 1-1 mapping b/w VID and FID) + */ +struct prueth_vlan_tbl { + u8 fid_c1; + u8 fid; +} __packed; + +/** + * struct prueth_fdb_slot - Result of FDB slot lookup + * @mac: MAC address + * @fid: fid to be associated with MAC + * @fid_c2: FID_C2 entry for this MAC + */ +struct prueth_fdb_slot { + u8 mac[ETH_ALEN]; + u8 fid; + u8 fid_c2; +} __packed; + +enum icssg_ietfpe_verify_states { + ICSSG_IETFPE_STATE_UNKNOWN = 0, + ICSSG_IETFPE_STATE_INITIAL, + ICSSG_IETFPE_STATE_VERIFYING, + ICSSG_IETFPE_STATE_SUCCEEDED, + ICSSG_IETFPE_STATE_FAILED, + ICSSG_IETFPE_STATE_DISABLED +}; +#endif /* __NET_TI_ICSSG_CONFIG_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index 8512f19a9b4d..e93488a79dbf 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -194,4 +194,19 @@ static inline int prueth_emac_slice(struct prueth_emac *emac) } } +/* Classifier helpers */ +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); +void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac); +void icssg_class_disable(struct regmap *miig_rt, int slice); +void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti); +void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr); + +/* config helpers */ +void icssg_config_ipg(struct prueth_emac *emac); +int icssg_config(struct prueth *prueth, struct prueth_emac *emac, + int slice); +int emac_set_port_state(struct prueth_emac *emac, + enum icssg_port_state_cmd state); +void icssg_config_set_speed(struct prueth_emac *emac); + #endif /* __NET_TI_ICSSG_PRUETH_H */ -- cgit From b8d5008f8c517b7cd61855fdb574b1ee80bcf4a3 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:22 +0530 Subject: net: ti: icssg-prueth: Add icssg queues APIs and macros Add icssg_queue.c file. This file introduces macros and APIs related to ICSSG queues. These will be used by ICSSG Ethernet driver. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_prueth.h | 5 +++ drivers/net/ethernet/ti/icssg/icssg_queues.c | 50 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_queues.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index e93488a79dbf..42fdf4005010 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -209,4 +209,9 @@ int emac_set_port_state(struct prueth_emac *emac, enum icssg_port_state_cmd state); void icssg_config_set_speed(struct prueth_emac *emac); +/* Buffer queue helpers */ +int icssg_queue_pop(struct prueth *prueth, u8 queue); +void icssg_queue_push(struct prueth *prueth, int queue, u16 addr); +u32 icssg_queue_level(struct prueth *prueth, int queue); + #endif /* __NET_TI_ICSSG_PRUETH_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_queues.c b/drivers/net/ethernet/ti/icssg/icssg_queues.c new file mode 100644 index 000000000000..3c34f61ad40b --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_queues.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* ICSSG Buffer queue helpers + * + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com + */ + +#include +#include "icssg_prueth.h" + +#define ICSSG_QUEUES_MAX 64 +#define ICSSG_QUEUE_OFFSET 0xd00 +#define ICSSG_QUEUE_PEEK_OFFSET 0xe00 +#define ICSSG_QUEUE_CNT_OFFSET 0xe40 +#define ICSSG_QUEUE_RESET_OFFSET 0xf40 + +int icssg_queue_pop(struct prueth *prueth, u8 queue) +{ + u32 val, cnt; + + if (queue >= ICSSG_QUEUES_MAX) + return -EINVAL; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, &cnt); + if (!cnt) + return -EINVAL; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, &val); + + return val; +} + +void icssg_queue_push(struct prueth *prueth, int queue, u16 addr) +{ + if (queue >= ICSSG_QUEUES_MAX) + return; + + regmap_write(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, addr); +} + +u32 icssg_queue_level(struct prueth *prueth, int queue) +{ + u32 reg; + + if (queue >= ICSSG_QUEUES_MAX) + return 0; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, ®); + + return reg; +} -- cgit From 128d5874c0822105ae9556d5435fb8562aff2e3b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 1 Aug 2023 14:44:24 +0530 Subject: net: ti: icssg-prueth: Add ICSSG ethernet driver This is the Ethernet driver for TI AM654 Silicon rev. 2 with the ICSSG PRU Sub-system running dual-EMAC firmware. The Programmable Real-time Unit and Industrial Communication Subsystem Gigabit (PRU_ICSSG) is a low-latency microcontroller subsystem in the TI SoCs. This subsystem is provided for the use cases like implementation of custom peripheral interfaces, offloading of tasks from the other processor cores of the SoC, etc. Every ICSSG core has two Programmable Real-Time Unit(PRUs), two auxiliary Real-Time Transfer Unit (RT_PRUs), and two Transmit Real-Time Transfer Units (TX_PRUs). Each one of these runs its own firmware. Every ICSSG core has two MII ports connect to these PRUs and also a MDIO port. The cores can run different firmwares to support different protocols and features like switch-dev, timestamping, etc. It uses System DMA to transfer and receive packets and shared memory register emulation between the firmware and driver for control and configuration. This patch adds support for basic EMAC functionality with 1Gbps and 100Mbps link speed. 10M and half duplex mode are not supported currently as they require IEP, the support for which will be added later. Support for switch-dev, timestamp, etc. will be added later by subsequent patch series. Signed-off-by: Roger Quadros Signed-off-by: Vignesh Raghavendra Signed-off-by: Grygorii Strashko Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Kconfig | 13 + drivers/net/ethernet/ti/Makefile | 8 + drivers/net/ethernet/ti/icssg/icssg_prueth.c | 1809 ++++++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 32 + 4 files changed, 1862 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_prueth.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index fce06663e1e1..63e510b6860f 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -183,4 +183,17 @@ config CPMAC help TI AR7 CPMAC Ethernet support +config TI_ICSSG_PRUETH + tristate "TI Gigabit PRU Ethernet driver" + select PHYLIB + depends on PRU_REMOTEPROC + depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER + help + Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem. + This subsystem is available starting with the AM65 platform. + + This driver requires firmware binaries which will run on the PRUs + to support the Ethernet operation. Currently, it supports Ethernet + with 1G and 100M link speed. + endif # NET_VENDOR_TI diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 75f761efbea7..efb050cbb4a8 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -28,3 +28,11 @@ obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o am65-cpsw-qos.o ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o + +obj-$(CONFIG_TI_ICSSG_PRUETH) += icssg-prueth.o +icssg-prueth-y := k3-cppi-desc-pool.o \ + icssg/icssg_prueth.o \ + icssg/icssg_classifier.o \ + icssg/icssg_queues.o \ + icssg/icssg_config.o \ + icssg/icssg_mii_cfg.o \ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c new file mode 100644 index 000000000000..1869e38f898f --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -0,0 +1,1809 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Texas Instruments ICSSG Ethernet Driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icssg_prueth.h" +#include "icssg_mii_rt.h" +#include "../k3-cppi-desc-pool.h" + +#define PRUETH_MODULE_DESCRIPTION "PRUSS ICSSG Ethernet driver" + +/* Netif debug messages possible */ +#define PRUETH_EMAC_DEBUG (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_TIMER | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR | \ + NETIF_MSG_TX_QUEUED | \ + NETIF_MSG_INTR | \ + NETIF_MSG_TX_DONE | \ + NETIF_MSG_RX_STATUS | \ + NETIF_MSG_PKTDATA | \ + NETIF_MSG_HW | \ + NETIF_MSG_WOL) + +#define prueth_napi_to_emac(napi) container_of(napi, struct prueth_emac, napi_rx) + +/* CTRLMMR_ICSSG_RGMII_CTRL register bits */ +#define ICSSG_CTRL_RGMII_ID_MODE BIT(24) + +static void prueth_cleanup_rx_chns(struct prueth_emac *emac, + struct prueth_rx_chn *rx_chn, + int max_rflows) +{ + if (rx_chn->desc_pool) + k3_cppi_desc_pool_destroy(rx_chn->desc_pool); + + if (rx_chn->rx_chn) + k3_udma_glue_release_rx_chn(rx_chn->rx_chn); +} + +static void prueth_cleanup_tx_chns(struct prueth_emac *emac) +{ + int i; + + for (i = 0; i < emac->tx_ch_num; i++) { + struct prueth_tx_chn *tx_chn = &emac->tx_chns[i]; + + if (tx_chn->desc_pool) + k3_cppi_desc_pool_destroy(tx_chn->desc_pool); + + if (tx_chn->tx_chn) + k3_udma_glue_release_tx_chn(tx_chn->tx_chn); + + /* Assume prueth_cleanup_tx_chns() is called at the + * end after all channel resources are freed + */ + memset(tx_chn, 0, sizeof(*tx_chn)); + } +} + +static void prueth_ndev_del_tx_napi(struct prueth_emac *emac, int num) +{ + int i; + + for (i = 0; i < num; i++) { + struct prueth_tx_chn *tx_chn = &emac->tx_chns[i]; + + if (tx_chn->irq) + free_irq(tx_chn->irq, tx_chn); + netif_napi_del(&tx_chn->napi_tx); + } +} + +static void prueth_xmit_free(struct prueth_tx_chn *tx_chn, + struct cppi5_host_desc_t *desc) +{ + struct cppi5_host_desc_t *first_desc, *next_desc; + dma_addr_t buf_dma, next_desc_dma; + u32 buf_dma_len; + + first_desc = desc; + next_desc = first_desc; + + cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len); + k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); + + dma_unmap_single(tx_chn->dma_dev, buf_dma, buf_dma_len, + DMA_TO_DEVICE); + + next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc); + k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); + while (next_desc_dma) { + next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, + next_desc_dma); + cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len); + k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); + + dma_unmap_page(tx_chn->dma_dev, buf_dma, buf_dma_len, + DMA_TO_DEVICE); + + next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc); + k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); + + k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); + } + + k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc); +} + +static int emac_tx_complete_packets(struct prueth_emac *emac, int chn, + int budget) +{ + struct net_device *ndev = emac->ndev; + struct cppi5_host_desc_t *desc_tx; + struct netdev_queue *netif_txq; + struct prueth_tx_chn *tx_chn; + unsigned int total_bytes = 0; + struct sk_buff *skb; + dma_addr_t desc_dma; + int res, num_tx = 0; + void **swdata; + + tx_chn = &emac->tx_chns[chn]; + + while (true) { + res = k3_udma_glue_pop_tx_chn(tx_chn->tx_chn, &desc_dma); + if (res == -ENODATA) + break; + + /* teardown completion */ + if (cppi5_desc_is_tdcm(desc_dma)) { + if (atomic_dec_and_test(&emac->tdown_cnt)) + complete(&emac->tdown_complete); + break; + } + + desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, + desc_dma); + swdata = cppi5_hdesc_get_swdata(desc_tx); + + skb = *(swdata); + prueth_xmit_free(tx_chn, desc_tx); + + ndev = skb->dev; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + total_bytes += skb->len; + napi_consume_skb(skb, budget); + num_tx++; + } + + if (!num_tx) + return 0; + + netif_txq = netdev_get_tx_queue(ndev, chn); + netdev_tx_completed_queue(netif_txq, num_tx, total_bytes); + + if (netif_tx_queue_stopped(netif_txq)) { + /* If the TX queue was stopped, wake it now + * if we have enough room. + */ + __netif_tx_lock(netif_txq, smp_processor_id()); + if (netif_running(ndev) && + (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >= + MAX_SKB_FRAGS)) + netif_tx_wake_queue(netif_txq); + __netif_tx_unlock(netif_txq); + } + + return num_tx; +} + +static int emac_napi_tx_poll(struct napi_struct *napi_tx, int budget) +{ + struct prueth_tx_chn *tx_chn = prueth_napi_to_tx_chn(napi_tx); + struct prueth_emac *emac = tx_chn->emac; + int num_tx_packets; + + num_tx_packets = emac_tx_complete_packets(emac, tx_chn->id, budget); + + if (num_tx_packets >= budget) + return budget; + + if (napi_complete_done(napi_tx, num_tx_packets)) + enable_irq(tx_chn->irq); + + return num_tx_packets; +} + +static irqreturn_t prueth_tx_irq(int irq, void *dev_id) +{ + struct prueth_tx_chn *tx_chn = dev_id; + + disable_irq_nosync(irq); + napi_schedule(&tx_chn->napi_tx); + + return IRQ_HANDLED; +} + +static int prueth_ndev_add_tx_napi(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int i, ret; + + for (i = 0; i < emac->tx_ch_num; i++) { + struct prueth_tx_chn *tx_chn = &emac->tx_chns[i]; + + netif_napi_add_tx(emac->ndev, &tx_chn->napi_tx, emac_napi_tx_poll); + ret = request_irq(tx_chn->irq, prueth_tx_irq, + IRQF_TRIGGER_HIGH, tx_chn->name, + tx_chn); + if (ret) { + netif_napi_del(&tx_chn->napi_tx); + dev_err(prueth->dev, "unable to request TX IRQ %d\n", + tx_chn->irq); + goto fail; + } + } + + return 0; +fail: + prueth_ndev_del_tx_napi(emac, i); + return ret; +} + +static int prueth_init_tx_chns(struct prueth_emac *emac) +{ + static const struct k3_ring_cfg ring_cfg = { + .elm_size = K3_RINGACC_RING_ELSIZE_8, + .mode = K3_RINGACC_RING_MODE_RING, + .flags = 0, + .size = PRUETH_MAX_TX_DESC, + }; + struct k3_udma_glue_tx_channel_cfg tx_cfg; + struct device *dev = emac->prueth->dev; + struct net_device *ndev = emac->ndev; + int ret, slice, i; + u32 hdesc_size; + + slice = prueth_emac_slice(emac); + if (slice < 0) + return slice; + + init_completion(&emac->tdown_complete); + + hdesc_size = cppi5_hdesc_calc_size(true, PRUETH_NAV_PS_DATA_SIZE, + PRUETH_NAV_SW_DATA_SIZE); + memset(&tx_cfg, 0, sizeof(tx_cfg)); + tx_cfg.swdata_size = PRUETH_NAV_SW_DATA_SIZE; + tx_cfg.tx_cfg = ring_cfg; + tx_cfg.txcq_cfg = ring_cfg; + + for (i = 0; i < emac->tx_ch_num; i++) { + struct prueth_tx_chn *tx_chn = &emac->tx_chns[i]; + + /* To differentiate channels for SLICE0 vs SLICE1 */ + snprintf(tx_chn->name, sizeof(tx_chn->name), + "tx%d-%d", slice, i); + + tx_chn->emac = emac; + tx_chn->id = i; + tx_chn->descs_num = PRUETH_MAX_TX_DESC; + + tx_chn->tx_chn = + k3_udma_glue_request_tx_chn(dev, tx_chn->name, + &tx_cfg); + if (IS_ERR(tx_chn->tx_chn)) { + ret = PTR_ERR(tx_chn->tx_chn); + tx_chn->tx_chn = NULL; + netdev_err(ndev, + "Failed to request tx dma ch: %d\n", ret); + goto fail; + } + + tx_chn->dma_dev = k3_udma_glue_tx_get_dma_device(tx_chn->tx_chn); + tx_chn->desc_pool = + k3_cppi_desc_pool_create_name(tx_chn->dma_dev, + tx_chn->descs_num, + hdesc_size, + tx_chn->name); + if (IS_ERR(tx_chn->desc_pool)) { + ret = PTR_ERR(tx_chn->desc_pool); + tx_chn->desc_pool = NULL; + netdev_err(ndev, "Failed to create tx pool: %d\n", ret); + goto fail; + } + + tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); + if (tx_chn->irq <= 0) { + ret = -EINVAL; + netdev_err(ndev, "failed to get tx irq\n"); + goto fail; + } + + snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", + dev_name(dev), tx_chn->id); + } + + return 0; + +fail: + prueth_cleanup_tx_chns(emac); + return ret; +} + +static int prueth_init_rx_chns(struct prueth_emac *emac, + struct prueth_rx_chn *rx_chn, + char *name, u32 max_rflows, + u32 max_desc_num) +{ + struct k3_udma_glue_rx_channel_cfg rx_cfg; + struct device *dev = emac->prueth->dev; + struct net_device *ndev = emac->ndev; + u32 fdqring_id, hdesc_size; + int i, ret = 0, slice; + + slice = prueth_emac_slice(emac); + if (slice < 0) + return slice; + + /* To differentiate channels for SLICE0 vs SLICE1 */ + snprintf(rx_chn->name, sizeof(rx_chn->name), "%s%d", name, slice); + + hdesc_size = cppi5_hdesc_calc_size(true, PRUETH_NAV_PS_DATA_SIZE, + PRUETH_NAV_SW_DATA_SIZE); + memset(&rx_cfg, 0, sizeof(rx_cfg)); + rx_cfg.swdata_size = PRUETH_NAV_SW_DATA_SIZE; + rx_cfg.flow_id_num = max_rflows; + rx_cfg.flow_id_base = -1; /* udmax will auto select flow id base */ + + /* init all flows */ + rx_chn->dev = dev; + rx_chn->descs_num = max_desc_num; + + rx_chn->rx_chn = k3_udma_glue_request_rx_chn(dev, rx_chn->name, + &rx_cfg); + if (IS_ERR(rx_chn->rx_chn)) { + ret = PTR_ERR(rx_chn->rx_chn); + rx_chn->rx_chn = NULL; + netdev_err(ndev, "Failed to request rx dma ch: %d\n", ret); + goto fail; + } + + rx_chn->dma_dev = k3_udma_glue_rx_get_dma_device(rx_chn->rx_chn); + rx_chn->desc_pool = k3_cppi_desc_pool_create_name(rx_chn->dma_dev, + rx_chn->descs_num, + hdesc_size, + rx_chn->name); + if (IS_ERR(rx_chn->desc_pool)) { + ret = PTR_ERR(rx_chn->desc_pool); + rx_chn->desc_pool = NULL; + netdev_err(ndev, "Failed to create rx pool: %d\n", ret); + goto fail; + } + + emac->rx_flow_id_base = k3_udma_glue_rx_get_flow_id_base(rx_chn->rx_chn); + netdev_dbg(ndev, "flow id base = %d\n", emac->rx_flow_id_base); + + fdqring_id = K3_RINGACC_RING_ID_ANY; + for (i = 0; i < rx_cfg.flow_id_num; i++) { + struct k3_ring_cfg rxring_cfg = { + .elm_size = K3_RINGACC_RING_ELSIZE_8, + .mode = K3_RINGACC_RING_MODE_RING, + .flags = 0, + }; + struct k3_ring_cfg fdqring_cfg = { + .elm_size = K3_RINGACC_RING_ELSIZE_8, + .flags = K3_RINGACC_RING_SHARED, + }; + struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = { + .rx_cfg = rxring_cfg, + .rxfdq_cfg = fdqring_cfg, + .ring_rxq_id = K3_RINGACC_RING_ID_ANY, + .src_tag_lo_sel = + K3_UDMA_GLUE_SRC_TAG_LO_USE_REMOTE_SRC_TAG, + }; + + rx_flow_cfg.ring_rxfdq0_id = fdqring_id; + rx_flow_cfg.rx_cfg.size = max_desc_num; + rx_flow_cfg.rxfdq_cfg.size = max_desc_num; + rx_flow_cfg.rxfdq_cfg.mode = emac->prueth->pdata.fdqring_mode; + + ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn, + i, &rx_flow_cfg); + if (ret) { + netdev_err(ndev, "Failed to init rx flow%d %d\n", + i, ret); + goto fail; + } + if (!i) + fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn, + i); + rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i); + if (rx_chn->irq[i] <= 0) { + ret = rx_chn->irq[i]; + netdev_err(ndev, "Failed to get rx dma irq"); + goto fail; + } + } + + return 0; + +fail: + prueth_cleanup_rx_chns(emac, rx_chn, max_rflows); + return ret; +} + +static int prueth_dma_rx_push(struct prueth_emac *emac, + struct sk_buff *skb, + struct prueth_rx_chn *rx_chn) +{ + struct net_device *ndev = emac->ndev; + struct cppi5_host_desc_t *desc_rx; + u32 pkt_len = skb_tailroom(skb); + dma_addr_t desc_dma; + dma_addr_t buf_dma; + void **swdata; + + desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool); + if (!desc_rx) { + netdev_err(ndev, "rx push: failed to allocate descriptor\n"); + return -ENOMEM; + } + desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx); + + buf_dma = dma_map_single(rx_chn->dma_dev, skb->data, pkt_len, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(rx_chn->dma_dev, buf_dma))) { + k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + netdev_err(ndev, "rx push: failed to map rx pkt buffer\n"); + return -EINVAL; + } + + cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT, + PRUETH_NAV_PS_DATA_SIZE); + k3_udma_glue_rx_dma_to_cppi5_addr(rx_chn->rx_chn, &buf_dma); + cppi5_hdesc_attach_buf(desc_rx, buf_dma, skb_tailroom(skb), buf_dma, skb_tailroom(skb)); + + swdata = cppi5_hdesc_get_swdata(desc_rx); + *swdata = skb; + + return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, 0, + desc_rx, desc_dma); +} + +static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) +{ + struct prueth_rx_chn *rx_chn = &emac->rx_chns; + u32 buf_dma_len, pkt_len, port_id = 0; + struct net_device *ndev = emac->ndev; + struct cppi5_host_desc_t *desc_rx; + struct sk_buff *skb, *new_skb; + dma_addr_t desc_dma, buf_dma; + void **swdata; + int ret; + + ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma); + if (ret) { + if (ret != -ENODATA) + netdev_err(ndev, "rx pop: failed: %d\n", ret); + return ret; + } + + if (cppi5_desc_is_tdcm(desc_dma)) /* Teardown ? */ + return 0; + + desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma); + + swdata = cppi5_hdesc_get_swdata(desc_rx); + skb = *swdata; + + cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); + k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); + pkt_len = cppi5_hdesc_get_pktlen(desc_rx); + /* firmware adds 4 CRC bytes, strip them */ + pkt_len -= 4; + cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL); + + dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); + k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + + skb->dev = ndev; + new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE); + /* if allocation fails we drop the packet but push the + * descriptor back to the ring with old skb to prevent a stall + */ + if (!new_skb) { + ndev->stats.rx_dropped++; + new_skb = skb; + } else { + /* send the filled skb up the n/w stack */ + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, ndev); + napi_gro_receive(&emac->napi_rx, skb); + ndev->stats.rx_bytes += pkt_len; + ndev->stats.rx_packets++; + } + + /* queue another RX DMA */ + ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_chns); + if (WARN_ON(ret < 0)) { + dev_kfree_skb_any(new_skb); + ndev->stats.rx_errors++; + ndev->stats.rx_dropped++; + } + + return ret; +} + +static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma) +{ + struct prueth_rx_chn *rx_chn = data; + struct cppi5_host_desc_t *desc_rx; + struct sk_buff *skb; + dma_addr_t buf_dma; + u32 buf_dma_len; + void **swdata; + + desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma); + swdata = cppi5_hdesc_get_swdata(desc_rx); + skb = *swdata; + cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); + k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); + + dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, + DMA_FROM_DEVICE); + k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + + dev_kfree_skb_any(skb); +} + +/** + * emac_ndo_start_xmit - EMAC Transmit function + * @skb: SKB pointer + * @ndev: EMAC network adapter + * + * Called by the system to transmit a packet - we queue the packet in + * EMAC hardware transmit queue + * Doesn't wait for completion we'll check for TX completion in + * emac_tx_complete_packets(). + * + * Return: enum netdev_tx + */ +static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; + struct prueth_emac *emac = netdev_priv(ndev); + struct netdev_queue *netif_txq; + struct prueth_tx_chn *tx_chn; + dma_addr_t desc_dma, buf_dma; + int i, ret = 0, q_idx; + void **swdata; + u32 pkt_len; + u32 *epib; + + pkt_len = skb_headlen(skb); + q_idx = skb_get_queue_mapping(skb); + + tx_chn = &emac->tx_chns[q_idx]; + netif_txq = netdev_get_tx_queue(ndev, q_idx); + + /* Map the linear buffer */ + buf_dma = dma_map_single(tx_chn->dma_dev, skb->data, pkt_len, DMA_TO_DEVICE); + if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) { + netdev_err(ndev, "tx: failed to map skb buffer\n"); + ret = NETDEV_TX_OK; + goto drop_free_skb; + } + + first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool); + if (!first_desc) { + netdev_dbg(ndev, "tx: failed to allocate descriptor\n"); + dma_unmap_single(tx_chn->dma_dev, buf_dma, pkt_len, DMA_TO_DEVICE); + goto drop_stop_q_busy; + } + + cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT, + PRUETH_NAV_PS_DATA_SIZE); + cppi5_hdesc_set_pkttype(first_desc, 0); + epib = first_desc->epib; + epib[0] = 0; + epib[1] = 0; + + /* set dst tag to indicate internal qid at the firmware which is at + * bit8..bit15. bit0..bit7 indicates port num for directed + * packets in case of switch mode operation + */ + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); + k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); + cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); + swdata = cppi5_hdesc_get_swdata(first_desc); + *swdata = skb; + + /* Handle the case where skb is fragmented in pages */ + cur_desc = first_desc; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + u32 frag_size = skb_frag_size(frag); + + next_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool); + if (!next_desc) { + netdev_err(ndev, + "tx: failed to allocate frag. descriptor\n"); + goto free_desc_stop_q_busy; + } + + buf_dma = skb_frag_dma_map(tx_chn->dma_dev, frag, 0, frag_size, + DMA_TO_DEVICE); + if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) { + netdev_err(ndev, "tx: Failed to map skb page\n"); + k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); + ret = NETDEV_TX_OK; + goto drop_free_descs; + } + + cppi5_hdesc_reset_hbdesc(next_desc); + k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); + cppi5_hdesc_attach_buf(next_desc, + buf_dma, frag_size, buf_dma, frag_size); + + desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, + next_desc); + k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &desc_dma); + cppi5_hdesc_link_hbdesc(cur_desc, desc_dma); + + pkt_len += frag_size; + cur_desc = next_desc; + } + WARN_ON_ONCE(pkt_len != skb->len); + + /* report bql before sending packet */ + netdev_tx_sent_queue(netif_txq, pkt_len); + + cppi5_hdesc_set_pktlen(first_desc, pkt_len); + desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc); + /* cppi5_desc_dump(first_desc, 64); */ + + skb_tx_timestamp(skb); /* SW timestamp if SKBTX_IN_PROGRESS not set */ + ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma); + if (ret) { + netdev_err(ndev, "tx: push failed: %d\n", ret); + goto drop_free_descs; + } + + if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) { + netif_tx_stop_queue(netif_txq); + /* Barrier, so that stop_queue visible to other cpus */ + smp_mb__after_atomic(); + + if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >= + MAX_SKB_FRAGS) + netif_tx_wake_queue(netif_txq); + } + + return NETDEV_TX_OK; + +drop_free_descs: + prueth_xmit_free(tx_chn, first_desc); + +drop_free_skb: + dev_kfree_skb_any(skb); + + /* error */ + ndev->stats.tx_dropped++; + netdev_err(ndev, "tx: error: %d\n", ret); + + return ret; + +free_desc_stop_q_busy: + prueth_xmit_free(tx_chn, first_desc); + +drop_stop_q_busy: + netif_tx_stop_queue(netif_txq); + return NETDEV_TX_BUSY; +} + +static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma) +{ + struct prueth_tx_chn *tx_chn = data; + struct cppi5_host_desc_t *desc_tx; + struct sk_buff *skb; + void **swdata; + + desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); + swdata = cppi5_hdesc_get_swdata(desc_tx); + skb = *(swdata); + prueth_xmit_free(tx_chn, desc_tx); + + dev_kfree_skb_any(skb); +} + +static irqreturn_t prueth_rx_irq(int irq, void *dev_id) +{ + struct prueth_emac *emac = dev_id; + + disable_irq_nosync(irq); + napi_schedule(&emac->napi_rx); + + return IRQ_HANDLED; +} + +struct icssg_firmwares { + char *pru; + char *rtu; + char *txpru; +}; + +static struct icssg_firmwares icssg_emac_firmwares[] = { + { + .pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", + .rtu = "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", + .txpru = "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", + }, + { + .pru = "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", + .rtu = "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", + .txpru = "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", + } +}; + +static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac) +{ + struct icssg_firmwares *firmwares; + struct device *dev = prueth->dev; + int slice, ret; + + firmwares = icssg_emac_firmwares; + + slice = prueth_emac_slice(emac); + if (slice < 0) { + netdev_err(emac->ndev, "invalid port\n"); + return -EINVAL; + } + + ret = icssg_config(prueth, emac, slice); + if (ret) + return ret; + + ret = rproc_set_firmware(prueth->pru[slice], firmwares[slice].pru); + ret = rproc_boot(prueth->pru[slice]); + if (ret) { + dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret); + return -EINVAL; + } + + ret = rproc_set_firmware(prueth->rtu[slice], firmwares[slice].rtu); + ret = rproc_boot(prueth->rtu[slice]); + if (ret) { + dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret); + goto halt_pru; + } + + ret = rproc_set_firmware(prueth->txpru[slice], firmwares[slice].txpru); + ret = rproc_boot(prueth->txpru[slice]); + if (ret) { + dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret); + goto halt_rtu; + } + + emac->fw_running = 1; + return 0; + +halt_rtu: + rproc_shutdown(prueth->rtu[slice]); + +halt_pru: + rproc_shutdown(prueth->pru[slice]); + + return ret; +} + +static void prueth_emac_stop(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int slice; + + switch (emac->port_id) { + case PRUETH_PORT_MII0: + slice = ICSS_SLICE0; + break; + case PRUETH_PORT_MII1: + slice = ICSS_SLICE1; + break; + default: + netdev_err(emac->ndev, "invalid port\n"); + return; + } + + emac->fw_running = 0; + rproc_shutdown(prueth->txpru[slice]); + rproc_shutdown(prueth->rtu[slice]); + rproc_shutdown(prueth->pru[slice]); +} + +/* called back by PHY layer if there is change in link state of hw port*/ +static void emac_adjust_link(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct phy_device *phydev = ndev->phydev; + struct prueth *prueth = emac->prueth; + bool new_state = false; + unsigned long flags; + + if (phydev->link) { + /* check the mode of operation - full/half duplex */ + if (phydev->duplex != emac->duplex) { + new_state = true; + emac->duplex = phydev->duplex; + } + if (phydev->speed != emac->speed) { + new_state = true; + emac->speed = phydev->speed; + } + if (!emac->link) { + new_state = true; + emac->link = 1; + } + } else if (emac->link) { + new_state = true; + emac->link = 0; + + /* f/w should support 100 & 1000 */ + emac->speed = SPEED_1000; + + /* half duplex may not be supported by f/w */ + emac->duplex = DUPLEX_FULL; + } + + if (new_state) { + phy_print_status(phydev); + + /* update RGMII and MII configuration based on PHY negotiated + * values + */ + if (emac->link) { + /* Set the RGMII cfg for gig en and full duplex */ + icssg_update_rgmii_cfg(prueth->miig_rt, emac); + + /* update the Tx IPG based on 100M/1G speed */ + spin_lock_irqsave(&emac->lock, flags); + icssg_config_ipg(emac); + spin_unlock_irqrestore(&emac->lock, flags); + icssg_config_set_speed(emac); + emac_set_port_state(emac, ICSSG_EMAC_PORT_FORWARD); + + } else { + emac_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE); + } + } + + if (emac->link) { + /* reactivate the transmit queue */ + netif_tx_wake_all_queues(ndev); + } else { + netif_tx_stop_all_queues(ndev); + } +} + +static int emac_napi_rx_poll(struct napi_struct *napi_rx, int budget) +{ + struct prueth_emac *emac = prueth_napi_to_emac(napi_rx); + int rx_flow = PRUETH_RX_FLOW_DATA; + int flow = PRUETH_MAX_RX_FLOWS; + int num_rx = 0; + int cur_budget; + int ret; + + while (flow--) { + cur_budget = budget - num_rx; + + while (cur_budget--) { + ret = emac_rx_packet(emac, flow); + if (ret) + break; + num_rx++; + } + + if (num_rx >= budget) + break; + } + + if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) + enable_irq(emac->rx_chns.irq[rx_flow]); + + return num_rx; +} + +static int prueth_prepare_rx_chan(struct prueth_emac *emac, + struct prueth_rx_chn *chn, + int buf_size) +{ + struct sk_buff *skb; + int i, ret; + + for (i = 0; i < chn->descs_num; i++) { + skb = __netdev_alloc_skb_ip_align(NULL, buf_size, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + ret = prueth_dma_rx_push(emac, skb, chn); + if (ret < 0) { + netdev_err(emac->ndev, + "cannot submit skb for rx chan %s ret %d\n", + chn->name, ret); + kfree_skb(skb); + return ret; + } + } + + return 0; +} + +static void prueth_reset_tx_chan(struct prueth_emac *emac, int ch_num, + bool free_skb) +{ + int i; + + for (i = 0; i < ch_num; i++) { + if (free_skb) + k3_udma_glue_reset_tx_chn(emac->tx_chns[i].tx_chn, + &emac->tx_chns[i], + prueth_tx_cleanup); + k3_udma_glue_disable_tx_chn(emac->tx_chns[i].tx_chn); + } +} + +static void prueth_reset_rx_chan(struct prueth_rx_chn *chn, + int num_flows, bool disable) +{ + int i; + + for (i = 0; i < num_flows; i++) + k3_udma_glue_reset_rx_chn(chn->rx_chn, i, chn, + prueth_rx_cleanup, !!i); + if (disable) + k3_udma_glue_disable_rx_chn(chn->rx_chn); +} + +static int emac_phy_connect(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + struct net_device *ndev = emac->ndev; + /* connect PHY */ + ndev->phydev = of_phy_connect(emac->ndev, emac->phy_node, + &emac_adjust_link, 0, + emac->phy_if); + if (!ndev->phydev) { + dev_err(prueth->dev, "couldn't connect to phy %s\n", + emac->phy_node->full_name); + return -ENODEV; + } + + /* remove unsupported modes */ + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT); + + if (emac->phy_if == PHY_INTERFACE_MODE_MII) + phy_set_max_speed(ndev->phydev, SPEED_100); + + return 0; +} + +/** + * emac_ndo_open - EMAC device open + * @ndev: network adapter device + * + * Called when system wants to start the interface. + * + * Return: 0 for a successful open, or appropriate error code + */ +static int emac_ndo_open(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + int ret, i, num_data_chn = emac->tx_ch_num; + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + struct device *dev = prueth->dev; + int max_rx_flows; + int rx_flow; + + /* clear SMEM and MSMC settings for all slices */ + if (!prueth->emacs_initialized) { + memset_io(prueth->msmcram.va, 0, prueth->msmcram.size); + memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS); + } + + /* set h/w MAC as user might have re-configured */ + ether_addr_copy(emac->mac_addr, ndev->dev_addr); + + icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr); + icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr); + + icssg_class_default(prueth->miig_rt, slice, 0); + + /* Notify the stack of the actual queue counts. */ + ret = netif_set_real_num_tx_queues(ndev, num_data_chn); + if (ret) { + dev_err(dev, "cannot set real number of tx queues\n"); + return ret; + } + + init_completion(&emac->cmd_complete); + ret = prueth_init_tx_chns(emac); + if (ret) { + dev_err(dev, "failed to init tx channel: %d\n", ret); + return ret; + } + + max_rx_flows = PRUETH_MAX_RX_FLOWS; + ret = prueth_init_rx_chns(emac, &emac->rx_chns, "rx", + max_rx_flows, PRUETH_MAX_RX_DESC); + if (ret) { + dev_err(dev, "failed to init rx channel: %d\n", ret); + goto cleanup_tx; + } + + ret = prueth_ndev_add_tx_napi(emac); + if (ret) + goto cleanup_rx; + + /* we use only the highest priority flow for now i.e. @irq[3] */ + rx_flow = PRUETH_RX_FLOW_DATA; + ret = request_irq(emac->rx_chns.irq[rx_flow], prueth_rx_irq, + IRQF_TRIGGER_HIGH, dev_name(dev), emac); + if (ret) { + dev_err(dev, "unable to request RX IRQ\n"); + goto cleanup_napi; + } + + /* reset and start PRU firmware */ + ret = prueth_emac_start(prueth, emac); + if (ret) + goto free_rx_irq; + + icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu); + + /* Prepare RX */ + ret = prueth_prepare_rx_chan(emac, &emac->rx_chns, PRUETH_MAX_PKT_SIZE); + if (ret) + goto stop; + + ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn); + if (ret) + goto reset_rx_chn; + + for (i = 0; i < emac->tx_ch_num; i++) { + ret = k3_udma_glue_enable_tx_chn(emac->tx_chns[i].tx_chn); + if (ret) + goto reset_tx_chan; + } + + /* Enable NAPI in Tx and Rx direction */ + for (i = 0; i < emac->tx_ch_num; i++) + napi_enable(&emac->tx_chns[i].napi_tx); + napi_enable(&emac->napi_rx); + + /* start PHY */ + phy_start(ndev->phydev); + + prueth->emacs_initialized++; + + return 0; + +reset_tx_chan: + /* Since interface is not yet up, there is wouldn't be + * any SKB for completion. So set false to free_skb + */ + prueth_reset_tx_chan(emac, i, false); +reset_rx_chn: + prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false); +stop: + prueth_emac_stop(emac); +free_rx_irq: + free_irq(emac->rx_chns.irq[rx_flow], emac); +cleanup_napi: + prueth_ndev_del_tx_napi(emac, emac->tx_ch_num); +cleanup_rx: + prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows); +cleanup_tx: + prueth_cleanup_tx_chns(emac); + + return ret; +} + +/** + * emac_ndo_stop - EMAC device stop + * @ndev: network adapter device + * + * Called when system wants to stop or down the interface. + * + * Return: Always 0 (Success) + */ +static int emac_ndo_stop(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct prueth *prueth = emac->prueth; + int rx_flow = PRUETH_RX_FLOW_DATA; + int max_rx_flows; + int ret, i; + + /* inform the upper layers. */ + netif_tx_stop_all_queues(ndev); + + /* block packets from wire */ + if (ndev->phydev) + phy_stop(ndev->phydev); + + icssg_class_disable(prueth->miig_rt, prueth_emac_slice(emac)); + + atomic_set(&emac->tdown_cnt, emac->tx_ch_num); + /* ensure new tdown_cnt value is visible */ + smp_mb__after_atomic(); + /* tear down and disable UDMA channels */ + reinit_completion(&emac->tdown_complete); + for (i = 0; i < emac->tx_ch_num; i++) + k3_udma_glue_tdown_tx_chn(emac->tx_chns[i].tx_chn, false); + + ret = wait_for_completion_timeout(&emac->tdown_complete, + msecs_to_jiffies(1000)); + if (!ret) + netdev_err(ndev, "tx teardown timeout\n"); + + prueth_reset_tx_chan(emac, emac->tx_ch_num, true); + for (i = 0; i < emac->tx_ch_num; i++) + napi_disable(&emac->tx_chns[i].napi_tx); + + max_rx_flows = PRUETH_MAX_RX_FLOWS; + k3_udma_glue_tdown_rx_chn(emac->rx_chns.rx_chn, true); + + prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, true); + + napi_disable(&emac->napi_rx); + + cancel_work_sync(&emac->rx_mode_work); + + /* stop PRUs */ + prueth_emac_stop(emac); + + free_irq(emac->rx_chns.irq[rx_flow], emac); + prueth_ndev_del_tx_napi(emac, emac->tx_ch_num); + prueth_cleanup_tx_chns(emac); + + prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows); + prueth_cleanup_tx_chns(emac); + + prueth->emacs_initialized--; + + return 0; +} + +static void emac_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue) +{ + ndev->stats.tx_errors++; +} + +static void emac_ndo_set_rx_mode_work(struct work_struct *work) +{ + struct prueth_emac *emac = container_of(work, struct prueth_emac, rx_mode_work); + struct net_device *ndev = emac->ndev; + bool promisc, allmulti; + + if (!netif_running(ndev)) + return; + + promisc = ndev->flags & IFF_PROMISC; + allmulti = ndev->flags & IFF_ALLMULTI; + emac_set_port_state(emac, ICSSG_EMAC_PORT_UC_FLOODING_DISABLE); + emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_DISABLE); + + if (promisc) { + emac_set_port_state(emac, ICSSG_EMAC_PORT_UC_FLOODING_ENABLE); + emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_ENABLE); + return; + } + + if (allmulti) { + emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_ENABLE); + return; + } + + if (!netdev_mc_empty(ndev)) { + emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_ENABLE); + return; + } +} + +/** + * emac_ndo_set_rx_mode - EMAC set receive mode function + * @ndev: The EMAC network adapter + * + * Called when system wants to set the receive mode of the device. + * + */ +static void emac_ndo_set_rx_mode(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + queue_work(emac->cmd_wq, &emac->rx_mode_work); +} + +static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + return phy_do_ioctl(ndev, ifr, cmd); +} + +static const struct net_device_ops emac_netdev_ops = { + .ndo_open = emac_ndo_open, + .ndo_stop = emac_ndo_stop, + .ndo_start_xmit = emac_ndo_start_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_tx_timeout = emac_ndo_tx_timeout, + .ndo_set_rx_mode = emac_ndo_set_rx_mode, + .ndo_eth_ioctl = emac_ndo_ioctl, +}; + +/* get emac_port corresponding to eth_node name */ +static int prueth_node_port(struct device_node *eth_node) +{ + u32 port_id; + int ret; + + ret = of_property_read_u32(eth_node, "reg", &port_id); + if (ret) + return ret; + + if (port_id == 0) + return PRUETH_PORT_MII0; + else if (port_id == 1) + return PRUETH_PORT_MII1; + else + return PRUETH_PORT_INVALID; +} + +/* get MAC instance corresponding to eth_node name */ +static int prueth_node_mac(struct device_node *eth_node) +{ + u32 port_id; + int ret; + + ret = of_property_read_u32(eth_node, "reg", &port_id); + if (ret) + return ret; + + if (port_id == 0) + return PRUETH_MAC0; + else if (port_id == 1) + return PRUETH_MAC1; + else + return PRUETH_MAC_INVALID; +} + +static int prueth_netdev_init(struct prueth *prueth, + struct device_node *eth_node) +{ + int ret, num_tx_chn = PRUETH_MAX_TX_QUEUES; + struct prueth_emac *emac; + struct net_device *ndev; + enum prueth_port port; + enum prueth_mac mac; + + port = prueth_node_port(eth_node); + if (port == PRUETH_PORT_INVALID) + return -EINVAL; + + mac = prueth_node_mac(eth_node); + if (mac == PRUETH_MAC_INVALID) + return -EINVAL; + + ndev = alloc_etherdev_mq(sizeof(*emac), num_tx_chn); + if (!ndev) + return -ENOMEM; + + emac = netdev_priv(ndev); + emac->prueth = prueth; + emac->ndev = ndev; + emac->port_id = port; + emac->cmd_wq = create_singlethread_workqueue("icssg_cmd_wq"); + if (!emac->cmd_wq) { + ret = -ENOMEM; + goto free_ndev; + } + INIT_WORK(&emac->rx_mode_work, emac_ndo_set_rx_mode_work); + + ret = pruss_request_mem_region(prueth->pruss, + port == PRUETH_PORT_MII0 ? + PRUSS_MEM_DRAM0 : PRUSS_MEM_DRAM1, + &emac->dram); + if (ret) { + dev_err(prueth->dev, "unable to get DRAM: %d\n", ret); + ret = -ENOMEM; + goto free_wq; + } + + emac->tx_ch_num = 1; + + SET_NETDEV_DEV(ndev, prueth->dev); + spin_lock_init(&emac->lock); + mutex_init(&emac->cmd_lock); + + emac->phy_node = of_parse_phandle(eth_node, "phy-handle", 0); + if (!emac->phy_node && !of_phy_is_fixed_link(eth_node)) { + dev_err(prueth->dev, "couldn't find phy-handle\n"); + ret = -ENODEV; + goto free; + } else if (of_phy_is_fixed_link(eth_node)) { + ret = of_phy_register_fixed_link(eth_node); + if (ret) { + ret = dev_err_probe(prueth->dev, ret, + "failed to register fixed-link phy\n"); + goto free; + } + + emac->phy_node = eth_node; + } + + ret = of_get_phy_mode(eth_node, &emac->phy_if); + if (ret) { + dev_err(prueth->dev, "could not get phy-mode property\n"); + goto free; + } + + if (emac->phy_if != PHY_INTERFACE_MODE_MII && + !phy_interface_mode_is_rgmii(emac->phy_if)) { + dev_err(prueth->dev, "PHY mode unsupported %s\n", phy_modes(emac->phy_if)); + ret = -EINVAL; + goto free; + } + + /* AM65 SR2.0 has TX Internal delay always enabled by hardware + * and it is not possible to disable TX Internal delay. The below + * switch case block describes how we handle different phy modes + * based on hardware restriction. + */ + switch (emac->phy_if) { + case PHY_INTERFACE_MODE_RGMII_ID: + emac->phy_if = PHY_INTERFACE_MODE_RGMII_RXID; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + emac->phy_if = PHY_INTERFACE_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_RXID: + dev_err(prueth->dev, "RGMII mode without TX delay is not supported"); + ret = -EINVAL; + goto free; + default: + break; + } + + /* get mac address from DT and set private and netdev addr */ + ret = of_get_ethdev_address(eth_node, ndev); + if (!is_valid_ether_addr(ndev->dev_addr)) { + eth_hw_addr_random(ndev); + dev_warn(prueth->dev, "port %d: using random MAC addr: %pM\n", + port, ndev->dev_addr); + } + ether_addr_copy(emac->mac_addr, ndev->dev_addr); + + ndev->min_mtu = PRUETH_MIN_PKT_SIZE; + ndev->max_mtu = PRUETH_MAX_MTU; + ndev->netdev_ops = &emac_netdev_ops; + ndev->hw_features = NETIF_F_SG; + ndev->features = ndev->hw_features; + + netif_napi_add(ndev, &emac->napi_rx, emac_napi_rx_poll); + prueth->emac[mac] = emac; + + return 0; + +free: + pruss_release_mem_region(prueth->pruss, &emac->dram); +free_wq: + destroy_workqueue(emac->cmd_wq); +free_ndev: + emac->ndev = NULL; + prueth->emac[mac] = NULL; + free_netdev(ndev); + + return ret; +} + +static void prueth_netdev_exit(struct prueth *prueth, + struct device_node *eth_node) +{ + struct prueth_emac *emac; + enum prueth_mac mac; + + mac = prueth_node_mac(eth_node); + if (mac == PRUETH_MAC_INVALID) + return; + + emac = prueth->emac[mac]; + if (!emac) + return; + + if (of_phy_is_fixed_link(emac->phy_node)) + of_phy_deregister_fixed_link(emac->phy_node); + + netif_napi_del(&emac->napi_rx); + + pruss_release_mem_region(prueth->pruss, &emac->dram); + destroy_workqueue(emac->cmd_wq); + free_netdev(emac->ndev); + prueth->emac[mac] = NULL; +} + +static int prueth_get_cores(struct prueth *prueth, int slice) +{ + struct device *dev = prueth->dev; + enum pruss_pru_id pruss_id; + struct device_node *np; + int idx = -1, ret; + + np = dev->of_node; + + switch (slice) { + case ICSS_SLICE0: + idx = 0; + break; + case ICSS_SLICE1: + idx = 3; + break; + default: + return -EINVAL; + } + + prueth->pru[slice] = pru_rproc_get(np, idx, &pruss_id); + if (IS_ERR(prueth->pru[slice])) { + ret = PTR_ERR(prueth->pru[slice]); + prueth->pru[slice] = NULL; + return dev_err_probe(dev, ret, "unable to get PRU%d\n", slice); + } + prueth->pru_id[slice] = pruss_id; + + idx++; + prueth->rtu[slice] = pru_rproc_get(np, idx, NULL); + if (IS_ERR(prueth->rtu[slice])) { + ret = PTR_ERR(prueth->rtu[slice]); + prueth->rtu[slice] = NULL; + return dev_err_probe(dev, ret, "unable to get RTU%d\n", slice); + } + + idx++; + prueth->txpru[slice] = pru_rproc_get(np, idx, NULL); + if (IS_ERR(prueth->txpru[slice])) { + ret = PTR_ERR(prueth->txpru[slice]); + prueth->txpru[slice] = NULL; + return dev_err_probe(dev, ret, "unable to get TX_PRU%d\n", slice); + } + + return 0; +} + +static void prueth_put_cores(struct prueth *prueth, int slice) +{ + if (prueth->txpru[slice]) + pru_rproc_put(prueth->txpru[slice]); + + if (prueth->rtu[slice]) + pru_rproc_put(prueth->rtu[slice]); + + if (prueth->pru[slice]) + pru_rproc_put(prueth->pru[slice]); +} + +static const struct of_device_id prueth_dt_match[]; + +static int prueth_probe(struct platform_device *pdev) +{ + struct device_node *eth_node, *eth_ports_node; + struct device_node *eth0_node = NULL; + struct device_node *eth1_node = NULL; + struct genpool_data_align gp_data = { + .align = SZ_64K, + }; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct device_node *np; + struct prueth *prueth; + struct pruss *pruss; + u32 msmc_ram_size; + int i, ret; + + np = dev->of_node; + + match = of_match_device(prueth_dt_match, dev); + if (!match) + return -ENODEV; + + prueth = devm_kzalloc(dev, sizeof(*prueth), GFP_KERNEL); + if (!prueth) + return -ENOMEM; + + dev_set_drvdata(dev, prueth); + prueth->pdev = pdev; + prueth->pdata = *(const struct prueth_pdata *)match->data; + + prueth->dev = dev; + eth_ports_node = of_get_child_by_name(np, "ethernet-ports"); + if (!eth_ports_node) + return -ENOENT; + + for_each_child_of_node(eth_ports_node, eth_node) { + u32 reg; + + if (strcmp(eth_node->name, "port")) + continue; + ret = of_property_read_u32(eth_node, "reg", ®); + if (ret < 0) { + dev_err(dev, "%pOF error reading port_id %d\n", + eth_node, ret); + } + + of_node_get(eth_node); + + if (reg == 0) { + eth0_node = eth_node; + if (!of_device_is_available(eth0_node)) { + of_node_put(eth0_node); + eth0_node = NULL; + } + } else if (reg == 1) { + eth1_node = eth_node; + if (!of_device_is_available(eth1_node)) { + of_node_put(eth1_node); + eth1_node = NULL; + } + } else { + dev_err(dev, "port reg should be 0 or 1\n"); + } + } + + of_node_put(eth_ports_node); + + /* At least one node must be present and available else we fail */ + if (!eth0_node && !eth1_node) { + dev_err(dev, "neither port0 nor port1 node available\n"); + return -ENODEV; + } + + if (eth0_node == eth1_node) { + dev_err(dev, "port0 and port1 can't have same reg\n"); + of_node_put(eth0_node); + return -ENODEV; + } + + prueth->eth_node[PRUETH_MAC0] = eth0_node; + prueth->eth_node[PRUETH_MAC1] = eth1_node; + + prueth->miig_rt = syscon_regmap_lookup_by_phandle(np, "ti,mii-g-rt"); + if (IS_ERR(prueth->miig_rt)) { + dev_err(dev, "couldn't get ti,mii-g-rt syscon regmap\n"); + return -ENODEV; + } + + prueth->mii_rt = syscon_regmap_lookup_by_phandle(np, "ti,mii-rt"); + if (IS_ERR(prueth->mii_rt)) { + dev_err(dev, "couldn't get ti,mii-rt syscon regmap\n"); + return -ENODEV; + } + + if (eth0_node) { + ret = prueth_get_cores(prueth, ICSS_SLICE0); + if (ret) + goto put_cores; + } + + if (eth1_node) { + ret = prueth_get_cores(prueth, ICSS_SLICE1); + if (ret) + goto put_cores; + } + + pruss = pruss_get(eth0_node ? + prueth->pru[ICSS_SLICE0] : prueth->pru[ICSS_SLICE1]); + if (IS_ERR(pruss)) { + ret = PTR_ERR(pruss); + dev_err(dev, "unable to get pruss handle\n"); + goto put_cores; + } + + prueth->pruss = pruss; + + ret = pruss_request_mem_region(pruss, PRUSS_MEM_SHRD_RAM2, + &prueth->shram); + if (ret) { + dev_err(dev, "unable to get PRUSS SHRD RAM2: %d\n", ret); + pruss_put(prueth->pruss); + } + + prueth->sram_pool = of_gen_pool_get(np, "sram", 0); + if (!prueth->sram_pool) { + dev_err(dev, "unable to get SRAM pool\n"); + ret = -ENODEV; + + goto put_mem; + } + + msmc_ram_size = MSMC_RAM_SIZE; + + /* NOTE: FW bug needs buffer base to be 64KB aligned */ + prueth->msmcram.va = + (void __iomem *)gen_pool_alloc_algo(prueth->sram_pool, + msmc_ram_size, + gen_pool_first_fit_align, + &gp_data); + + if (!prueth->msmcram.va) { + ret = -ENOMEM; + dev_err(dev, "unable to allocate MSMC resource\n"); + goto put_mem; + } + prueth->msmcram.pa = gen_pool_virt_to_phys(prueth->sram_pool, + (unsigned long)prueth->msmcram.va); + prueth->msmcram.size = msmc_ram_size; + memset_io(prueth->msmcram.va, 0, msmc_ram_size); + dev_dbg(dev, "sram: pa %llx va %p size %zx\n", prueth->msmcram.pa, + prueth->msmcram.va, prueth->msmcram.size); + + /* setup netdev interfaces */ + if (eth0_node) { + ret = prueth_netdev_init(prueth, eth0_node); + if (ret) { + dev_err_probe(dev, ret, "netdev init %s failed\n", + eth0_node->name); + goto netdev_exit; + } + } + + if (eth1_node) { + ret = prueth_netdev_init(prueth, eth1_node); + if (ret) { + dev_err_probe(dev, ret, "netdev init %s failed\n", + eth1_node->name); + goto netdev_exit; + } + } + + /* register the network devices */ + if (eth0_node) { + ret = register_netdev(prueth->emac[PRUETH_MAC0]->ndev); + if (ret) { + dev_err(dev, "can't register netdev for port MII0"); + goto netdev_exit; + } + + prueth->registered_netdevs[PRUETH_MAC0] = prueth->emac[PRUETH_MAC0]->ndev; + + emac_phy_connect(prueth->emac[PRUETH_MAC0]); + phy_attached_info(prueth->emac[PRUETH_MAC0]->ndev->phydev); + } + + if (eth1_node) { + ret = register_netdev(prueth->emac[PRUETH_MAC1]->ndev); + if (ret) { + dev_err(dev, "can't register netdev for port MII1"); + goto netdev_unregister; + } + + prueth->registered_netdevs[PRUETH_MAC1] = prueth->emac[PRUETH_MAC1]->ndev; + emac_phy_connect(prueth->emac[PRUETH_MAC1]); + phy_attached_info(prueth->emac[PRUETH_MAC1]->ndev->phydev); + } + + dev_info(dev, "TI PRU ethernet driver initialized: %s EMAC mode\n", + (!eth0_node || !eth1_node) ? "single" : "dual"); + + if (eth1_node) + of_node_put(eth1_node); + if (eth0_node) + of_node_put(eth0_node); + return 0; + +netdev_unregister: + for (i = 0; i < PRUETH_NUM_MACS; i++) { + if (!prueth->registered_netdevs[i]) + continue; + if (prueth->emac[i]->ndev->phydev) { + phy_disconnect(prueth->emac[i]->ndev->phydev); + prueth->emac[i]->ndev->phydev = NULL; + } + unregister_netdev(prueth->registered_netdevs[i]); + } + +netdev_exit: + for (i = 0; i < PRUETH_NUM_MACS; i++) { + eth_node = prueth->eth_node[i]; + if (!eth_node) + continue; + + prueth_netdev_exit(prueth, eth_node); + } + + gen_pool_free(prueth->sram_pool, + (unsigned long)prueth->msmcram.va, msmc_ram_size); + +put_mem: + pruss_release_mem_region(prueth->pruss, &prueth->shram); + pruss_put(prueth->pruss); + +put_cores: + if (eth1_node) { + prueth_put_cores(prueth, ICSS_SLICE1); + of_node_put(eth1_node); + } + + if (eth0_node) { + prueth_put_cores(prueth, ICSS_SLICE0); + of_node_put(eth0_node); + } + + return ret; +} + +static void prueth_remove(struct platform_device *pdev) +{ + struct prueth *prueth = platform_get_drvdata(pdev); + struct device_node *eth_node; + int i; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + if (!prueth->registered_netdevs[i]) + continue; + phy_stop(prueth->emac[i]->ndev->phydev); + phy_disconnect(prueth->emac[i]->ndev->phydev); + prueth->emac[i]->ndev->phydev = NULL; + unregister_netdev(prueth->registered_netdevs[i]); + } + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + eth_node = prueth->eth_node[i]; + if (!eth_node) + continue; + + prueth_netdev_exit(prueth, eth_node); + } + + gen_pool_free(prueth->sram_pool, + (unsigned long)prueth->msmcram.va, + MSMC_RAM_SIZE); + + pruss_release_mem_region(prueth->pruss, &prueth->shram); + + pruss_put(prueth->pruss); + + if (prueth->eth_node[PRUETH_MAC1]) + prueth_put_cores(prueth, ICSS_SLICE1); + + if (prueth->eth_node[PRUETH_MAC0]) + prueth_put_cores(prueth, ICSS_SLICE0); +} + +static const struct prueth_pdata am654_icssg_pdata = { + .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE, + .quirk_10m_link_issue = 1, +}; + +static const struct of_device_id prueth_dt_match[] = { + { .compatible = "ti,am654-icssg-prueth", .data = &am654_icssg_pdata }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, prueth_dt_match); + +static struct platform_driver prueth_driver = { + .probe = prueth_probe, + .remove_new = prueth_remove, + .driver = { + .name = "icssg-prueth", + .of_match_table = prueth_dt_match, + }, +}; +module_platform_driver(prueth_driver); + +MODULE_AUTHOR("Roger Quadros "); +MODULE_AUTHOR("Md Danish Anwar "); +MODULE_DESCRIPTION("PRUSS ICSSG Ethernet Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index 42fdf4005010..b3a923e7a5c9 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -34,13 +34,42 @@ #include +#include "icssg_config.h" #include "icssg_switch_map.h" +#define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN) +#define PRUETH_MIN_PKT_SIZE (VLAN_ETH_ZLEN) +#define PRUETH_MAX_PKT_SIZE (PRUETH_MAX_MTU + ETH_HLEN + ETH_FCS_LEN) + #define ICSS_SLICE0 0 #define ICSS_SLICE1 1 +#define ICSS_FW_PRU 0 +#define ICSS_FW_RTU 1 + #define ICSSG_MAX_RFLOWS 8 /* per slice */ +/* Firmware status codes */ +#define ICSS_HS_FW_READY 0x55555555 +#define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ + +/* Firmware command codes */ +#define ICSS_HS_CMD_BUSY 0x40000000 +#define ICSS_HS_CMD_DONE 0x80000000 +#define ICSS_HS_CMD_CANCEL 0x10000000 + +/* Firmware commands */ +#define ICSS_CMD_SPAD 0x20 +#define ICSS_CMD_RXTX 0x10 +#define ICSS_CMD_ADD_FDB 0x1 +#define ICSS_CMD_DEL_FDB 0x2 +#define ICSS_CMD_SET_RUN 0x4 +#define ICSS_CMD_GET_FDB_SLOT 0x5 +#define ICSS_CMD_ENABLE_VLAN 0x5 +#define ICSS_CMD_DISABLE_VLAN 0x6 +#define ICSS_CMD_ADD_FILTER 0x7 +#define ICSS_CMD_ADD_MAC 0x8 + /* In switch mode there are 3 real ports i.e. 3 mac addrs. * however Linux sees only the host side port. The other 2 ports * are the switch ports. @@ -214,4 +243,7 @@ int icssg_queue_pop(struct prueth *prueth, u8 queue); void icssg_queue_push(struct prueth *prueth, int queue, u16 addr); u32 icssg_queue_level(struct prueth *prueth, int queue); +#define prueth_napi_to_tx_chn(pnapi) \ + container_of(pnapi, struct prueth_tx_chn, napi_tx) + #endif /* __NET_TI_ICSSG_PRUETH_H */ -- cgit From c1e10d5dc7a1be8d4eba8560540e20bd03c2be01 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:25 +0530 Subject: net: ti: icssg-prueth: Add ICSSG Stats Add icssg_stats.c to help dump, icssg related driver statistics. ICSSG has hardware registers for providing statistics like total rx bytes, total tx bytes, etc. These registers are of 32 bits and hence in case of 1G link, they overflows in around 32 seconds. The behaviour of these registers is such that they don't roll back to 0 after overflow but rather stay at UINT_MAX. These registers support a feature where the value written to them is subtracted from the register. This feature can be utilized to fix the overflowing of stats. This solution uses a Workqueues based solution where a function gets called before the registers overflow (every 25 seconds in 1G link, 25000 seconds in 100M link), this function saves the register values in local variables and writes the last read value to the register. So any update during the read will be taken care of. Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Makefile | 1 + drivers/net/ethernet/ti/icssg/icssg_prueth.c | 8 ++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 8 ++ drivers/net/ethernet/ti/icssg/icssg_stats.c | 44 ++++++++ drivers/net/ethernet/ti/icssg/icssg_stats.h | 158 +++++++++++++++++++++++++++ 5 files changed, 219 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_stats.c create mode 100644 drivers/net/ethernet/ti/icssg/icssg_stats.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index efb050cbb4a8..03d9b2b36b5f 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -36,3 +36,4 @@ icssg-prueth-y := k3-cppi-desc-pool.o \ icssg/icssg_queues.o \ icssg/icssg_config.o \ icssg/icssg_mii_cfg.o \ + icssg/icssg_stats.o \ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 1869e38f898f..d0bb4db11b30 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -1090,6 +1091,8 @@ static int emac_ndo_open(struct net_device *ndev) prueth->emacs_initialized++; + queue_work(system_long_wq, &emac->stats_work.work); + return 0; reset_tx_chan: @@ -1164,6 +1167,9 @@ static int emac_ndo_stop(struct net_device *ndev) cancel_work_sync(&emac->rx_mode_work); + /* Destroying the queued work in ndo_stop() */ + cancel_delayed_work_sync(&emac->stats_work); + /* stop PRUs */ prueth_emac_stop(emac); @@ -1313,6 +1319,8 @@ static int prueth_netdev_init(struct prueth *prueth, } INIT_WORK(&emac->rx_mode_work, emac_ndo_set_rx_mode_work); + INIT_DELAYED_WORK(&emac->stats_work, emac_stats_work_handler); + ret = pruss_request_mem_region(prueth->pruss, port == PRUETH_PORT_MII0 ? PRUSS_MEM_DRAM0 : PRUSS_MEM_DRAM1, diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index b3a923e7a5c9..f13de0d2e90b 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -49,6 +49,9 @@ #define ICSSG_MAX_RFLOWS 8 /* per slice */ +/* Number of ICSSG related stats */ +#define ICSSG_NUM_STATS 60 + /* Firmware status codes */ #define ICSS_HS_FW_READY 0x55555555 #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ @@ -153,6 +156,9 @@ struct prueth_emac { struct workqueue_struct *cmd_wq; struct pruss_mem_region dram; + + struct delayed_work stats_work; + u64 stats[ICSSG_NUM_STATS]; }; /** @@ -246,4 +252,6 @@ u32 icssg_queue_level(struct prueth *prueth, int queue); #define prueth_napi_to_tx_chn(pnapi) \ container_of(pnapi, struct prueth_tx_chn, napi_tx) +void emac_stats_work_handler(struct work_struct *work); +void emac_update_hardware_stats(struct prueth_emac *emac); #endif /* __NET_TI_ICSSG_PRUETH_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c new file mode 100644 index 000000000000..25deb368a3f0 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2021 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include "icssg_prueth.h" +#include "icssg_stats.h" +#include + +static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ + 0xb18, /* Slice 1 stats start */ +}; + +void emac_update_hardware_stats(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + u32 base = stats_base[slice]; + u32 val; + int i; + + for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { + regmap_read(prueth->miig_rt, + base + icssg_all_stats[i].offset, + &val); + regmap_write(prueth->miig_rt, + base + icssg_all_stats[i].offset, + val); + + emac->stats[i] += val; + } +} + +void emac_stats_work_handler(struct work_struct *work) +{ + struct prueth_emac *emac = container_of(work, struct prueth_emac, + stats_work.work); + emac_update_hardware_stats(emac); + + queue_delayed_work(system_long_wq, &emac->stats_work, + msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed)); +} diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h new file mode 100644 index 000000000000..999a4a91276c --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_STATS_H +#define __NET_TI_ICSSG_STATS_H + +#include "icssg_prueth.h" + +#define STATS_TIME_LIMIT_1G_MS 25000 /* 25 seconds @ 1G */ + +struct miig_stats_regs { + /* Rx */ + u32 rx_packets; + u32 rx_broadcast_frames; + u32 rx_multicast_frames; + u32 rx_crc_errors; + u32 rx_mii_error_frames; + u32 rx_odd_nibble_frames; + u32 rx_frame_max_size; + u32 rx_max_size_error_frames; + u32 rx_frame_min_size; + u32 rx_min_size_error_frames; + u32 rx_over_errors; + u32 rx_class0_hits; + u32 rx_class1_hits; + u32 rx_class2_hits; + u32 rx_class3_hits; + u32 rx_class4_hits; + u32 rx_class5_hits; + u32 rx_class6_hits; + u32 rx_class7_hits; + u32 rx_class8_hits; + u32 rx_class9_hits; + u32 rx_class10_hits; + u32 rx_class11_hits; + u32 rx_class12_hits; + u32 rx_class13_hits; + u32 rx_class14_hits; + u32 rx_class15_hits; + u32 rx_smd_frags; + u32 rx_bucket1_size; + u32 rx_bucket2_size; + u32 rx_bucket3_size; + u32 rx_bucket4_size; + u32 rx_64B_frames; + u32 rx_bucket1_frames; + u32 rx_bucket2_frames; + u32 rx_bucket3_frames; + u32 rx_bucket4_frames; + u32 rx_bucket5_frames; + u32 rx_bytes; + u32 rx_tx_total_bytes; + /* Tx */ + u32 tx_packets; + u32 tx_broadcast_frames; + u32 tx_multicast_frames; + u32 tx_odd_nibble_frames; + u32 tx_underflow_errors; + u32 tx_frame_max_size; + u32 tx_max_size_error_frames; + u32 tx_frame_min_size; + u32 tx_min_size_error_frames; + u32 tx_bucket1_size; + u32 tx_bucket2_size; + u32 tx_bucket3_size; + u32 tx_bucket4_size; + u32 tx_64B_frames; + u32 tx_bucket1_frames; + u32 tx_bucket2_frames; + u32 tx_bucket3_frames; + u32 tx_bucket4_frames; + u32 tx_bucket5_frames; + u32 tx_bytes; +}; + +#define ICSSG_STATS(field, stats_type) \ +{ \ + #field, \ + offsetof(struct miig_stats_regs, field), \ + stats_type \ +} + +struct icssg_stats { + char name[ETH_GSTRING_LEN]; + u32 offset; + bool standard_stats; +}; + +static const struct icssg_stats icssg_all_stats[] = { + /* Rx */ + ICSSG_STATS(rx_packets, true), + ICSSG_STATS(rx_broadcast_frames, false), + ICSSG_STATS(rx_multicast_frames, true), + ICSSG_STATS(rx_crc_errors, true), + ICSSG_STATS(rx_mii_error_frames, false), + ICSSG_STATS(rx_odd_nibble_frames, false), + ICSSG_STATS(rx_frame_max_size, true), + ICSSG_STATS(rx_max_size_error_frames, false), + ICSSG_STATS(rx_frame_min_size, true), + ICSSG_STATS(rx_min_size_error_frames, false), + ICSSG_STATS(rx_over_errors, true), + ICSSG_STATS(rx_class0_hits, false), + ICSSG_STATS(rx_class1_hits, false), + ICSSG_STATS(rx_class2_hits, false), + ICSSG_STATS(rx_class3_hits, false), + ICSSG_STATS(rx_class4_hits, false), + ICSSG_STATS(rx_class5_hits, false), + ICSSG_STATS(rx_class6_hits, false), + ICSSG_STATS(rx_class7_hits, false), + ICSSG_STATS(rx_class8_hits, false), + ICSSG_STATS(rx_class9_hits, false), + ICSSG_STATS(rx_class10_hits, false), + ICSSG_STATS(rx_class11_hits, false), + ICSSG_STATS(rx_class12_hits, false), + ICSSG_STATS(rx_class13_hits, false), + ICSSG_STATS(rx_class14_hits, false), + ICSSG_STATS(rx_class15_hits, false), + ICSSG_STATS(rx_smd_frags, false), + ICSSG_STATS(rx_bucket1_size, true), + ICSSG_STATS(rx_bucket2_size, true), + ICSSG_STATS(rx_bucket3_size, true), + ICSSG_STATS(rx_bucket4_size, true), + ICSSG_STATS(rx_64B_frames, true), + ICSSG_STATS(rx_bucket1_frames, true), + ICSSG_STATS(rx_bucket2_frames, true), + ICSSG_STATS(rx_bucket3_frames, true), + ICSSG_STATS(rx_bucket4_frames, true), + ICSSG_STATS(rx_bucket5_frames, true), + ICSSG_STATS(rx_bytes, true), + ICSSG_STATS(rx_tx_total_bytes, false), + /* Tx */ + ICSSG_STATS(tx_packets, true), + ICSSG_STATS(tx_broadcast_frames, false), + ICSSG_STATS(tx_multicast_frames, false), + ICSSG_STATS(tx_odd_nibble_frames, false), + ICSSG_STATS(tx_underflow_errors, false), + ICSSG_STATS(tx_frame_max_size, true), + ICSSG_STATS(tx_max_size_error_frames, false), + ICSSG_STATS(tx_frame_min_size, true), + ICSSG_STATS(tx_min_size_error_frames, false), + ICSSG_STATS(tx_bucket1_size, true), + ICSSG_STATS(tx_bucket2_size, true), + ICSSG_STATS(tx_bucket3_size, true), + ICSSG_STATS(tx_bucket4_size, true), + ICSSG_STATS(tx_64B_frames, true), + ICSSG_STATS(tx_bucket1_frames, true), + ICSSG_STATS(tx_bucket2_frames, true), + ICSSG_STATS(tx_bucket3_frames, true), + ICSSG_STATS(tx_bucket4_frames, true), + ICSSG_STATS(tx_bucket5_frames, true), + ICSSG_STATS(tx_bytes, true), +}; + +#endif /* __NET_TI_ICSSG_STATS_H */ -- cgit From c2f67d192351d33ec884af6bbbbfe77c57f7c397 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:26 +0530 Subject: net: ti: icssg-prueth: Add Standard network staticstics Implement .ndo_get_stats64 to dump standard network interface statistics for ICSSG ethernet driver. Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 22 ++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 2 ++ drivers/net/ethernet/ti/icssg/icssg_stats.c | 13 +++++++++++++ 3 files changed, 37 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index d0bb4db11b30..e641b6ce9415 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -1240,6 +1240,27 @@ static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) return phy_do_ioctl(ndev, ifr, cmd); } +static void emac_ndo_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + emac_update_hardware_stats(emac); + + stats->rx_packets = emac_get_stat_by_name(emac, "rx_packets"); + stats->rx_bytes = emac_get_stat_by_name(emac, "rx_bytes"); + stats->tx_packets = emac_get_stat_by_name(emac, "tx_packets"); + stats->tx_bytes = emac_get_stat_by_name(emac, "tx_bytes"); + stats->rx_crc_errors = emac_get_stat_by_name(emac, "rx_crc_errors"); + stats->rx_over_errors = emac_get_stat_by_name(emac, "rx_over_errors"); + stats->multicast = emac_get_stat_by_name(emac, "rx_multicast_frames"); + + stats->rx_errors = ndev->stats.rx_errors; + stats->rx_dropped = ndev->stats.rx_dropped; + stats->tx_errors = ndev->stats.tx_errors; + stats->tx_dropped = ndev->stats.tx_dropped; +} + static const struct net_device_ops emac_netdev_ops = { .ndo_open = emac_ndo_open, .ndo_stop = emac_ndo_stop, @@ -1249,6 +1270,7 @@ static const struct net_device_ops emac_netdev_ops = { .ndo_tx_timeout = emac_ndo_tx_timeout, .ndo_set_rx_mode = emac_ndo_set_rx_mode, .ndo_eth_ioctl = emac_ndo_ioctl, + .ndo_get_stats64 = emac_ndo_get_stats64, }; /* get emac_port corresponding to eth_node name */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index f13de0d2e90b..e58cd8db7ba0 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -51,6 +51,7 @@ /* Number of ICSSG related stats */ #define ICSSG_NUM_STATS 60 +#define ICSSG_NUM_STANDARD_STATS 31 /* Firmware status codes */ #define ICSS_HS_FW_READY 0x55555555 @@ -254,4 +255,5 @@ u32 icssg_queue_level(struct prueth *prueth, int queue); void emac_stats_work_handler(struct work_struct *work); void emac_update_hardware_stats(struct prueth_emac *emac); +int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name); #endif /* __NET_TI_ICSSG_PRUETH_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c index 25deb368a3f0..bb0b33927e3b 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_stats.c +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c @@ -42,3 +42,16 @@ void emac_stats_work_handler(struct work_struct *work) queue_delayed_work(system_long_wq, &emac->stats_work, msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed)); } + +int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { + if (!strcmp(icssg_all_stats[i].name, stat_name)) + return emac->stats[icssg_all_stats[i].offset / sizeof(u32)]; + } + + netdev_err(emac->ndev, "Invalid stats %s\n", stat_name); + return -EINVAL; +} -- cgit From 8fb86b0dcaed2d6bbc33203e7340bff3e68fe339 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:27 +0530 Subject: net: ti: icssg-prueth: Add ethtool ops for ICSSG Ethernet driver Add icssg_ethtool.c file. This file will be used for dumping statistics via ethtool for ICSSG ethernet driver. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Makefile | 1 + drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 188 ++++++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.c | 1 + drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 + 4 files changed, 193 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icssg_ethtool.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 03d9b2b36b5f..9176d79c36e1 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -37,3 +37,4 @@ icssg-prueth-y := k3-cppi-desc-pool.o \ icssg/icssg_config.o \ icssg/icssg_mii_cfg.o \ icssg/icssg_stats.o \ + icssg/icssg_ethtool.o diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c new file mode 100644 index 000000000000..02c312f01d10 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include "icssg_prueth.h" +#include "icssg_stats.h" + +static void emac_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct prueth *prueth = emac->prueth; + + strscpy(info->driver, dev_driver_string(prueth->dev), + sizeof(info->driver)); + strscpy(info->bus_info, dev_name(prueth->dev), sizeof(info->bus_info)); +} + +static u32 emac_get_msglevel(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + return emac->msg_enable; +} + +static void emac_set_msglevel(struct net_device *ndev, u32 value) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + emac->msg_enable = value; +} + +static int emac_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *ecmd) +{ + return phy_ethtool_get_link_ksettings(ndev, ecmd); +} + +static int emac_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *ecmd) +{ + return phy_ethtool_set_link_ksettings(ndev, ecmd); +} + +static int emac_get_eee(struct net_device *ndev, struct ethtool_eee *edata) +{ + if (!ndev->phydev) + return -EOPNOTSUPP; + + return phy_ethtool_get_eee(ndev->phydev, edata); +} + +static int emac_set_eee(struct net_device *ndev, struct ethtool_eee *edata) +{ + if (!ndev->phydev) + return -EOPNOTSUPP; + + return phy_ethtool_set_eee(ndev->phydev, edata); +} + +static int emac_nway_reset(struct net_device *ndev) +{ + return phy_ethtool_nway_reset(ndev); +} + +static int emac_get_sset_count(struct net_device *ndev, int stringset) +{ + switch (stringset) { + case ETH_SS_STATS: + return ICSSG_NUM_ETHTOOL_STATS; + default: + return -EOPNOTSUPP; + } +} + +static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data) +{ + u8 *p = data; + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { + if (!icssg_all_stats[i].standard_stats) { + memcpy(p, icssg_all_stats[i].name, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + } + break; + default: + break; + } +} + +static void emac_get_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) +{ + struct prueth_emac *emac = netdev_priv(ndev); + int i; + + emac_update_hardware_stats(emac); + + for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) + if (!icssg_all_stats[i].standard_stats) + *(data++) = emac->stats[i]; +} + +static int emac_set_channels(struct net_device *ndev, + struct ethtool_channels *ch) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + /* Check if interface is up. Can change the num queues when + * the interface is down. + */ + if (netif_running(emac->ndev)) + return -EBUSY; + + emac->tx_ch_num = ch->tx_count; + + return 0; +} + +static void emac_get_channels(struct net_device *ndev, + struct ethtool_channels *ch) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + ch->max_rx = 1; + ch->max_tx = PRUETH_MAX_TX_QUEUES; + ch->rx_count = 1; + ch->tx_count = emac->tx_ch_num; +} + +static const struct ethtool_rmon_hist_range emac_rmon_ranges[] = { + { 0, 64}, + { 65, 128}, + { 129, 256}, + { 257, 512}, + { 513, PRUETH_MAX_PKT_SIZE}, + {} +}; + +static void emac_get_rmon_stats(struct net_device *ndev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + *ranges = emac_rmon_ranges; + + rmon_stats->undersize_pkts = emac_get_stat_by_name(emac, "rx_bucket1_frames") - + emac_get_stat_by_name(emac, "rx_64B_frames"); + + rmon_stats->hist[0] = emac_get_stat_by_name(emac, "rx_bucket1_frames"); + rmon_stats->hist[1] = emac_get_stat_by_name(emac, "rx_bucket2_frames"); + rmon_stats->hist[2] = emac_get_stat_by_name(emac, "rx_bucket3_frames"); + rmon_stats->hist[3] = emac_get_stat_by_name(emac, "rx_bucket4_frames"); + rmon_stats->hist[4] = emac_get_stat_by_name(emac, "rx_bucket5_frames"); + + rmon_stats->hist_tx[0] = emac_get_stat_by_name(emac, "tx_bucket1_frames"); + rmon_stats->hist_tx[1] = emac_get_stat_by_name(emac, "tx_bucket2_frames"); + rmon_stats->hist_tx[2] = emac_get_stat_by_name(emac, "tx_bucket3_frames"); + rmon_stats->hist_tx[3] = emac_get_stat_by_name(emac, "tx_bucket4_frames"); + rmon_stats->hist_tx[4] = emac_get_stat_by_name(emac, "tx_bucket5_frames"); +} + +const struct ethtool_ops icssg_ethtool_ops = { + .get_drvinfo = emac_get_drvinfo, + .get_msglevel = emac_get_msglevel, + .set_msglevel = emac_set_msglevel, + .get_sset_count = emac_get_sset_count, + .get_ethtool_stats = emac_get_ethtool_stats, + .get_strings = emac_get_strings, + .get_channels = emac_get_channels, + .set_channels = emac_set_channels, + .get_link_ksettings = emac_get_link_ksettings, + .set_link_ksettings = emac_set_link_ksettings, + .get_link = ethtool_op_get_link, + .get_eee = emac_get_eee, + .set_eee = emac_set_eee, + .nway_reset = emac_nway_reset, + .get_rmon_stats = emac_get_rmon_stats, +}; diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index e641b6ce9415..80721d82f6c5 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -1421,6 +1421,7 @@ static int prueth_netdev_init(struct prueth *prueth, ndev->min_mtu = PRUETH_MIN_PKT_SIZE; ndev->max_mtu = PRUETH_MAX_MTU; ndev->netdev_ops = &emac_netdev_ops; + ndev->ethtool_ops = &icssg_ethtool_ops; ndev->hw_features = NETIF_F_SG; ndev->features = ndev->hw_features; diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index e58cd8db7ba0..a8ce4d01ef16 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -52,6 +52,7 @@ /* Number of ICSSG related stats */ #define ICSSG_NUM_STATS 60 #define ICSSG_NUM_STANDARD_STATS 31 +#define ICSSG_NUM_ETHTOOL_STATS (ICSSG_NUM_STATS - ICSSG_NUM_STANDARD_STATS) /* Firmware status codes */ #define ICSS_HS_FW_READY 0x55555555 @@ -230,6 +231,8 @@ static inline int prueth_emac_slice(struct prueth_emac *emac) } } +extern const struct ethtool_ops icssg_ethtool_ops; + /* Classifier helpers */ void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac); -- cgit From a46750a13bb09e2e185bc66c44d9a002dab2d3d5 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 1 Aug 2023 14:44:28 +0530 Subject: net: ti: icssg-prueth: Add Power management support Add suspend / resume APIs to support power management in ICSSG ethernet driver. Reviewed-by: Andrew Lunn Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 57 ++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 80721d82f6c5..47b941fb0198 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -1813,6 +1813,62 @@ static void prueth_remove(struct platform_device *pdev) prueth_put_cores(prueth, ICSS_SLICE0); } +#ifdef CONFIG_PM_SLEEP +static int prueth_suspend(struct device *dev) +{ + struct prueth *prueth = dev_get_drvdata(dev); + struct net_device *ndev; + int i, ret; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + ndev = prueth->registered_netdevs[i]; + + if (!ndev) + continue; + + if (netif_running(ndev)) { + netif_device_detach(ndev); + ret = emac_ndo_stop(ndev); + if (ret < 0) { + netdev_err(ndev, "failed to stop: %d", ret); + return ret; + } + } + } + + return 0; +} + +static int prueth_resume(struct device *dev) +{ + struct prueth *prueth = dev_get_drvdata(dev); + struct net_device *ndev; + int i, ret; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + ndev = prueth->registered_netdevs[i]; + + if (!ndev) + continue; + + if (netif_running(ndev)) { + ret = emac_ndo_open(ndev); + if (ret < 0) { + netdev_err(ndev, "failed to start: %d", ret); + return ret; + } + netif_device_attach(ndev); + } + } + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops prueth_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(prueth_suspend, prueth_resume) +}; + static const struct prueth_pdata am654_icssg_pdata = { .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE, .quirk_10m_link_issue = 1, @@ -1830,6 +1886,7 @@ static struct platform_driver prueth_driver = { .driver = { .name = "icssg-prueth", .of_match_table = prueth_dt_match, + .pm = &prueth_dev_pm_ops, }, }; module_platform_driver(prueth_driver); -- cgit From d6b484b5cb2a7d509b36a220911509ddd8b777c4 Mon Sep 17 00:00:00 2001 From: Azeem Shaikh Date: Mon, 3 Jul 2023 18:12:56 +0000 Subject: wifi: mt76: Replace strlcpy() with strscpy() strlcpy() reads the entire source buffer first. This read may exceed the destination size limit. This is both inefficient and can lead to linear read overflows if a source string is not NUL-terminated [1]. In an effort to remove strlcpy() completely [2], replace strlcpy() here with strscpy(). Direct replacement is safe here since DEV_ASSIGN is only used by TRACE macros and the return values are ignored. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy [2] https://github.com/KSPP/linux/issues/89 Signed-off-by: Azeem Shaikh Reviewed-by: Kees Cook Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230703181256.3712079-1-azeemshaikh38@gmail.com --- drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_trace.h | 2 +- drivers/net/wireless/mediatek/mt76/trace.h | 2 +- drivers/net/wireless/mediatek/mt76/usb_trace.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h index d3eb49d83b98..9be5a58a4e6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index 6a98092e996b..11d119cd0f6f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/trace.h b/drivers/net/wireless/mediatek/mt76/trace.h index c3d0ef8e2890..109a07f9733a 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.h +++ b/drivers/net/wireless/mediatek/mt76/trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEVICE_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEVICE_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/usb_trace.h b/drivers/net/wireless/mediatek/mt76/usb_trace.h index f5ab3215af80..7b261ddb2ac6 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_trace.h +++ b/drivers/net/wireless/mediatek/mt76/usb_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s " #define DEV_PR_ARG __entry->wiphy_name -- cgit From a9477c12ae54aec11f22ee473938d91f4b1c8536 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 19:23:45 +0300 Subject: wifi: brcmsmac: remove more unused data types Remove unused 'struct brcmu_iovar' and 'struct tx_inst_power'. This follows commit b2090d93d4b6 ("wifi: brcmsmac: remove unused data type"). Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725162400.192357-1-dmantipov@yandex.ru --- drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h | 5 ----- drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h | 9 --------- 2 files changed, 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h index 2e6a3d454ee8..1efc92fd1671 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h @@ -141,11 +141,6 @@ struct tx_power { u8 target[WL_TX_POWER_RATES]; }; -struct tx_inst_power { - u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ - u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ -}; - struct brcms_chanvec { u8 vec[MAXCHANNEL / NBBY]; }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h index 2b0df07ced74..12a0df5b4e98 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h @@ -288,15 +288,6 @@ struct tx_status; struct d11rxhdr; struct txpwr_limits; -/* iovar structure */ -struct brcmu_iovar { - const char *name; /* name for lookup and display */ - u16 varid; /* id for switch */ - u16 flags; /* driver-specific flag bits */ - u16 type; /* base type of argument */ - u16 minlen; /* min length for buffer vars */ -}; - /* brcm_msg_level is a bit vector with defs in defs.h */ extern u32 brcm_msg_level; -- cgit From 0701519fda6fe8390e48a910da4ffb0f178ca332 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 25 Jul 2023 19:23:46 +0300 Subject: wifi: brcmsmac: cleanup SCB-related data types Drop unused and set-but-unused fields of 'struct scb_ampdu_tid_ini', 'struct scb_ampdu' and 'struct scb', as well as now unused argument of 'brcms_c_ampdu_tx_operational()', adjust related code. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725162400.192357-2-dmantipov@yandex.ru --- drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c | 6 ------ .../net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c | 8 +++----- drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c | 2 -- drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h | 2 +- drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h | 14 -------------- 5 files changed, 4 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c index e24228e60027..e859075db716 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c @@ -476,11 +476,9 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, - u8 ba_wsize, /* negotiated ba window size (in pdu) */ uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ { struct scb_ampdu *scb_ampdu; - struct scb_ampdu_tid_ini *ini; struct ampdu_info *ampdu = wlc->ampdu; struct scb *scb = &wlc->pri_scb; scb_ampdu = &scb->scb_ampdu; @@ -491,10 +489,6 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, return; } - ini = &scb_ampdu->ini[tid]; - ini->tid = tid; - ini->scb = scb_ampdu->scb; - ini->ba_wsize = ba_wsize; scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 0bd4e679a359..543e93ec49d2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -810,7 +810,6 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, brcms_c_init_scb(scb); wl->pub->global_ampdu = &(scb->scb_ampdu); - wl->pub->global_ampdu->scb = scb; wl->pub->global_ampdu->max_pdu = 16; /* @@ -831,7 +830,6 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; - u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; @@ -863,11 +861,11 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, /* * BA window size from ADDBA response ('buf_size') defines how * many outstanding MPDUs are allowed for the BA stream by - * recipient and traffic class. 'ampdu_factor' gives maximum - * AMPDU size. + * recipient and traffic class (this is actually unused by the + * rest of the driver). 'ampdu_factor' gives maximum AMPDU size. */ spin_lock_bh(&wl->lock); - brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, + brcms_c_ampdu_tx_operational(wl->wlc, tid, (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->deflink.ht_cap.ampdu_factor)) - 1); spin_unlock_bh(&wl->lock); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 11b33e78127c..b3663c5ef382 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -3147,10 +3147,8 @@ void brcms_c_init_scb(struct scb *scb) scb->flags = SCB_WMECAP | SCB_HTCAP; for (i = 0; i < NUMPRIO; i++) { scb->seqnum[i] = 0; - scb->seqctl[i] = 0xFFFF; } - scb->seqctl_nonqos = 0xFFFF; scb->magic = SCB_MAGIC; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h index 4da38cb4f318..bfc63b2f0537 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h @@ -297,7 +297,7 @@ struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, u16 tid); void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, - u8 ba_wsize, uint max_rx_ampdu_bytes); + uint max_rx_ampdu_bytes); int brcms_c_module_register(struct brcms_pub *pub, const char *name, struct brcms_info *hdl, int (*down_fn)(void *handle)); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h index 3a3d73699f83..d65561227da0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h @@ -36,19 +36,13 @@ /* structure to store per-tid state for the ampdu initiator */ struct scb_ampdu_tid_ini { - u8 tid; /* initiator tid for easy lookup */ /* tx retry count; indexed by seq modulo */ u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; - struct scb *scb; /* backptr for easy lookup */ - u8 ba_wsize; /* negotiated ba window size (in pdu) */ }; struct scb_ampdu { - struct scb *scb; /* back pointer for easy reference */ - u8 mpdu_density; /* mpdu density */ u8 max_pdu; /* max pdus allowed in ampdu */ u8 release; /* # of mpdus released at a time */ - u16 min_len; /* min mpdu len to support the density */ u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ /* @@ -64,15 +58,7 @@ struct scb_ampdu { struct scb { u32 magic; u32 flags; /* various bit flags as defined below */ - u32 flags2; /* various bit flags2 as defined below */ - u8 state; /* current state bitfield of auth/assoc process */ - u8 ea[ETH_ALEN]; /* station address */ - uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ - u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ - /* seqctl of last received frame (for dups) for non-QoS data and - * management */ - u16 seqctl_nonqos; u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ -- cgit From 288c63d5cb4667a51a04668b3e2bb0ea499bc5f4 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 31 Jul 2023 10:43:07 +0300 Subject: wifi: mwifiex: fix error recovery in PCIE buffer descriptor management Add missing 'kfree_skb()' in 'mwifiex_init_rxq_ring()' and never do 'kfree(card->rxbd_ring_vbase)' because this area is DMAed and should be released with 'dma_free_coherent()'. The latter is performed in 'mwifiex_pcie_delete_rxbd_ring()', which is now called to recover from possible errors in 'mwifiex_pcie_create_rxbd_ring()'. Likewise for 'mwifiex_pcie_init_evt_ring()', 'kfree(card->evtbd_ring_vbase)' 'mwifiex_pcie_delete_evtbd_ring()' and 'mwifiex_pcie_create_rxbd_ring()'. Fixes: d930faee141b ("mwifiex: add support for Marvell pcie8766 chipset") Signed-off-by: Dmitry Antipov Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230731074334.56463-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/pcie.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 9a698a16a8f3..6697132ecc97 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -189,6 +189,8 @@ static int mwifiex_pcie_probe_of(struct device *dev) } static void mwifiex_pcie_work(struct work_struct *work); +static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter); +static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter); static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, @@ -792,14 +794,15 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) if (!skb) { mwifiex_dbg(adapter, ERROR, "Unable to allocate skb for RX ring.\n"); - kfree(card->rxbd_ring_vbase); return -ENOMEM; } if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_RX_DATA_BUF_SIZE, - DMA_FROM_DEVICE)) - return -1; + DMA_FROM_DEVICE)) { + kfree_skb(skb); + return -ENOMEM; + } buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); @@ -849,7 +852,6 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) if (!skb) { mwifiex_dbg(adapter, ERROR, "Unable to allocate skb for EVENT buf.\n"); - kfree(card->evtbd_ring_vbase); return -ENOMEM; } skb_put(skb, MAX_EVENT_SIZE); @@ -857,8 +859,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, DMA_FROM_DEVICE)) { kfree_skb(skb); - kfree(card->evtbd_ring_vbase); - return -1; + return -ENOMEM; } buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); @@ -1058,6 +1059,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) */ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) { + int ret; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -1096,7 +1098,10 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->rxbd_ring_pbase >> 32), card->rxbd_ring_size); - return mwifiex_init_rxq_ring(adapter); + ret = mwifiex_init_rxq_ring(adapter); + if (ret) + mwifiex_pcie_delete_rxbd_ring(adapter); + return ret; } /* @@ -1127,6 +1132,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) */ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) { + int ret; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -1161,7 +1167,10 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->evtbd_ring_pbase >> 32), card->evtbd_ring_size); - return mwifiex_pcie_init_evt_ring(adapter); + ret = mwifiex_pcie_init_evt_ring(adapter); + if (ret) + mwifiex_pcie_delete_evtbd_ring(adapter); + return ret; } /* -- cgit From 34093c9fa05df24558d1e2c5d32f7f93b2c97ee9 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Tue, 1 Aug 2023 08:50:41 +0800 Subject: net: Remove duplicated include in mac.c ./drivers/net/ethernet/freescale/fman/mac.c: linux/of_platform.h is included more than once. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=6039 Signed-off-by: Yang Li Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fman/mac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index b6c7c4c0b367..9767586b4eb3 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include -- cgit From 72c8caf904aed2caed5d6e75233294b6159ddb5d Mon Sep 17 00:00:00 2001 From: Aditya Kumar Singh Date: Wed, 26 Jul 2023 10:16:24 +0530 Subject: wifi: ath11k: fix band selection for ppdu received in channel 177 of 5 GHz 5 GHz band channel 177 support was added with the commit e5e94d10c856 ("wifi: ath11k: add channel 177 into 5 GHz channel list"). However, during processing for the received ppdu in ath11k_dp_rx_h_ppdu(), channel number is checked only till 173. This leads to driver code checking for channel and then fetching the band from it which is extra effort since firmware has already given the channel number in the metadata. Fix this issue by checking the channel number till 177 since we support it now. Found via code review. Compile tested only. Fixes: e5e94d10c856 ("wifi: ath11k: add channel 177 into 5 GHz channel list") Signed-off-by: Aditya Kumar Singh Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726044624.20507-1-quic_adisi@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 5c76664ba0dd..1e488eed282b 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2408,7 +2408,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, rx_status->freq = center_freq; } else if (channel_num >= 1 && channel_num <= 14) { rx_status->band = NL80211_BAND_2GHZ; - } else if (channel_num >= 36 && channel_num <= 173) { + } else if (channel_num >= 36 && channel_num <= 177) { rx_status->band = NL80211_BAND_5GHZ; } else { spin_lock_bh(&ar->data_lock); -- cgit From 6f092c98dcfa1e4cf37d45f9b8e4d4a3cbeb79d4 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 26 Jul 2023 12:21:02 +0300 Subject: wifi: ath11k: simplify ath11k_mac_validate_vht_he_fixed_rate_settings() In ath11k_mac_validate_vht_he_fixed_rate_settings() ar->ab->peers list is not altered so list_for_each_entry() should be safe. Compile tested only. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726092113.78794-1-dmantipov@yandex.ru --- drivers/net/wireless/ath/ath11k/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 8c77ade49437..2aadf2c387b6 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -8255,7 +8255,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b const struct cfg80211_bitrate_mask *mask) { bool he_fixed_rate = false, vht_fixed_rate = false; - struct ath11k_peer *peer, *tmp; + struct ath11k_peer *peer; const u16 *vht_mcs_mask, *he_mcs_mask; struct ieee80211_link_sta *deflink; u8 vht_nss, he_nss; @@ -8278,7 +8278,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b rcu_read_lock(); spin_lock_bh(&ar->ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { + list_for_each_entry(peer, &ar->ab->peers, list) { if (peer->sta) { deflink = &peer->sta->deflink; -- cgit From 011e5a3052a22d3758d17442bf0c04c68bf79bea Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Wed, 26 Jul 2023 19:40:30 +0530 Subject: wifi: ath11k: Split coldboot calibration hw_param QCN9074 enables coldboot calibration only in Factory Test Mode (FTM). Hence, split cold_boot_calib to two hw_params for mission and FTM mode. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Seevalamuthu Mariappan Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726141032.3061-2-quic_rajkbhag@quicinc.com --- drivers/net/wireless/ath/ath11k/ahb.c | 3 +-- drivers/net/wireless/ath/ath11k/core.c | 36 ++++++++++++++++++++++++++-------- drivers/net/wireless/ath/ath11k/core.h | 1 + drivers/net/wireless/ath/ath11k/hw.h | 3 ++- drivers/net/wireless/ath/ath11k/qmi.c | 6 +++--- 5 files changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 1cebba7889d7..56aea2bc9787 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -423,8 +423,7 @@ static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab) { int timeout; - if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done || - ab->hw_params.cold_boot_calib == 0 || + if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || ab->hw_params.cbcal_restart_fw == 0) return 0; diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index bebfd342e28b..d5bf2896d8c5 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -86,7 +86,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = false, .idle_ps = false, .supports_sta_ps = false, - .cold_boot_calib = true, + .coldboot_cal_mm = true, + .coldboot_cal_ftm = true, .cbcal_restart_fw = true, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -167,7 +168,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = false, .idle_ps = false, .supports_sta_ps = false, - .cold_boot_calib = true, + .coldboot_cal_mm = true, + .coldboot_cal_ftm = true, .cbcal_restart_fw = true, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -248,7 +250,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = true, .idle_ps = true, .supports_sta_ps = true, - .cold_boot_calib = false, + .coldboot_cal_mm = false, + .coldboot_cal_ftm = false, .cbcal_restart_fw = false, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -332,7 +335,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = false, .idle_ps = false, .supports_sta_ps = false, - .cold_boot_calib = false, + .coldboot_cal_mm = false, + .coldboot_cal_ftm = false, .cbcal_restart_fw = false, .fw_mem_mode = 2, .num_vdevs = 8, @@ -413,7 +417,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = true, .idle_ps = true, .supports_sta_ps = true, - .cold_boot_calib = false, + .coldboot_cal_mm = false, + .coldboot_cal_ftm = false, .cbcal_restart_fw = false, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -495,7 +500,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = true, .idle_ps = true, .supports_sta_ps = true, - .cold_boot_calib = false, + .coldboot_cal_mm = false, + .coldboot_cal_ftm = false, .cbcal_restart_fw = false, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -578,7 +584,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_shadow_regs = true, .idle_ps = true, .supports_sta_ps = true, - .cold_boot_calib = true, + .coldboot_cal_mm = true, + .coldboot_cal_ftm = true, .cbcal_restart_fw = false, .fw_mem_mode = 0, .num_vdevs = 16 + 1, @@ -667,7 +674,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .supports_suspend = false, .hal_params = &ath11k_hw_hal_params_ipq8074, .single_pdev_only = false, - .cold_boot_calib = true, + .coldboot_cal_mm = true, + .coldboot_cal_ftm = true, .cbcal_restart_fw = true, .fix_l1ss = true, .supports_dynamic_smps_6ghz = false, @@ -749,6 +757,18 @@ void ath11k_fw_stats_free(struct ath11k_fw_stats *stats) ath11k_fw_stats_bcn_free(&stats->bcn); } +bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab) +{ + if (!ath11k_cold_boot_cal) + return false; + + if (ath11k_ftm_mode) + return ab->hw_params.coldboot_cal_ftm; + + else + return ab->hw_params.coldboot_cal_mm; +} + int ath11k_core_suspend(struct ath11k_base *ab) { int ret; diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 9d15b4390b9c..b04447762483 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -1186,6 +1186,7 @@ void ath11k_core_halt(struct ath11k *ar); int ath11k_core_resume(struct ath11k_base *ab); int ath11k_core_suspend(struct ath11k_base *ab); void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); +bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab); const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, const char *filename); diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index f5533630a7f9..d51a99669dd6 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -187,7 +187,8 @@ struct ath11k_hw_params { bool supports_shadow_regs; bool idle_ps; bool supports_sta_ps; - bool cold_boot_calib; + bool coldboot_cal_mm; + bool coldboot_cal_ftm; bool cbcal_restart_fw; int fw_mem_mode; u32 num_vdevs; diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index d4eaf7d2ba84..91a214caa8b5 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -2079,7 +2079,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) return -EINVAL; } - if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) { + if (ath11k_core_coldboot_cal_support(ab)) { if (hremote_node) { ab->qmi.target_mem[idx].paddr = res.start + host_ddr_sz; @@ -3209,8 +3209,8 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) break; } - if (ath11k_cold_boot_cal && ab->qmi.cal_done == 0 && - ab->hw_params.cold_boot_calib) { + if (ab->qmi.cal_done == 0 && + ath11k_core_coldboot_cal_support(ab)) { ath11k_qmi_process_coldboot_calibration(ab); } else { clear_bit(ATH11K_FLAG_CRASH_FLUSH, -- cgit From bdfc967bf5fcd762473a01d39edb81f1165ba290 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Wed, 26 Jul 2023 19:40:31 +0530 Subject: wifi: ath11k: Add coldboot calibration support for QCN9074 QCN9074 supports 6 GHz, which has increased number of channels compared to 5 GHz/2 GHz. So, to support coldboot calibration in QCN9074 ATH11K_COLD_BOOT_FW_RESET_DELAY extended to 60 seconds. To avoid code redundancy, fwreset_from_cold_boot moved to QMI and made common for both ahb and pci. Coldboot calibration is enabled only in FTM mode for QCN9074. QCN9074 requires firmware restart after coldboot, hence enable cbcal_restart_fw in hw_params. This support can be enabled/disabled using hw params for different hardware. Currently it is not enabled for QCA6390. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Anilkumar Kolli Signed-off-by: Seevalamuthu Mariappan Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726141032.3061-3-quic_rajkbhag@quicinc.com --- drivers/net/wireless/ath/ath11k/ahb.c | 28 ++-------------------------- drivers/net/wireless/ath/ath11k/core.c | 4 ++-- drivers/net/wireless/ath/ath11k/pci.c | 2 ++ drivers/net/wireless/ath/ath11k/qmi.c | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/qmi.h | 3 ++- 5 files changed, 36 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 56aea2bc9787..b0a40970bada 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -14,6 +14,7 @@ #include "ahb.h" #include "debug.h" #include "hif.h" +#include "qmi.h" #include #include "pcic.h" #include @@ -419,31 +420,6 @@ static void ath11k_ahb_power_down(struct ath11k_base *ab) rproc_shutdown(ab_ahb->tgt_rproc); } -static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab) -{ - int timeout; - - if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || - ab->hw_params.cbcal_restart_fw == 0) - return 0; - - ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n"); - timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, - (ab->qmi.cal_done == 1), - ATH11K_COLD_BOOT_FW_RESET_DELAY); - if (timeout <= 0) { - ath11k_cold_boot_cal = 0; - ath11k_warn(ab, "Coldboot Calibration failed timed out\n"); - } - - /* reset the firmware */ - ath11k_ahb_power_down(ab); - ath11k_ahb_power_up(ab); - - ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n"); - return 0; -} - static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) { struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; @@ -1226,7 +1202,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) goto err_ce_free; } - ath11k_ahb_fwreset_from_cold_boot(ab); + ath11k_qmi_fwreset_from_cold_boot(ab); return 0; diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index d5bf2896d8c5..fc7c4564a715 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -336,8 +336,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .idle_ps = false, .supports_sta_ps = false, .coldboot_cal_mm = false, - .coldboot_cal_ftm = false, - .cbcal_restart_fw = false, + .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, .fw_mem_mode = 2, .num_vdevs = 8, .num_peers = 128, diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 79e2cbe82638..5fd08ffc2a9f 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -15,6 +15,7 @@ #include "mhi.h" #include "debug.h" #include "pcic.h" +#include "qmi.h" #define ATH11K_PCI_BAR_NUM 0 #define ATH11K_PCI_DMA_MASK 32 @@ -897,6 +898,7 @@ unsupported_wcn6855_soc: ath11k_err(ab, "failed to init core: %d\n", ret); goto err_irq_affinity_cleanup; } + ath11k_qmi_fwreset_from_cold_boot(ab); return 0; err_irq_affinity_cleanup: diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 91a214caa8b5..c4eab5d7f5c5 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -9,6 +9,7 @@ #include "qmi.h" #include "core.h" #include "debug.h" +#include "hif.h" #include #include #include @@ -2839,6 +2840,33 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab, return 0; } +int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab) +{ + int timeout; + + if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || + ab->hw_params.cbcal_restart_fw == 0) + return 0; + + ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n"); + + timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, + (ab->qmi.cal_done == 1), + ATH11K_COLD_BOOT_FW_RESET_DELAY); + + if (timeout <= 0) { + ath11k_warn(ab, "Coldboot Calibration timed out\n"); + return -ETIMEDOUT; + } + + /* reset the firmware */ + ath11k_hif_power_down(ab); + ath11k_hif_power_up(ab); + ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n"); + return 0; +} +EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot); + static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab) { int timeout; diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h index 0909d53cefeb..b0407abf90cd 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -37,7 +37,7 @@ #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH11K_FIRMWARE_MODE_OFF 4 -#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) +#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 @@ -519,5 +519,6 @@ void ath11k_qmi_msg_recv_work(struct work_struct *work); void ath11k_qmi_deinit_service(struct ath11k_base *ab); int ath11k_qmi_init_service(struct ath11k_base *ab); void ath11k_qmi_free_resource(struct ath11k_base *ab); +int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); #endif -- cgit From 13329d0cb7212b058bd8451a99d215a8f97645ea Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Wed, 26 Jul 2023 19:40:32 +0530 Subject: wifi: ath11k: Remove cal_done check during probe In some race conditions, calibration done QMI message is received even before host wait starts for calibration to be done. Due to this, resetting firmware was not performed after calibration. Hence, remove cal_done check in ath11k_qmi_fwreset_from_cold_boot() as this is called only from probe. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Seevalamuthu Mariappan Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726141032.3061-4-quic_rajkbhag@quicinc.com --- drivers/net/wireless/ath/ath11k/qmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index c4eab5d7f5c5..617abb441882 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -2844,7 +2844,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab) { int timeout; - if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || + if (!ath11k_core_coldboot_cal_support(ab) || ab->hw_params.cbcal_restart_fw == 0) return 0; -- cgit From 8ad314da54c6dd223a6b6cc85019160aa842f659 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 26 Jul 2023 05:26:25 -0400 Subject: wifi: ath12k: Fix a NULL pointer dereference in ath12k_mac_op_hw_scan() In ath12k_mac_op_hw_scan(), the return value of kzalloc() is directly used in memcpy(), which may lead to a NULL pointer dereference on failure of kzalloc(). Fix this bug by adding a check of arg.extraie.ptr. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726092625.3350-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 1bb9802ef569..af46b63bb15b 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -2755,9 +2755,12 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, arg.scan_id = ATH12K_SCAN_ID; if (req->ie_len) { + arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL); + if (!arg.extraie.ptr) { + ret = -ENOMEM; + goto exit; + } arg.extraie.len = req->ie_len; - arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL); - memcpy(arg.extraie.ptr, req->ie, req->ie_len); } if (req->n_ssids) { -- cgit From 15c8441dc1eddb9a19c75a0742edc9f002625931 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 26 Jul 2023 05:38:57 -0400 Subject: wifi: ath12k: correct the data_type from QMI_OPT_FLAG to QMI_UNSIGNED_1_BYTE for mlo_capable Currently, the encoding rule for field mlo_capable in struct qmi_wlanfw_host_cap_req_msg_v01 defined in array qmi_wlanfw_host_cap_req_msg_v01_ei uses type QMI_OPT_FLAG. Unfortunately, all ath12k firmware actually expects this field to be of type NON QMI_OPT_FLAG such as QMI_UNSIGNED_1_BYTE/QMI_UNSIGNED_8_BYTE... And as a result, firmware is unable to correctly decode the mlo_capable field. Change the ath12k definition as QMI_UNSIGNED_1_BYTE to match the firmware definition so that firmware can correctly parse the mlo_capable info from message QMI_WLANFW_HOST_CAP_REQ_V01 at wlan load time. This is just an accidental typo and that both WCN7850 and QCN9274 firmwares use QMI_UNSIGNED_1_BYTE. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726093857.3610-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/qmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index b510c2de1bd4..b2db0436bdde 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -387,7 +387,7 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { mlo_capable_valid), }, { - .data_type = QMI_OPT_FLAG, + .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, .elem_size = sizeof(u8), .array_type = NO_ARRAY, -- cgit From 603cf6c2fcdcbc38f1daa316794e7268852677a7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jul 2023 14:37:29 +0200 Subject: wifi: ath12k: fix memcpy array overflow in ath12k_peer_assoc_h_he() Two memory copies in this function copy from a short array into a longer one, using the wrong size, which leads to an out-of-bounds access: include/linux/fortify-string.h:592:4: error: call to '__read_overflow2_field' declared with 'warning' attribute: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] __read_overflow2_field(q_size_field, size); ^ include/linux/fortify-string.h:592:4: error: call to '__read_overflow2_field' declared with 'warning' attribute: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] 2 errors generated. Fixes: d889913205cf7 ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230703123737.3420464-1-arnd@kernel.org --- drivers/net/wireless/ath/ath12k/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index af46b63bb15b..d165b24094ad 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1637,9 +1637,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, arg->peer_nss = min(sta->deflink.rx_nss, max_nss); memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, - sizeof(arg->peer_he_cap_macinfo)); + sizeof(he_cap->he_cap_elem.mac_cap_info)); memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info, - sizeof(arg->peer_he_cap_phyinfo)); + sizeof(he_cap->he_cap_elem.phy_cap_info)); arg->peer_he_ops = vif->bss_conf.he_oper.params; /* the top most byte is used to indicate BSS color info */ -- cgit From 1e9b1363e2de1552ee4e3d74ac8bb43a194f1cb4 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Fri, 14 Jul 2023 03:24:05 -0400 Subject: wifi: ath12k: avoid array overflow of hw mode for preferred_hw_mode Currently ath12k define WMI_HOST_HW_MODE_DBS_OR_SBS=5 as max hw mode for enum wmi_host_hw_mode_config_type, it is also same for the array ath12k_hw_mode_pri_map. When tested with new version firmware/board data which support new hw mode eMLSR mode with hw mode value 8, it leads overflow usage for array ath12k_hw_mode_pri_map in function ath12k_wmi_hw_mode_caps(), and then lead preferred_hw_mode changed to 8, and finally function ath12k_pull_mac_phy_cap_svc_ready_ext() select the capability of hw mode 8, but the capability of eMLSR mode report from firmware does not support 2.4 GHz band for WCN7850, so finally 2.4 GHz band is disabled. Skip the hw mode which exceeds WMI_HOST_HW_MODE_MAX in function ath12k_wmi_hw_mode_caps() helps to avoid array overflow, then the 2.4 GHz band will not be disabled. This is to keep compatibility with newer version firmware/board data files, this change is still needed after ath12k add eMLSR hw mode 8 in array ath12k_hw_mode_pri_map and enum wmi_host_hw_mode_config_type, because more hw mode maybe added in next firmware/board data version e.g hw mode 9, then it will also lead new array overflow without this change. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230714072405.28705-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 6512267ae4ca..e6033ab15825 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -3705,6 +3705,10 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc, for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) { hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i]; mode = le32_to_cpu(hw_mode_caps->hw_mode_id); + + if (mode >= WMI_HOST_HW_MODE_MAX) + continue; + pref = soc->wmi_ab.preferred_hw_mode; if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) { -- cgit From 7ee027abd4533d53438ccafdd3ba7a68a16aae8d Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Fri, 14 Jul 2023 16:06:58 +0800 Subject: wifi: ath12k: Use pdev_id rather than mac_id to get pdev We are seeing kernel crash in below test scenario: 1. make DUT connect to an WPA3 encrypted 11ax AP in Ch44 HE80 2. use "wpa_cli -i disconnect" to disconnect 3. wait for DUT to automatically reconnect Kernel crashes while waiting, below shows the crash stack: [ 755.120868] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 755.120871] #PF: supervisor read access in kernel mode [ 755.120872] #PF: error_code(0x0000) - not-present page [ 755.120873] PGD 0 P4D 0 [ 755.120875] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 755.120876] CPU: 7 PID: 0 Comm: swapper/7 Kdump: loaded Not tainted 5.19.0-rc1+ #3 [ 755.120878] Hardware name: Intel(R) Client Systems NUC11PHi7/NUC11PHBi7, BIOS PHTGL579.0063.2021.0707.1057 07/07/2021 [ 755.120879] RIP: 0010:ath12k_dp_process_rx_err+0x2b6/0x14a0 [ath12k] [ 755.120890] Code: 01 c0 48 c1 e0 05 48 8b 9c 07 b8 b2 00 00 48 c7 c0 61 ff 0e c1 48 85 db 53 48 0f 44 c6 48 c7 c6 80 9d 0f c1 50 e8 1a 25 00 00 <4c> 8b 3b 4d 8b 76 14 41 59 41 5a 41 8b 87 78 43 01 00 4d 85 f6 89 [ 755.120891] RSP: 0018:ffff9a93402c8d10 EFLAGS: 00010282 [ 755.120892] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000303 [ 755.120893] RDX: 0000000000000000 RSI: ffffffff93b7cbe9 RDI: 00000000ffffffff [ 755.120894] RBP: ffff9a93402c8e50 R08: ffffffff93e65360 R09: ffffffff942e044d [ 755.120894] R10: 0000000000000000 R11: 0000000000000063 R12: ffff8dbec5420000 [ 755.120895] R13: ffff8dbec5420000 R14: ffff8dbdefe9a0a0 R15: ffff8dbec5420000 [ 755.120896] FS: 0000000000000000(0000) GS:ffff8dc2705c0000(0000) knlGS:0000000000000000 [ 755.120897] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 755.120898] CR2: 0000000000000000 CR3: 0000000107be4005 CR4: 0000000000770ee0 [ 755.120898] PKRU: 55555554 [ 755.120899] Call Trace: [ 755.120900] [ 755.120903] ? ath12k_pci_write32+0x2e/0x80 [ath12k] [ 755.120910] ath12k_dp_service_srng+0x214/0x2e0 [ath12k] [ 755.120917] ath12k_pci_ext_grp_napi_poll+0x26/0x80 [ath12k] [ 755.120923] __napi_poll+0x2b/0x1c0 [ 755.120925] net_rx_action+0x2a1/0x2f0 [ 755.120927] __do_softirq+0xfa/0x2e9 [ 755.120929] irq_exit_rcu+0xb9/0xd0 [ 755.120932] common_interrupt+0xc1/0xe0 [ 755.120934] [ 755.120934] [ 755.120935] asm_common_interrupt+0x2c/0x40 [ 755.120936] RIP: 0010:cpuidle_enter_state+0xdd/0x3a0 [ 755.120938] Code: 00 31 ff e8 45 e2 74 ff 80 7d d7 00 74 16 9c 58 0f 1f 40 00 f6 c4 02 0f 85 a0 02 00 00 31 ff e8 69 79 7b ff fb 0f 1f 44 00 00 <45> 85 ff 0f 88 6d 01 00 00 49 63 d7 4c 2b 6d c8 48 8d 04 52 48 8d [ 755.120939] RSP: 0018:ffff9a934018be50 EFLAGS: 00000246 [ 755.120940] RAX: ffff8dc2705c0000 RBX: 0000000000000002 RCX: 000000000000001f [ 755.120941] RDX: 000000afd0b532d3 RSI: ffffffff93b7cbe9 RDI: ffffffff93b8b66e [ 755.120942] RBP: ffff9a934018be88 R08: 0000000000000002 R09: 0000000000030500 [ 755.120942] R10: ffff9a934018be18 R11: 0000000000000741 R12: ffffba933fdc0600 [ 755.120943] R13: 000000afd0b532d3 R14: ffffffff93fcbc60 R15: 0000000000000002 [ 755.120945] cpuidle_enter+0x2e/0x40 [ 755.120946] call_cpuidle+0x23/0x40 [ 755.120948] do_idle+0x1ff/0x260 [ 755.120950] cpu_startup_entry+0x1d/0x20 [ 755.120951] start_secondary+0x10d/0x130 [ 755.120953] secondary_startup_64_no_verify+0xd3/0xdb [ 755.120956] [ 755.120956] Modules linked in: michael_mic rfcomm cmac algif_hash algif_skcipher af_alg bnep qrtr_mhi intel_rapl_msr intel_rapl_common x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio kvm_intel qrtr snd_hda_codec_hdmi kvm irqbypass ath12k snd_hda_intel snd_seq_midi crct10dif_pclmul mhi ghash_clmulni_intel snd_intel_dspcfg snd_seq_midi_event aesni_intel qmi_helpers i915 snd_rawmidi crypto_simd snd_hda_codec cryptd cec intel_cstate snd_hda_core mac80211 rc_core nouveau snd_seq snd_hwdep btusb drm_buddy drm_ttm_helper nls_iso8859_1 snd_pcm ttm btrtl snd_seq_device wmi_bmof mxm_wmi input_leds cfg80211 joydev btbcm drm_display_helper snd_timer btintel mei_me libarc4 drm_kms_helper bluetooth i2c_algo_bit snd fb_sys_fops syscopyarea mei sysfillrect ecdh_generic soundcore sysimgblt ecc acpi_pad mac_hid sch_fq_codel ipmi_devintf ipmi_msghandler msr parport_pc ppdev lp ramoops parport reed_solomon drm efi_pstore ip_tables x_tables autofs4 [ 755.120992] hid_generic usbhid hid ax88179_178a usbnet mii nvme nvme_core rtsx_pci_sdmmc crc32_pclmul i2c_i801 intel_lpss_pci i2c_smbus intel_lpss rtsx_pci idma64 virt_dma vmd wmi video [ 755.121002] CR2: 0000000000000000 The crash is because, for WCN7850, only ab->pdev[0] is initialized, while mac_id here is misused to retrieve pdev and it is not zero, leading to a NULL pointer access. Fix this issue by getting pdev_id first and then use it to retrieve pdev. Also fix some other code snippets which have the same issue. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230714080658.3140-1-quic_bqiang@quicinc.com --- drivers/net/wireless/ath/ath12k/dp_rx.c | 11 +++++++---- drivers/net/wireless/ath/ath12k/dp_tx.c | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index ffd9a2018610..67f8c140840f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -2539,7 +2539,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab, struct ath12k_skb_rxcb *rxcb; struct sk_buff *msdu; struct ath12k *ar; - u8 mac_id; + u8 mac_id, pdev_id; int ret; if (skb_queue_empty(msdu_list)) @@ -2550,8 +2550,9 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab, while ((msdu = __skb_dequeue(msdu_list))) { rxcb = ATH12K_SKB_RXCB(msdu); mac_id = rxcb->mac_id; - ar = ab->pdevs[mac_id].ar; - if (!rcu_dereference(ab->pdevs_active[mac_id])) { + pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id); + ar = ab->pdevs[pdev_id].ar; + if (!rcu_dereference(ab->pdevs_active[pdev_id])) { dev_kfree_skb_any(msdu); continue; } @@ -3385,6 +3386,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi, dma_addr_t paddr; bool is_frag; bool drop = false; + int pdev_id; tot_n_bufs_reaped = 0; quota = budget; @@ -3440,7 +3442,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi, mac_id = le32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); - ar = ab->pdevs[mac_id].ar; + pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id); + ar = ab->pdevs[pdev_id].ar; if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, drop, msdu_cookies[i])) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index d3c7c76d6b75..d661fe586651 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -347,6 +347,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab, { struct ath12k *ar; struct ath12k_skb_cb *skb_cb; + u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id); skb_cb = ATH12K_SKB_CB(msdu); @@ -357,7 +358,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab, dev_kfree_skb_any(msdu); - ar = ab->pdevs[mac_id].ar; + ar = ab->pdevs[pdev_id].ar; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); } @@ -536,7 +537,7 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) struct hal_tx_status ts = { 0 }; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; struct hal_wbm_release_ring *desc; - u8 mac_id; + u8 mac_id, pdev_id; u64 desc_va; spin_lock_bh(&status_ring->lock); @@ -605,7 +606,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) continue; } - ar = ab->pdevs[mac_id].ar; + pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id); + ar = ab->pdevs[pdev_id].ar; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); -- cgit From 68c35cc39b41dca8f6cb54915bdfd60dd7397b01 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Fri, 14 Jul 2023 05:25:55 -0400 Subject: wifi: ath12k: trigger station disconnect on hardware restart Currently after the hardware restart triggered from the driver, the station interface connection remains intact, since a disconnect trigger is not sent to userspace. This can lead to a problem in targets where the wifi mac sequence is added by the firmware. After the target restart, its wifi mac sequence number gets reset to zero. Hence AP to which our device is connected will receive frames with a wifi mac sequence number jump to the past, thereby resulting in the AP dropping all these frames, until the frame arrives with a wifi mac sequence number which AP was expecting. To avoid such frame drops, its better to trigger a station disconnect upon target hardware restart which can be done with API ieee80211_reconfig_disconnect exposed to mac80211. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230714092555.2018-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index d165b24094ad..13f477eb4707 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -6391,6 +6391,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, { struct ath12k *ar = hw->priv; struct ath12k_base *ab = ar->ab; + struct ath12k_vif *arvif; int recovery_count; if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) @@ -6419,6 +6420,26 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n"); } } + + list_for_each_entry(arvif, &ar->arvifs, list) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "reconfig cipher %d up %d vdev type %d\n", + arvif->key_cipher, + arvif->is_up, + arvif->vdev_type); + /* After trigger disconnect, then upper layer will + * trigger connect again, then the PN number of + * upper layer will be reset to keep up with AP + * side, hence PN number mis-match will not happened. + */ + if (arvif->is_up && + arvif->vdev_type == WMI_VDEV_TYPE_STA && + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) { + ieee80211_hw_restart_disconnect(arvif->vif); + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "restart disconnect\n"); + } + } } mutex_unlock(&ar->conf_mutex); -- cgit From 3742928a52d6859731d525f06c09decff87ffa01 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Sun, 16 Jul 2023 23:34:31 -0400 Subject: wifi: ath12k: change to use dynamic memory for channel list of scan Currently there are about 60 channels for 6 GHz, then the size of chan_list in struct scan_req_params which is 40 is not enough to fill all the channel list of 6 GHz. Use dynamic memory to save the channel list of scan. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230717033431.21983-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 10 ++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 13f477eb4707..4fa565a115e3 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -2773,6 +2773,14 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, if (req->n_channels) { arg.num_chan = req->n_channels; + arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), + GFP_KERNEL); + + if (!arg.chan_list) { + ret = -ENOMEM; + goto exit; + } + for (i = 0; i < arg.num_chan; i++) arg.chan_list[i] = req->channels[i]->center_freq; } @@ -2791,6 +2799,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, ATH12K_MAC_SCAN_TIMEOUT_MSECS)); exit: + kfree(arg.chan_list); + if (req->ie_len) kfree(arg.extraie.ptr); diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index d89c12bfb009..9b8ba8704904 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -3034,7 +3034,6 @@ enum scan_dwelltime_adaptive_mode { #define WLAN_SCAN_MAX_NUM_SSID 10 #define WLAN_SCAN_MAX_NUM_BSSID 10 -#define WLAN_SCAN_MAX_NUM_CHANNELS 40 struct ath12k_wmi_element_info_arg { u32 len; @@ -3243,7 +3242,7 @@ struct ath12k_wmi_scan_req_arg { u32 num_bssid; u32 num_ssids; u32 n_probes; - u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS]; + u32 *chan_list; u32 notify_scan_events; struct cfg80211_ssid ssid[WLAN_SCAN_MAX_NUM_SSID]; struct ath12k_wmi_mac_addr_params bssid_list[WLAN_SCAN_MAX_NUM_BSSID]; -- cgit From ae1d60c41e581be049aa84dd53aca89027101ce1 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 31 Jul 2023 15:38:58 +0800 Subject: net: hisilicon: fix the return value handle and remove redundant netdev_err() for platform_get_irq() There is no possible for platform_get_irq() to return 0 and the return value of platform_get_irq() is more sensible to show the error reason. And there is no need to call the netdev_err() function directly to print a custom message when handling an error from platform_get_irq() function as it is going to display an appropriate error message in case of a failure. Signed-off-by: Ruan Jinjie Reviewed-by: Jesse Brandeburg Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20230731073858.3633193-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hip04_eth.c | 4 ++-- drivers/net/ethernet/hisilicon/hisi_femac.c | 4 ++-- drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 50c3f5d6611f..ecf92a5d56bb 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -960,8 +960,8 @@ static int hip04_mac_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - ret = -EINVAL; + if (irq < 0) { + ret = irq; goto init_fail; } diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index ce2571c16e43..cb7b0293fe85 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -862,8 +862,8 @@ static int hisi_femac_drv_probe(struct platform_device *pdev) goto out_disconnect_phy; ndev->irq = platform_get_irq(pdev, 0); - if (ndev->irq <= 0) { - ret = -ENODEV; + if (ndev->irq < 0) { + ret = ndev->irq; goto out_disconnect_phy; } diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index f867e9531117..26d22bb04b87 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -1206,9 +1206,8 @@ static int hix5hd2_dev_probe(struct platform_device *pdev) } ndev->irq = platform_get_irq(pdev, 0); - if (ndev->irq <= 0) { - netdev_err(ndev, "No irq resource\n"); - ret = -EINVAL; + if (ndev->irq < 0) { + ret = ndev->irq; goto out_phy_node; } -- cgit From c7606d49e6093e9a66ffd1c5dfb294a4f8836dba Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Tue, 1 Aug 2023 19:26:38 +0800 Subject: octeontx2: Remove unnecessary ternary operators There are a little ternary operators, the true or false judgement of which is unnecessary in C language semantics. So remove it to clean Code. Signed-off-by: Ruan Jinjie Reviewed-by: Simon Horman Reviewed-by: Sunil Goutham Link: https://lore.kernel.org/r/20230801112638.317149-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 4 ++-- drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c index 0ee420a489fc..c55c2c441a1a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c @@ -61,12 +61,12 @@ static const struct pci_device_id ptp_id_table[]; static bool is_ptp_dev_cnf10kb(struct ptp *ptp) { - return (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_PTP) ? true : false; + return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_PTP; } static bool is_ptp_dev_cn10k(struct ptp *ptp) { - return (ptp->pdev->device == PCI_DEVID_CN10K_PTP) ? true : false; + return ptp->pdev->device == PCI_DEVID_CN10K_PTP; } static bool cn10k_ptp_errata(struct ptp *ptp) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 9551b422622a..61f62a6ec662 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -2027,7 +2027,7 @@ u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb, #endif int txq; - qos_enabled = (netdev->real_num_tx_queues > pf->hw.tx_queues) ? true : false; + qos_enabled = netdev->real_num_tx_queues > pf->hw.tx_queues; if (unlikely(qos_enabled)) { /* This smp_load_acquire() pairs with smp_store_release() in * otx2_qos_root_add() called from htb offload root creation -- cgit From ae336f30d513c5ccd8a87db02804c7451a061461 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Tue, 1 Aug 2023 19:19:28 +0800 Subject: bnx2x: Remove unnecessary ternary operators There are a little ternary operators, the true or false judgement of which is unnecessary in C language semantics. Signed-off-by: Ruan Jinjie Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230801111928.300231-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 542c69822649..8e04552d2216 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -890,7 +890,7 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp, (struct eth_classify_rules_ramrod_data *)(raw->rdata); int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd; union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; - bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; + bool add = cmd == BNX2X_VLAN_MAC_ADD; unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags; u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac; @@ -1075,7 +1075,7 @@ static void bnx2x_set_one_vlan_e2(struct bnx2x *bp, int rule_cnt = rule_idx + 1; union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; - bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; + bool add = cmd == BNX2X_VLAN_MAC_ADD; u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan; /* Reset the ramrod data buffer for the first rule */ @@ -1125,7 +1125,7 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp, int rule_cnt = rule_idx + 1; union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; enum bnx2x_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; - bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false; + bool add = cmd == BNX2X_VLAN_MAC_ADD; u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan; u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac; u16 inner_mac; -- cgit From ae3683a34265381cd4bc006295a091009c7215d1 Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 1 Aug 2023 15:16:47 +0200 Subject: net: dsa: hellcreek: Replace bogus comment Replace bogus comment about matching the latched timestamp to one of the received frames. That comment is probably copied from mv88e6xxx and true for these switches. However, the hellcreek switch is configured to insert the timestamp directly into the PTP packets. While here, remove the other comments regarding the list splicing and locking as well, because it doesn't add any value. Signed-off-by: Kurt Kanzenbach Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230801131647.84697-1-kurt@linutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c b/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c index ffd06cf8c44f..bd7aacc71a63 100644 --- a/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c +++ b/drivers/net/dsa/hirschmann/hellcreek_hwtstamp.c @@ -298,17 +298,10 @@ static void hellcreek_get_rxts(struct hellcreek *hellcreek, struct sk_buff_head received; unsigned long flags; - /* The latched timestamp belongs to one of the received frames. */ + /* Construct Rx timestamps for all received PTP packets. */ __skb_queue_head_init(&received); - - /* Lock & disable interrupts */ spin_lock_irqsave(&rxq->lock, flags); - - /* Add the reception queue "rxq" to the "received" queue an reintialize - * "rxq". From now on, we deal with "received" not with "rxq" - */ skb_queue_splice_tail_init(rxq, &received); - spin_unlock_irqrestore(&rxq->lock, flags); for (; skb; skb = __skb_dequeue(&received)) { -- cgit From 497c3a5fb3ed4a59c4d3c460c70393dd609815dc Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Tue, 1 Aug 2023 21:31:21 +0800 Subject: cirrus: cs89x0: fix the return value handle and remove redundant dev_warn() for platform_get_irq() There is no possible for platform_get_irq() to return 0 and the return value of platform_get_irq() is more sensible to show the error reason. And there is no need to call the dev_warn() function directly to print a custom message when handling an error from platform_get_irq() function as it is going to display an appropriate error message in case of a failure. Signed-off-by: Ruan Jinjie Reviewed-by: Simon Horman Reviewed-by: Alex Elder Link: https://lore.kernel.org/r/20230801133121.416319-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/cirrus/cs89x0.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index 7c51fd9fc9be..d323c5c23521 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1854,9 +1854,8 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev) return -ENOMEM; dev->irq = platform_get_irq(pdev, 0); - if (dev->irq <= 0) { - dev_warn(&dev->dev, "interrupt resource missing\n"); - err = -ENXIO; + if (dev->irq < 0) { + err = dev->irq; goto free; } -- cgit From 30ff01ee99bc961e5f278f997e41ffb94785a88b Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Tue, 1 Aug 2023 09:58:33 -0700 Subject: pds_core: Fix documentation for pds_client_register The documentation above pds_client_register states that it returns 0 on success and negative on error. However, it actually returns a positive client ID on success and negative on error. Fix the documentation to state exactly that. Signed-off-by: Brett Creeley Signed-off-by: Shannon Nelson Reviewed-by: Jesse Brandeburg Link: https://lore.kernel.org/r/20230801165833.1622-1-brett.creeley@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/auxbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c index 561af8e5b3ea..6787a5fae908 100644 --- a/drivers/net/ethernet/amd/pds_core/auxbus.c +++ b/drivers/net/ethernet/amd/pds_core/auxbus.c @@ -11,7 +11,7 @@ * @pf_pdev: ptr to the PF driver struct * @devname: name that includes service into, e.g. pds_core.vDPA * - * Return: 0 on success, or + * Return: positive client ID (ci) on success, or * negative for error */ int pds_client_register(struct pci_dev *pf_pdev, char *devname) -- cgit From fbd517549c324049d636de0872ad9d3de63ec015 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:12 +0300 Subject: net/mlx5e: Add function to get IPsec offload namespace Add function to get namespace in different directions. It will be extended for switchdev mode in later patch, but no functionality change for now. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/ac2982c34f1ed3288d4670cacfd7e1b87a8c96d9.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 46 +++++++++++----------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 47baf983147f..7ec92f0cf1bd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -814,11 +814,20 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp } } -static int setup_modify_header(struct mlx5_core_dev *mdev, u32 val, u8 dir, +static enum mlx5_flow_namespace_type ipsec_fs_get_ns(struct mlx5e_ipsec *ipsec, u8 dir) +{ + if (dir == XFRM_DEV_OFFLOAD_IN) + return MLX5_FLOW_NAMESPACE_KERNEL; + + return MLX5_FLOW_NAMESPACE_EGRESS; +} + +static int setup_modify_header(struct mlx5e_ipsec *ipsec, u32 val, u8 dir, struct mlx5_flow_act *flow_act) { + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, dir); u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; - enum mlx5_flow_namespace_type ns_type; + struct mlx5_core_dev *mdev = ipsec->mdev; struct mlx5_modify_hdr *modify_hdr; MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); @@ -826,12 +835,10 @@ static int setup_modify_header(struct mlx5_core_dev *mdev, u32 val, u8 dir, case XFRM_DEV_OFFLOAD_IN: MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); - ns_type = MLX5_FLOW_NAMESPACE_KERNEL; break; case XFRM_DEV_OFFLOAD_OUT: MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_0); - ns_type = MLX5_FLOW_NAMESPACE_EGRESS; break; default: return -EINVAL; @@ -1024,26 +1031,16 @@ setup_pkt_transport_reformat(struct mlx5_accel_esp_xfrm_attrs *attrs, return 0; } -static int setup_pkt_reformat(struct mlx5_core_dev *mdev, +static int setup_pkt_reformat(struct mlx5e_ipsec *ipsec, struct mlx5_accel_esp_xfrm_attrs *attrs, struct mlx5_flow_act *flow_act) { + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, attrs->dir); struct mlx5_pkt_reformat_params reformat_params = {}; + struct mlx5_core_dev *mdev = ipsec->mdev; struct mlx5_pkt_reformat *pkt_reformat; - enum mlx5_flow_namespace_type ns_type; int ret; - switch (attrs->dir) { - case XFRM_DEV_OFFLOAD_IN: - ns_type = MLX5_FLOW_NAMESPACE_KERNEL; - break; - case XFRM_DEV_OFFLOAD_OUT: - ns_type = MLX5_FLOW_NAMESPACE_EGRESS; - break; - default: - return -EINVAL; - } - switch (attrs->mode) { case XFRM_MODE_TRANSPORT: ret = setup_pkt_transport_reformat(attrs, &reformat_params); @@ -1101,14 +1098,14 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) setup_fte_esp(spec); setup_fte_no_frags(spec); - err = setup_modify_header(mdev, sa_entry->ipsec_obj_id | BIT(31), + err = setup_modify_header(ipsec, sa_entry->ipsec_obj_id | BIT(31), XFRM_DEV_OFFLOAD_IN, &flow_act); if (err) goto err_mod_header; switch (attrs->type) { case XFRM_DEV_OFFLOAD_PACKET: - err = setup_pkt_reformat(mdev, attrs, &flow_act); + err = setup_pkt_reformat(ipsec, attrs, &flow_act); if (err) goto err_pkt_reformat; break; @@ -1202,7 +1199,7 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) case XFRM_DEV_OFFLOAD_PACKET: if (attrs->reqid) setup_fte_reg_c0(spec, attrs->reqid); - err = setup_pkt_reformat(mdev, attrs, &flow_act); + err = setup_pkt_reformat(ipsec, attrs, &flow_act); if (err) goto err_pkt_reformat; break; @@ -1259,15 +1256,16 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) { struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); - struct mlx5e_ipsec_tx *tx = pol_entry->ipsec->tx; + struct mlx5e_ipsec *ipsec = pol_entry->ipsec; struct mlx5_flow_destination dest[2] = {}; + struct mlx5e_ipsec_tx *tx = ipsec->tx; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; struct mlx5_flow_table *ft; int err, dstn = 0; - ft = tx_ft_get_policy(mdev, pol_entry->ipsec, attrs->prio); + ft = tx_ft_get_policy(mdev, ipsec, attrs->prio); if (IS_ERR(ft)) return PTR_ERR(ft); @@ -1291,7 +1289,7 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) if (!attrs->reqid) break; - err = setup_modify_header(mdev, attrs->reqid, + err = setup_modify_header(ipsec, attrs->reqid, XFRM_DEV_OFFLOAD_OUT, &flow_act); if (err) goto err_mod_header; @@ -1331,7 +1329,7 @@ err_action: err_mod_header: kvfree(spec); err_alloc: - tx_ft_put_policy(pol_entry->ipsec, attrs->prio); + tx_ft_put_policy(ipsec, attrs->prio); return err; } -- cgit From 33b18a0f75cd2278a1ebb585b53be9c10f6f5364 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:13 +0300 Subject: net/mlx5e: Change the parameter of IPsec RX skb handle function Refactor the function to pass in reg B value only. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/3b3c53f64660d464893eaecc41298b1ce49c6baa.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 3 +-- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c index eab5bc718771..8d6379ac4574 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c @@ -309,9 +309,8 @@ enum { void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, - struct mlx5_cqe64 *cqe) + u32 ipsec_meta_data) { - u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata); struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5e_ipsec *ipsec = priv->ipsec; struct mlx5e_ipsec_sa_entry *sa_entry; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h index 1878a70b9031..436e9a8a32d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h @@ -66,7 +66,7 @@ void mlx5e_ipsec_handle_tx_wqe(struct mlx5e_tx_wqe *wqe, struct mlx5_wqe_inline_seg *inlseg); void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, - struct mlx5_cqe64 *cqe); + u32 ipsec_meta_data); static inline unsigned int mlx5e_ipsec_tx_ids_len(struct mlx5e_accel_tx_ipsec_state *ipsec_st) { return ipsec_st->tailen; @@ -145,7 +145,7 @@ mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, static inline void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, - struct mlx5_cqe64 *cqe) + u32 ipsec_meta_data) {} static inline bool mlx5e_ipsec_eseg_meta(struct mlx5_wqe_eth_seg *eseg) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 41d37159e027..f7bb5f4aaaca 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1543,7 +1543,8 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, mlx5e_ktls_handle_rx_skb(rq, skb, cqe, &cqe_bcnt); if (unlikely(mlx5_ipsec_is_rx_flow(cqe))) - mlx5e_ipsec_offload_handle_rx_skb(netdev, skb, cqe); + mlx5e_ipsec_offload_handle_rx_skb(netdev, skb, + be32_to_cpu(cqe->ft_metadata)); if (unlikely(mlx5e_macsec_is_rx_flow(cqe))) mlx5e_macsec_offload_handle_rx_skb(netdev, skb, cqe); -- cgit From f5c5abc4c04110317dd3e7d5794bd0ca43a013ca Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:14 +0300 Subject: net/mlx5e: Prepare IPsec packet offload for switchdev mode As the uplink representor is created only in switchdev mode, add a local variable for IPsec to indicate the device is in this mode. In this mode, IPsec ROCE is disabled, and crypto offload is kept as it is. However, as the tables for packet offload are created in FDB, ipsec->rx_esw and ipsec->tx_esw are added. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/ee242398f3b0a18007749fe79ff6ff19445a0280.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 2 + .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 3 + .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 262 ++++++++++++++------- 3 files changed, 184 insertions(+), 83 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 658b7d8d50c7..a577f0edabe8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -40,6 +40,7 @@ #include "en.h" #include "ipsec.h" #include "ipsec_rxtx.h" +#include "en_rep.h" #define MLX5_IPSEC_RESCHED msecs_to_jiffies(1000) #define MLX5E_IPSEC_TUNNEL_SA XA_MARK_1 @@ -858,6 +859,7 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv) goto clear_aso; } + ipsec->is_uplink_rep = mlx5e_is_uplink_rep(priv); ret = mlx5e_accel_ipsec_fs_init(ipsec); if (ret) goto err_fs_init; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index 7a7047263618..e12154276666 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -178,11 +178,14 @@ struct mlx5e_ipsec { struct mlx5e_flow_steering *fs; struct mlx5e_ipsec_rx *rx_ipv4; struct mlx5e_ipsec_rx *rx_ipv6; + struct mlx5e_ipsec_rx *rx_esw; struct mlx5e_ipsec_tx *tx; + struct mlx5e_ipsec_tx *tx_esw; struct mlx5e_ipsec_aso *aso; struct notifier_block nb; struct notifier_block netevent_nb; struct mlx5_ipsec_fs *roce; + u8 is_uplink_rep: 1; }; struct mlx5e_ipsec_esn_state { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 7ec92f0cf1bd..0f0c48f5f620 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -60,14 +60,25 @@ static enum mlx5_traffic_types family2tt(u32 family) return MLX5_TT_IPV6_IPSEC_ESP; } -static struct mlx5e_ipsec_rx *ipsec_rx(struct mlx5e_ipsec *ipsec, u32 family) +static struct mlx5e_ipsec_rx *ipsec_rx(struct mlx5e_ipsec *ipsec, u32 family, int type) { + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) + return ipsec->rx_esw; + if (family == AF_INET) return ipsec->rx_ipv4; return ipsec->rx_ipv6; } +static struct mlx5e_ipsec_tx *ipsec_tx(struct mlx5e_ipsec *ipsec, int type) +{ + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) + return ipsec->tx_esw; + + return ipsec->tx; +} + static struct mlx5_fs_chains * ipsec_chains_create(struct mlx5_core_dev *mdev, struct mlx5_flow_table *miss_ft, enum mlx5_flow_namespace_type ns, int base_prio, @@ -406,9 +417,10 @@ static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, } static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, - struct mlx5e_ipsec *ipsec, u32 family) + struct mlx5e_ipsec *ipsec, u32 family, + int type) { - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); int err; mutex_lock(&rx->ft.mutex); @@ -422,9 +434,9 @@ static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, static struct mlx5_flow_table *rx_ft_get_policy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, - u32 family, u32 prio) + u32 family, u32 prio, int type) { - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); struct mlx5_flow_table *ft; int err; @@ -449,18 +461,18 @@ err_get: return ERR_PTR(err); } -static void rx_ft_put(struct mlx5e_ipsec *ipsec, u32 family) +static void rx_ft_put(struct mlx5e_ipsec *ipsec, u32 family, int type) { - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); mutex_lock(&rx->ft.mutex); rx_put(ipsec, rx, family); mutex_unlock(&rx->ft.mutex); } -static void rx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 family, u32 prio) +static void rx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 family, u32 prio, int type) { - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); mutex_lock(&rx->ft.mutex); if (rx->chains) @@ -629,9 +641,9 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, - u32 prio) + u32 prio, int type) { - struct mlx5e_ipsec_tx *tx = ipsec->tx; + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); struct mlx5_flow_table *ft; int err; @@ -657,9 +669,9 @@ err_get: } static struct mlx5e_ipsec_tx *tx_ft_get(struct mlx5_core_dev *mdev, - struct mlx5e_ipsec *ipsec) + struct mlx5e_ipsec *ipsec, int type) { - struct mlx5e_ipsec_tx *tx = ipsec->tx; + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); int err; mutex_lock(&tx->ft.mutex); @@ -671,18 +683,18 @@ static struct mlx5e_ipsec_tx *tx_ft_get(struct mlx5_core_dev *mdev, return tx; } -static void tx_ft_put(struct mlx5e_ipsec *ipsec) +static void tx_ft_put(struct mlx5e_ipsec *ipsec, int type) { - struct mlx5e_ipsec_tx *tx = ipsec->tx; + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); mutex_lock(&tx->ft.mutex); tx_put(ipsec, tx); mutex_unlock(&tx->ft.mutex); } -static void tx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 prio) +static void tx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 prio, int type) { - struct mlx5e_ipsec_tx *tx = ipsec->tx; + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); mutex_lock(&tx->ft.mutex); if (tx->chains) @@ -1079,7 +1091,7 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) struct mlx5_fc *counter; int err; - rx = rx_ft_get(mdev, ipsec, attrs->family); + rx = rx_ft_get(mdev, ipsec, attrs->family, attrs->type); if (IS_ERR(rx)) return PTR_ERR(rx); @@ -1155,7 +1167,7 @@ err_pkt_reformat: err_mod_header: kvfree(spec); err_alloc: - rx_ft_put(ipsec, attrs->family); + rx_ft_put(ipsec, attrs->family, attrs->type); return err; } @@ -1172,7 +1184,7 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) struct mlx5_fc *counter; int err; - tx = tx_ft_get(mdev, ipsec); + tx = tx_ft_get(mdev, ipsec, attrs->type); if (IS_ERR(tx)) return PTR_ERR(tx); @@ -1248,7 +1260,7 @@ err_add_cnt: err_pkt_reformat: kvfree(spec); err_alloc: - tx_ft_put(ipsec); + tx_ft_put(ipsec, attrs->type); return err; } @@ -1258,14 +1270,14 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); struct mlx5e_ipsec *ipsec = pol_entry->ipsec; struct mlx5_flow_destination dest[2] = {}; - struct mlx5e_ipsec_tx *tx = ipsec->tx; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; struct mlx5_flow_table *ft; + struct mlx5e_ipsec_tx *tx; int err, dstn = 0; - ft = tx_ft_get_policy(mdev, ipsec, attrs->prio); + ft = tx_ft_get_policy(mdev, ipsec, attrs->prio, attrs->type); if (IS_ERR(ft)) return PTR_ERR(ft); @@ -1275,6 +1287,7 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) goto err_alloc; } + tx = ipsec_tx(ipsec, attrs->type); if (attrs->family == AF_INET) setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); else @@ -1329,7 +1342,7 @@ err_action: err_mod_header: kvfree(spec); err_alloc: - tx_ft_put_policy(ipsec, attrs->prio); + tx_ft_put_policy(ipsec, attrs->prio, attrs->type); return err; } @@ -1345,11 +1358,12 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) struct mlx5e_ipsec_rx *rx; int err, dstn = 0; - ft = rx_ft_get_policy(mdev, pol_entry->ipsec, attrs->family, attrs->prio); + ft = rx_ft_get_policy(mdev, pol_entry->ipsec, attrs->family, attrs->prio, + attrs->type); if (IS_ERR(ft)) return PTR_ERR(ft); - rx = ipsec_rx(pol_entry->ipsec, attrs->family); + rx = ipsec_rx(pol_entry->ipsec, attrs->family, attrs->type); spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) { @@ -1398,88 +1412,110 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) err_action: kvfree(spec); err_alloc: - rx_ft_put_policy(pol_entry->ipsec, attrs->family, attrs->prio); + rx_ft_put_policy(pol_entry->ipsec, attrs->family, attrs->prio, attrs->type); return err; } +static void ipsec_fs_destroy_single_counter(struct mlx5_core_dev *mdev, + struct mlx5e_ipsec_fc *fc) +{ + mlx5_fc_destroy(mdev, fc->drop); + mlx5_fc_destroy(mdev, fc->cnt); + kfree(fc); +} + static void ipsec_fs_destroy_counters(struct mlx5e_ipsec *ipsec) { - struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; struct mlx5_core_dev *mdev = ipsec->mdev; - struct mlx5e_ipsec_tx *tx = ipsec->tx; - - mlx5_fc_destroy(mdev, tx->fc->drop); - mlx5_fc_destroy(mdev, tx->fc->cnt); - kfree(tx->fc); - mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); - mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); - kfree(rx_ipv4->fc); + + ipsec_fs_destroy_single_counter(mdev, ipsec->tx->fc); + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_ipv4->fc); + if (ipsec->is_uplink_rep) { + ipsec_fs_destroy_single_counter(mdev, ipsec->tx_esw->fc); + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_esw->fc); + } } -static int ipsec_fs_init_counters(struct mlx5e_ipsec *ipsec) +static struct mlx5e_ipsec_fc *ipsec_fs_init_single_counter(struct mlx5_core_dev *mdev) { - struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; - struct mlx5e_ipsec_rx *rx_ipv6 = ipsec->rx_ipv6; - struct mlx5_core_dev *mdev = ipsec->mdev; - struct mlx5e_ipsec_tx *tx = ipsec->tx; struct mlx5e_ipsec_fc *fc; struct mlx5_fc *counter; int err; - fc = kzalloc(sizeof(*rx_ipv4->fc), GFP_KERNEL); + fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (!fc) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - /* Both IPv4 and IPv6 point to same flow counters struct. */ - rx_ipv4->fc = fc; - rx_ipv6->fc = fc; counter = mlx5_fc_create(mdev, false); if (IS_ERR(counter)) { err = PTR_ERR(counter); - goto err_rx_cnt; + goto err_cnt; } - fc->cnt = counter; + counter = mlx5_fc_create(mdev, false); if (IS_ERR(counter)) { err = PTR_ERR(counter); - goto err_rx_drop; + goto err_drop; } - fc->drop = counter; - fc = kzalloc(sizeof(*tx->fc), GFP_KERNEL); - if (!fc) { - err = -ENOMEM; - goto err_tx_fc; + + return fc; + +err_drop: + mlx5_fc_destroy(mdev, fc->cnt); +err_cnt: + kfree(fc); + return ERR_PTR(err); +} + +static int ipsec_fs_init_counters(struct mlx5e_ipsec *ipsec) +{ + struct mlx5_core_dev *mdev = ipsec->mdev; + struct mlx5e_ipsec_fc *fc; + int err; + + fc = ipsec_fs_init_single_counter(mdev); + if (IS_ERR(fc)) { + err = PTR_ERR(fc); + goto err_rx_cnt; } + ipsec->rx_ipv4->fc = fc; - tx->fc = fc; - counter = mlx5_fc_create(mdev, false); - if (IS_ERR(counter)) { - err = PTR_ERR(counter); + fc = ipsec_fs_init_single_counter(mdev); + if (IS_ERR(fc)) { + err = PTR_ERR(fc); goto err_tx_cnt; } + ipsec->tx->fc = fc; - fc->cnt = counter; - counter = mlx5_fc_create(mdev, false); - if (IS_ERR(counter)) { - err = PTR_ERR(counter); - goto err_tx_drop; + if (ipsec->is_uplink_rep) { + fc = ipsec_fs_init_single_counter(mdev); + if (IS_ERR(fc)) { + err = PTR_ERR(fc); + goto err_rx_esw_cnt; + } + ipsec->rx_esw->fc = fc; + + fc = ipsec_fs_init_single_counter(mdev); + if (IS_ERR(fc)) { + err = PTR_ERR(fc); + goto err_tx_esw_cnt; + } + ipsec->tx_esw->fc = fc; } - fc->drop = counter; + /* Both IPv4 and IPv6 point to same flow counters struct. */ + ipsec->rx_ipv6->fc = ipsec->rx_ipv4->fc; return 0; -err_tx_drop: - mlx5_fc_destroy(mdev, tx->fc->cnt); +err_tx_esw_cnt: + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_esw->fc); +err_rx_esw_cnt: + ipsec_fs_destroy_single_counter(mdev, ipsec->tx->fc); err_tx_cnt: - kfree(tx->fc); -err_tx_fc: - mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); -err_rx_drop: - mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_ipv4->fc); err_rx_cnt: - kfree(rx_ipv4->fc); return err; } @@ -1489,6 +1525,7 @@ void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv, void *ipsec_stats) struct mlx5e_ipsec *ipsec = priv->ipsec; struct mlx5e_ipsec_hw_stats *stats; struct mlx5e_ipsec_fc *fc; + u64 packets, bytes; stats = (struct mlx5e_ipsec_hw_stats *)ipsec_stats; @@ -1510,6 +1547,30 @@ void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv, void *ipsec_stats) mlx5_fc_query(mdev, fc->cnt, &stats->ipsec_tx_pkts, &stats->ipsec_tx_bytes); mlx5_fc_query(mdev, fc->drop, &stats->ipsec_tx_drop_pkts, &stats->ipsec_tx_drop_bytes); + + if (ipsec->is_uplink_rep) { + fc = ipsec->rx_esw->fc; + if (!mlx5_fc_query(mdev, fc->cnt, &packets, &bytes)) { + stats->ipsec_rx_pkts += packets; + stats->ipsec_rx_bytes += bytes; + } + + if (!mlx5_fc_query(mdev, fc->drop, &packets, &bytes)) { + stats->ipsec_rx_drop_pkts += packets; + stats->ipsec_rx_drop_bytes += bytes; + } + + fc = ipsec->tx_esw->fc; + if (!mlx5_fc_query(mdev, fc->cnt, &packets, &bytes)) { + stats->ipsec_tx_pkts += packets; + stats->ipsec_tx_bytes += bytes; + } + + if (!mlx5_fc_query(mdev, fc->drop, &packets, &bytes)) { + stats->ipsec_tx_drop_pkts += packets; + stats->ipsec_tx_drop_bytes += bytes; + } + } } int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) @@ -1531,12 +1592,12 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) mlx5_packet_reformat_dealloc(mdev, ipsec_rule->pkt_reformat); if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) { - tx_ft_put(sa_entry->ipsec); + tx_ft_put(sa_entry->ipsec, sa_entry->attrs.type); return; } mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); - rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family); + rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family, sa_entry->attrs.type); } int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry) @@ -1556,14 +1617,14 @@ void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry) if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) { rx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.family, - pol_entry->attrs.prio); + pol_entry->attrs.prio, pol_entry->attrs.type); return; } if (ipsec_rule->modify_hdr) mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); - tx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.prio); + tx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.prio, pol_entry->attrs.type); } void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) @@ -1571,7 +1632,7 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) if (!ipsec->tx) return; - if (mlx5_ipsec_device_caps(ipsec->mdev) & MLX5_IPSEC_CAP_ROCE) + if (ipsec->roce) mlx5_ipsec_fs_roce_cleanup(ipsec->roce); ipsec_fs_destroy_counters(ipsec); @@ -1586,12 +1647,22 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) mutex_destroy(&ipsec->rx_ipv6->ft.mutex); WARN_ON(ipsec->rx_ipv6->ft.refcnt); kfree(ipsec->rx_ipv6); + + if (ipsec->is_uplink_rep) { + mutex_destroy(&ipsec->tx_esw->ft.mutex); + WARN_ON(ipsec->tx_esw->ft.refcnt); + kfree(ipsec->tx_esw); + + mutex_destroy(&ipsec->rx_esw->ft.mutex); + WARN_ON(ipsec->rx_esw->ft.refcnt); + kfree(ipsec->rx_esw); + } } int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) { struct mlx5_core_dev *mdev = ipsec->mdev; - struct mlx5_flow_namespace *ns; + struct mlx5_flow_namespace *ns, *ns_esw; int err = -ENOMEM; ns = mlx5_get_flow_namespace(ipsec->mdev, @@ -1599,9 +1670,23 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) if (!ns) return -EOPNOTSUPP; + if (ipsec->is_uplink_rep) { + ns_esw = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_FDB); + if (!ns_esw) + return -EOPNOTSUPP; + + ipsec->tx_esw = kzalloc(sizeof(*ipsec->tx_esw), GFP_KERNEL); + if (!ipsec->tx_esw) + return -ENOMEM; + + ipsec->rx_esw = kzalloc(sizeof(*ipsec->rx_esw), GFP_KERNEL); + if (!ipsec->rx_esw) + goto err_rx_esw; + } + ipsec->tx = kzalloc(sizeof(*ipsec->tx), GFP_KERNEL); if (!ipsec->tx) - return -ENOMEM; + goto err_tx; ipsec->rx_ipv4 = kzalloc(sizeof(*ipsec->rx_ipv4), GFP_KERNEL); if (!ipsec->rx_ipv4) @@ -1620,8 +1705,13 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) mutex_init(&ipsec->rx_ipv6->ft.mutex); ipsec->tx->ns = ns; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) + if (ipsec->is_uplink_rep) { + mutex_init(&ipsec->tx_esw->ft.mutex); + mutex_init(&ipsec->rx_esw->ft.mutex); + ipsec->tx_esw->ns = ns_esw; + } else if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) { ipsec->roce = mlx5_ipsec_fs_roce_init(mdev); + } return 0; @@ -1631,6 +1721,10 @@ err_rx_ipv6: kfree(ipsec->rx_ipv4); err_rx_ipv4: kfree(ipsec->tx); +err_tx: + kfree(ipsec->rx_esw); +err_rx_esw: + kfree(ipsec->tx_esw); return err; } @@ -1652,10 +1746,12 @@ void mlx5e_accel_ipsec_fs_modify(struct mlx5e_ipsec_sa_entry *sa_entry) bool mlx5e_ipsec_fs_tunnel_enabled(struct mlx5e_ipsec_sa_entry *sa_entry) { - struct mlx5e_ipsec_rx *rx = - ipsec_rx(sa_entry->ipsec, sa_entry->attrs.family); - struct mlx5e_ipsec_tx *tx = sa_entry->ipsec->tx; + struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; + struct mlx5e_ipsec_rx *rx; + struct mlx5e_ipsec_tx *tx; + rx = ipsec_rx(sa_entry->ipsec, attrs->family, attrs->type); + tx = ipsec_tx(sa_entry->ipsec, attrs->type); if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) return tx->allow_tunnel_mode; -- cgit From 6e125265d52d491781e6301b80f885f2453d2e65 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:15 +0300 Subject: net/mlx5e: Refactor IPsec RX tables creation and destruction Add attribute for IPsec RX creation, so rx_create() can be used by eswitch in later patch. And move the code for TTC dest connect/disconnect, which are needed only in NIC mode, to individual functions. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/87478d928479b6a4eee41901204546ea05741815.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 11 +++ .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 100 ++++++++++++++------- 2 files changed, 80 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index e12154276666..03d83cdf1e20 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -169,6 +169,17 @@ struct mlx5e_ipsec_aso { spinlock_t lock; }; +struct mlx5e_ipsec_rx_create_attr { + struct mlx5_flow_namespace *ns; + struct mlx5_ttc_table *ttc; + u32 family; + int prio; + int pol_level; + int sa_level; + int status_level; + enum mlx5_flow_namespace_type chains_ns; +}; + struct mlx5e_ipsec { struct mlx5_core_dev *mdev; struct xarray sadb; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 0f0c48f5f620..52e382948c13 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -249,13 +249,19 @@ out: return err; } +static void ipsec_rx_ft_disconnect(struct mlx5e_ipsec *ipsec, u32 family) +{ + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); + + mlx5_ttc_fwd_default_dest(ttc, family2tt(family)); +} + static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, u32 family) { - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); /* disconnect */ - mlx5_ttc_fwd_default_dest(ttc, family2tt(family)); + ipsec_rx_ft_disconnect(ipsec, family); if (rx->chains) { ipsec_chains_destroy(rx->chains); @@ -277,41 +283,78 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family); } +static void ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + u32 family, + struct mlx5e_ipsec_rx_create_attr *attr) +{ + attr->ns = mlx5e_fs_get_ns(ipsec->fs, false); + attr->ttc = mlx5e_fs_get_ttc(ipsec->fs, false); + attr->family = family; + attr->prio = MLX5E_NIC_PRIO; + attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL; + attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; + attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; + attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL; +} + +static int ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5e_ipsec_rx_create_attr *attr, + struct mlx5_flow_destination *dest) +{ + struct mlx5_flow_table *ft; + int err; + + *dest = mlx5_ttc_get_default_dest(attr->ttc, family2tt(attr->family)); + err = mlx5_ipsec_fs_roce_rx_create(ipsec->mdev, ipsec->roce, attr->ns, dest, + attr->family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, + attr->prio); + if (err) + return err; + + ft = mlx5_ipsec_fs_roce_ft_get(ipsec->roce, attr->family); + if (ft) { + dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest->ft = ft; + } + + return 0; +} + +static void ipsec_rx_ft_connect(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5e_ipsec_rx_create_attr *attr) +{ + struct mlx5_flow_destination dest = {}; + + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest.ft = rx->ft.pol; + mlx5_ttc_fwd_dest(attr->ttc, family2tt(attr->family), &dest); +} + static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, u32 family) { - struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(ipsec->fs, false); - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); - struct mlx5_flow_destination default_dest; + struct mlx5e_ipsec_rx_create_attr attr; struct mlx5_flow_destination dest[2]; struct mlx5_flow_table *ft; u32 flags = 0; int err; - default_dest = mlx5_ttc_get_default_dest(ttc, family2tt(family)); - err = mlx5_ipsec_fs_roce_rx_create(mdev, ipsec->roce, ns, &default_dest, - family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, - MLX5E_NIC_PRIO); + ipsec_rx_create_attr_set(ipsec, rx, family, &attr); + + err = ipsec_rx_status_pass_dest_get(ipsec, rx, &attr, &dest[0]); if (err) return err; - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, - MLX5E_NIC_PRIO, 1, 0); + ft = ipsec_ft_create(attr.ns, attr.status_level, attr.prio, 1, 0); if (IS_ERR(ft)) { err = PTR_ERR(ft); goto err_fs_ft_status; } - rx->ft.status = ft; - ft = mlx5_ipsec_fs_roce_ft_get(ipsec->roce, family); - if (ft) { - dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest[0].ft = ft; - } else { - dest[0] = default_dest; - } - dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; dest[1].counter_id = mlx5_fc_id(rx->fc->cnt); err = ipsec_status_rule(mdev, rx, dest); @@ -323,8 +366,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (rx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_LEVEL, MLX5E_NIC_PRIO, 2, - flags); + ft = ipsec_ft_create(attr.ns, attr.sa_level, attr.prio, 2, flags); if (IS_ERR(ft)) { err = PTR_ERR(ft); goto err_fs_ft; @@ -337,9 +379,9 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) { rx->chains = ipsec_chains_create(mdev, rx->ft.sa, - MLX5_FLOW_NAMESPACE_KERNEL, - MLX5E_NIC_PRIO, - MLX5E_ACCEL_FS_POL_FT_LEVEL, + attr.chains_ns, + attr.prio, + attr.pol_level, &rx->ft.pol); if (IS_ERR(rx->chains)) { err = PTR_ERR(rx->chains); @@ -349,8 +391,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, goto connect; } - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_POL_FT_LEVEL, MLX5E_NIC_PRIO, - 2, 0); + ft = ipsec_ft_create(attr.ns, attr.pol_level, attr.prio, 2, 0); if (IS_ERR(ft)) { err = PTR_ERR(ft); goto err_pol_ft; @@ -365,10 +406,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, connect: /* connect */ - memset(dest, 0x00, sizeof(*dest)); - dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest[0].ft = rx->ft.pol; - mlx5_ttc_fwd_dest(ttc, family2tt(family), &dest[0]); + ipsec_rx_ft_connect(ipsec, rx, &attr); return 0; err_pol_miss: -- cgit From 1762f132d54200ffa008e86f9f6c96ab4ee3fb71 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:16 +0300 Subject: net/mlx5e: Support IPsec packet offload for RX in switchdev mode As decryption must be done first, add new prio for IPsec offload in FDB, and put it just lower than BYPASS prio and higher than TC prio. Three levels are added for RX. The first one is for ip xfrm policy. SA table is created in the second level for ip xfrm state. The status table is created in the last to check the decryption result. If success, packets continue with the next process, or dropped otherwise. For now, the set of reg c1 is removed for swtichdev mode, and the datapath process will be added in the next patch. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/c91063554cf643fb50b99cf093e8a9bf11729de5.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 4 + .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 41 ++++- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 80 ++++----- .../mellanox/mlx5/core/en_accel/ipsec_offload.c | 5 +- .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 184 +++++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h | 39 +++++ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 6 + 7 files changed, 312 insertions(+), 47 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 35f00700a4d6..63a2f2bb80a6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -75,6 +75,10 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \ esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \ esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o +ifneq ($(CONFIG_MLX5_EN_IPSEC),) + mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/ipsec_fs.o +endif + mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \ en/rep/bridge.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index 03d83cdf1e20..578af9d7aef3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -143,7 +143,7 @@ struct mlx5e_ipsec_sw_stats { atomic64_t ipsec_tx_drop_trailer; }; -struct mlx5e_ipsec_rx; +struct mlx5e_ipsec_fc; struct mlx5e_ipsec_tx; struct mlx5e_ipsec_work { @@ -180,6 +180,38 @@ struct mlx5e_ipsec_rx_create_attr { enum mlx5_flow_namespace_type chains_ns; }; +struct mlx5e_ipsec_ft { + struct mutex mutex; /* Protect changes to this struct */ + struct mlx5_flow_table *pol; + struct mlx5_flow_table *sa; + struct mlx5_flow_table *status; + u32 refcnt; +}; + +struct mlx5e_ipsec_rule { + struct mlx5_flow_handle *rule; + struct mlx5_modify_hdr *modify_hdr; + struct mlx5_pkt_reformat *pkt_reformat; + struct mlx5_fc *fc; +}; + +struct mlx5e_ipsec_miss { + struct mlx5_flow_group *group; + struct mlx5_flow_handle *rule; +}; + +struct mlx5e_ipsec_rx { + struct mlx5e_ipsec_ft ft; + struct mlx5e_ipsec_miss pol; + struct mlx5e_ipsec_miss sa; + struct mlx5e_ipsec_rule status; + struct mlx5e_ipsec_miss status_drop; + struct mlx5_fc *status_drop_cnt; + struct mlx5e_ipsec_fc *fc; + struct mlx5_fs_chains *chains; + u8 allow_tunnel_mode : 1; +}; + struct mlx5e_ipsec { struct mlx5_core_dev *mdev; struct xarray sadb; @@ -205,13 +237,6 @@ struct mlx5e_ipsec_esn_state { u8 overlap: 1; }; -struct mlx5e_ipsec_rule { - struct mlx5_flow_handle *rule; - struct mlx5_modify_hdr *modify_hdr; - struct mlx5_pkt_reformat *pkt_reformat; - struct mlx5_fc *fc; -}; - struct mlx5e_ipsec_limits { u64 round; u8 soft_limit_hit : 1; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 52e382948c13..2db16e49abc1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -9,6 +9,7 @@ #include "fs_core.h" #include "lib/ipsec_fs_roce.h" #include "lib/fs_chains.h" +#include "esw/ipsec_fs.h" #define NUM_IPSEC_FTE BIT(15) #define MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE 16 @@ -19,29 +20,6 @@ struct mlx5e_ipsec_fc { struct mlx5_fc *drop; }; -struct mlx5e_ipsec_ft { - struct mutex mutex; /* Protect changes to this struct */ - struct mlx5_flow_table *pol; - struct mlx5_flow_table *sa; - struct mlx5_flow_table *status; - u32 refcnt; -}; - -struct mlx5e_ipsec_miss { - struct mlx5_flow_group *group; - struct mlx5_flow_handle *rule; -}; - -struct mlx5e_ipsec_rx { - struct mlx5e_ipsec_ft ft; - struct mlx5e_ipsec_miss pol; - struct mlx5e_ipsec_miss sa; - struct mlx5e_ipsec_rule status; - struct mlx5e_ipsec_fc *fc; - struct mlx5_fs_chains *chains; - u8 allow_tunnel_mode : 1; -}; - struct mlx5e_ipsec_tx { struct mlx5e_ipsec_ft ft; struct mlx5e_ipsec_miss pol; @@ -259,9 +237,9 @@ static void ipsec_rx_ft_disconnect(struct mlx5e_ipsec *ipsec, u32 family) static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, u32 family) { - /* disconnect */ - ipsec_rx_ft_disconnect(ipsec, family); + if (rx != ipsec->rx_esw) + ipsec_rx_ft_disconnect(ipsec, family); if (rx->chains) { ipsec_chains_destroy(rx->chains); @@ -276,8 +254,12 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, mlx5_destroy_flow_table(rx->ft.sa); if (rx->allow_tunnel_mode) mlx5_eswitch_unblock_encap(mdev); - mlx5_del_flow_rules(rx->status.rule); - mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); + if (rx == ipsec->rx_esw) { + mlx5_esw_ipsec_rx_status_destroy(ipsec, rx); + } else { + mlx5_del_flow_rules(rx->status.rule); + mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); + } mlx5_destroy_flow_table(rx->ft.status); mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family); @@ -288,6 +270,13 @@ static void ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, u32 family, struct mlx5e_ipsec_rx_create_attr *attr) { + if (rx == ipsec->rx_esw) { + /* For packet offload in switchdev mode, RX & TX use FDB namespace */ + attr->ns = ipsec->tx_esw->ns; + mlx5_esw_ipsec_rx_create_attr_set(ipsec, attr); + return; + } + attr->ns = mlx5e_fs_get_ns(ipsec->fs, false); attr->ttc = mlx5e_fs_get_ttc(ipsec->fs, false); attr->family = family; @@ -306,6 +295,9 @@ static int ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, struct mlx5_flow_table *ft; int err; + if (rx == ipsec->rx_esw) + return mlx5_esw_ipsec_rx_status_pass_dest_get(ipsec, dest); + *dest = mlx5_ttc_get_default_dest(attr->ttc, family2tt(attr->family)); err = mlx5_ipsec_fs_roce_rx_create(ipsec->mdev, ipsec->roce, attr->ns, dest, attr->family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, @@ -357,7 +349,10 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; dest[1].counter_id = mlx5_fc_id(rx->fc->cnt); - err = ipsec_status_rule(mdev, rx, dest); + if (rx == ipsec->rx_esw) + err = mlx5_esw_ipsec_rx_status_create(ipsec, rx, dest); + else + err = ipsec_status_rule(mdev, rx, dest); if (err) goto err_add; @@ -406,7 +401,8 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, connect: /* connect */ - ipsec_rx_ft_connect(ipsec, rx, &attr); + if (rx != ipsec->rx_esw) + ipsec_rx_ft_connect(ipsec, rx, &attr); return 0; err_pol_miss: @@ -864,18 +860,22 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp } } -static enum mlx5_flow_namespace_type ipsec_fs_get_ns(struct mlx5e_ipsec *ipsec, u8 dir) +static enum mlx5_flow_namespace_type ipsec_fs_get_ns(struct mlx5e_ipsec *ipsec, + int type, u8 dir) { + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) + return MLX5_FLOW_NAMESPACE_FDB; + if (dir == XFRM_DEV_OFFLOAD_IN) return MLX5_FLOW_NAMESPACE_KERNEL; return MLX5_FLOW_NAMESPACE_EGRESS; } -static int setup_modify_header(struct mlx5e_ipsec *ipsec, u32 val, u8 dir, +static int setup_modify_header(struct mlx5e_ipsec *ipsec, int type, u32 val, u8 dir, struct mlx5_flow_act *flow_act) { - enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, dir); + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, type, dir); u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; struct mlx5_core_dev *mdev = ipsec->mdev; struct mlx5_modify_hdr *modify_hdr; @@ -1085,7 +1085,8 @@ static int setup_pkt_reformat(struct mlx5e_ipsec *ipsec, struct mlx5_accel_esp_xfrm_attrs *attrs, struct mlx5_flow_act *flow_act) { - enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, attrs->dir); + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, attrs->type, + attrs->dir); struct mlx5_pkt_reformat_params reformat_params = {}; struct mlx5_core_dev *mdev = ipsec->mdev; struct mlx5_pkt_reformat *pkt_reformat; @@ -1127,7 +1128,7 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) struct mlx5_flow_spec *spec; struct mlx5e_ipsec_rx *rx; struct mlx5_fc *counter; - int err; + int err = 0; rx = rx_ft_get(mdev, ipsec, attrs->family, attrs->type); if (IS_ERR(rx)) @@ -1148,8 +1149,10 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) setup_fte_esp(spec); setup_fte_no_frags(spec); - err = setup_modify_header(ipsec, sa_entry->ipsec_obj_id | BIT(31), - XFRM_DEV_OFFLOAD_IN, &flow_act); + if (rx != ipsec->rx_esw) + err = setup_modify_header(ipsec, attrs->type, + sa_entry->ipsec_obj_id | BIT(31), + XFRM_DEV_OFFLOAD_IN, &flow_act); if (err) goto err_mod_header; @@ -1340,7 +1343,7 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) if (!attrs->reqid) break; - err = setup_modify_header(ipsec, attrs->reqid, + err = setup_modify_header(ipsec, attrs->type, attrs->reqid, XFRM_DEV_OFFLOAD_OUT, &flow_act); if (err) goto err_mod_header; @@ -1388,6 +1391,7 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) { struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); + struct mlx5e_ipsec *ipsec = pol_entry->ipsec; struct mlx5_flow_destination dest[2]; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_handle *rule; @@ -1433,6 +1437,8 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) } flow_act.flags |= FLOW_ACT_NO_APPEND; + if (rx == ipsec->rx_esw && rx->chains) + flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[dstn].ft = rx->ft.sa; dstn++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index 5ff06263c5bd..3245d1c9d539 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -45,8 +45,9 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; - if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && - MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) + if ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || + MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level)) caps |= MLX5_IPSEC_CAP_PRIO; if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c new file mode 100644 index 000000000000..7df7a8b0a6a0 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +#include "fs_core.h" +#include "eswitch.h" +#include "en_accel/ipsec.h" +#include "esw/ipsec_fs.h" + +enum { + MLX5_ESW_IPSEC_RX_POL_FT_LEVEL, + MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL, + MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL, +}; + +static void esw_ipsec_rx_status_drop_destroy(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx) +{ + mlx5_del_flow_rules(rx->status_drop.rule); + mlx5_destroy_flow_group(rx->status_drop.group); + mlx5_fc_destroy(ipsec->mdev, rx->status_drop_cnt); +} + +static void esw_ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx) +{ + mlx5_del_flow_rules(rx->status.rule); + mlx5_chains_put_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0); +} + +static int esw_ipsec_rx_status_drop_create(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx) +{ + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); + struct mlx5_flow_table *ft = rx->ft.status; + struct mlx5_core_dev *mdev = ipsec->mdev; + struct mlx5_flow_destination dest = {}; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *rule; + struct mlx5_fc *flow_counter; + struct mlx5_flow_spec *spec; + struct mlx5_flow_group *g; + u32 *flow_group_in; + int err = 0; + + flow_group_in = kvzalloc(inlen, GFP_KERNEL); + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!flow_group_in || !spec) { + err = -ENOMEM; + goto err_out; + } + + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1); + g = mlx5_create_flow_group(ft, flow_group_in); + if (IS_ERR(g)) { + err = PTR_ERR(g); + mlx5_core_err(mdev, + "Failed to add ipsec rx status drop flow group, err=%d\n", err); + goto err_out; + } + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + err = PTR_ERR(flow_counter); + mlx5_core_err(mdev, + "Failed to add ipsec rx status drop rule counter, err=%d\n", err); + goto err_cnt; + } + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest.counter_id = mlx5_fc_id(flow_counter); + spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK; + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + mlx5_core_err(mdev, + "Failed to add ipsec rx status drop rule, err=%d\n", err); + goto err_rule; + } + + rx->status_drop.group = g; + rx->status_drop.rule = rule; + rx->status_drop_cnt = flow_counter; + + kvfree(flow_group_in); + kvfree(spec); + return 0; + +err_rule: + mlx5_fc_destroy(mdev, flow_counter); +err_cnt: + mlx5_destroy_flow_group(g); +err_out: + kvfree(flow_group_in); + kvfree(spec); + return err; +} + +static int esw_ipsec_rx_status_pass_create(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5_flow_destination *dest) +{ + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + int err; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + misc_parameters_2.ipsec_syndrome); + MLX5_SET(fte_match_param, spec->match_value, + misc_parameters_2.ipsec_syndrome, 0); + spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK; + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; + flow_act.flags = FLOW_ACT_NO_APPEND; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + rule = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + mlx5_core_warn(ipsec->mdev, + "Failed to add ipsec rx status pass rule, err=%d\n", err); + goto err_rule; + } + + rx->status.rule = rule; + kvfree(spec); + return 0; + +err_rule: + kvfree(spec); + return err; +} + +void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx) +{ + esw_ipsec_rx_status_pass_destroy(ipsec, rx); + esw_ipsec_rx_status_drop_destroy(ipsec, rx); +} + +int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5_flow_destination *dest) +{ + int err; + + err = esw_ipsec_rx_status_drop_create(ipsec, rx); + if (err) + return err; + + err = esw_ipsec_rx_status_pass_create(ipsec, rx, dest); + if (err) + goto err_pass_create; + + return 0; + +err_pass_create: + esw_ipsec_rx_status_drop_destroy(ipsec, rx); + return err; +} + +void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx_create_attr *attr) +{ + attr->prio = FDB_CRYPTO_INGRESS; + attr->pol_level = MLX5_ESW_IPSEC_RX_POL_FT_LEVEL; + attr->sa_level = MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL; + attr->status_level = MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL; + attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB; +} + +int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, + struct mlx5_flow_destination *dest) +{ + dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest->ft = mlx5_chains_get_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0); + + return 0; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h new file mode 100644 index 000000000000..1d6104648d32 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#ifndef __MLX5_ESW_IPSEC_FS_H__ +#define __MLX5_ESW_IPSEC_FS_H__ + +struct mlx5e_ipsec; + +#ifdef CONFIG_MLX5_ESWITCH +void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx); +int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5_flow_destination *dest); +void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx_create_attr *attr); +int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, + struct mlx5_flow_destination *dest); +#else +static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx) {} + +static inline int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx *rx, + struct mlx5_flow_destination *dest) +{ + return -EINVAL; +} + +static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx_create_attr *attr) {} + +static inline int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, + struct mlx5_flow_destination *dest) +{ + return -EINVAL; +} +#endif /* CONFIG_MLX5_ESWITCH */ +#endif /* __MLX5_ESW_IPSEC_FS_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 4ef04aa28771..8ae1854d6b73 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -2987,6 +2987,12 @@ static int init_fdb_root_ns(struct mlx5_flow_steering *steering) if (err) goto out_err; + maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_CRYPTO_INGRESS, 3); + if (IS_ERR(maj_prio)) { + err = PTR_ERR(maj_prio); + goto out_err; + } + err = create_fdb_fast_path(steering); if (err) goto out_err; -- cgit From 91bafc638ed4128eaca074fe7e88a5444db14325 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:17 +0300 Subject: net/mlx5e: Handle IPsec offload for RX datapath in switchdev mode Reuse tun opts bits in reg c1, to pass IPsec obj id to datapath. As this is only for RX SA and there are only 11 bits, xarray is used to map IPsec obj id to an index, which is between 1 and 0x7ff, and replace obj id to write to reg c1. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/43d60fbcc9cd672a97d7e2a2f7fe6a3d9e9a776d.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlx5/core/en/rep/tc.c | 17 +++++- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 2 + .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 7 +++ .../mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 22 +++++++ .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h | 2 + .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 69 ++++++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h | 20 +++++++ 7 files changed, 136 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c index b5c773ffc763..b12fe3c5a258 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c @@ -715,9 +715,20 @@ void mlx5e_rep_tc_receive(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, uplink_priv = &uplink_rpriv->uplink_priv; ct_priv = uplink_priv->ct_priv; - if (!mlx5_ipsec_is_rx_flow(cqe) && - !mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, zone_restore_id, tunnel_id, - &tc_priv)) +#ifdef CONFIG_MLX5_EN_IPSEC + if (!(tunnel_id >> ESW_TUN_OPTS_BITS)) { + u32 mapped_id; + u32 metadata; + + mapped_id = tunnel_id & ESW_IPSEC_RX_MAPPED_ID_MASK; + if (mapped_id && + !mlx5_esw_ipsec_rx_make_metadata(priv, mapped_id, &metadata)) + mlx5e_ipsec_offload_handle_rx_skb(priv->netdev, skb, metadata); + } +#endif + + if (!mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, + zone_restore_id, tunnel_id, &tc_priv)) goto free_skb; forward: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index 578af9d7aef3..168b9600bde3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -210,6 +210,7 @@ struct mlx5e_ipsec_rx { struct mlx5e_ipsec_fc *fc; struct mlx5_fs_chains *chains; u8 allow_tunnel_mode : 1; + struct xarray ipsec_obj_id_map; }; struct mlx5e_ipsec { @@ -256,6 +257,7 @@ struct mlx5e_ipsec_sa_entry { struct mlx5e_ipsec_work *work; struct mlx5e_ipsec_dwork *dwork; struct mlx5e_ipsec_limits limits; + u32 rx_mapped_id; }; struct mlx5_accel_pol_xfrm_attrs { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 2db16e49abc1..84322e85cd23 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -1153,6 +1153,9 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) err = setup_modify_header(ipsec, attrs->type, sa_entry->ipsec_obj_id | BIT(31), XFRM_DEV_OFFLOAD_IN, &flow_act); + else + err = mlx5_esw_ipsec_rx_setup_modify_header(sa_entry, &flow_act); + if (err) goto err_mod_header; @@ -1641,6 +1644,7 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) } mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); + mlx5_esw_ipsec_rx_id_mapping_remove(sa_entry); rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family, sa_entry->attrs.type); } @@ -1693,6 +1697,8 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) kfree(ipsec->rx_ipv6); if (ipsec->is_uplink_rep) { + xa_destroy(&ipsec->rx_esw->ipsec_obj_id_map); + mutex_destroy(&ipsec->tx_esw->ft.mutex); WARN_ON(ipsec->tx_esw->ft.refcnt); kfree(ipsec->tx_esw); @@ -1753,6 +1759,7 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) mutex_init(&ipsec->tx_esw->ft.mutex); mutex_init(&ipsec->rx_esw->ft.mutex); ipsec->tx_esw->ns = ns_esw; + xa_init_flags(&ipsec->rx_esw->ipsec_obj_id_map, XA_FLAGS_ALLOC1); } else if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) { ipsec->roce = mlx5_ipsec_fs_roce_init(mdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c index 8d6379ac4574..c00fe0d5ea11 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c @@ -37,6 +37,7 @@ #include "ipsec.h" #include "ipsec_rxtx.h" #include "en.h" +#include "esw/ipsec_fs.h" enum { MLX5E_IPSEC_TX_SYNDROME_OFFLOAD = 0x8, @@ -355,3 +356,24 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_syndrome); } } + +int mlx5_esw_ipsec_rx_make_metadata(struct mlx5e_priv *priv, u32 id, u32 *metadata) +{ + struct mlx5e_ipsec *ipsec = priv->ipsec; + u32 ipsec_obj_id; + int err; + + if (!ipsec || !ipsec->is_uplink_rep) + return -EINVAL; + + err = mlx5_esw_ipsec_rx_ipsec_obj_id_search(priv, id, &ipsec_obj_id); + if (err) { + atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_sadb_miss); + return err; + } + + *metadata = MLX5_IPSEC_METADATA_CREATE(ipsec_obj_id, + MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_DECRYPTED); + + return 0; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h index 436e9a8a32d3..9ee014a8ad24 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h @@ -43,6 +43,7 @@ #define MLX5_IPSEC_METADATA_MARKER(metadata) (((metadata) >> 31) & 0x1) #define MLX5_IPSEC_METADATA_SYNDROM(metadata) (((metadata) >> 24) & GENMASK(5, 0)) #define MLX5_IPSEC_METADATA_HANDLE(metadata) ((metadata) & GENMASK(23, 0)) +#define MLX5_IPSEC_METADATA_CREATE(id, syndrome) ((id) | ((syndrome) << 24)) struct mlx5e_accel_tx_ipsec_state { struct xfrm_offload *xo; @@ -67,6 +68,7 @@ void mlx5e_ipsec_handle_tx_wqe(struct mlx5e_tx_wqe *wqe, void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, u32 ipsec_meta_data); +int mlx5_esw_ipsec_rx_make_metadata(struct mlx5e_priv *priv, u32 id, u32 *metadata); static inline unsigned int mlx5e_ipsec_tx_ids_len(struct mlx5e_accel_tx_ipsec_state *ipsec_st) { return ipsec_st->tailen; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c index 7df7a8b0a6a0..0675587c1a79 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -182,3 +182,72 @@ int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, return 0; } + +int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_act *flow_act) +{ + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; + struct mlx5_core_dev *mdev = ipsec->mdev; + struct mlx5_modify_hdr *modify_hdr; + u32 mapped_id; + int err; + + err = xa_alloc_bh(&ipsec->rx_esw->ipsec_obj_id_map, &mapped_id, + xa_mk_value(sa_entry->ipsec_obj_id), + XA_LIMIT(1, ESW_IPSEC_RX_MAPPED_ID_MASK), 0); + if (err) + return err; + + /* reuse tunnel bits for ipsec, + * tun_id is always 0 and tun_opts is mapped to ipsec_obj_id. + */ + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); + MLX5_SET(set_action_in, action, field, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_1); + MLX5_SET(set_action_in, action, offset, ESW_ZONE_ID_BITS); + MLX5_SET(set_action_in, action, length, + ESW_TUN_ID_BITS + ESW_TUN_OPTS_BITS); + MLX5_SET(set_action_in, action, data, mapped_id); + + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_FDB, + 1, action); + if (IS_ERR(modify_hdr)) { + err = PTR_ERR(modify_hdr); + goto err_header_alloc; + } + + sa_entry->rx_mapped_id = mapped_id; + flow_act->modify_hdr = modify_hdr; + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + + return 0; + +err_header_alloc: + xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, mapped_id); + return err; +} + +void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) +{ + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; + + if (sa_entry->rx_mapped_id) + xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, + sa_entry->rx_mapped_id); +} + +int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, + u32 *ipsec_obj_id) +{ + struct mlx5e_ipsec *ipsec = priv->ipsec; + void *val; + + val = xa_load(&ipsec->rx_esw->ipsec_obj_id_map, id); + if (!val) + return -ENOENT; + + *ipsec_obj_id = xa_to_value(val); + + return 0; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h index 1d6104648d32..44df34032d1e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h @@ -5,6 +5,7 @@ #define __MLX5_ESW_IPSEC_FS_H__ struct mlx5e_ipsec; +struct mlx5e_ipsec_sa_entry; #ifdef CONFIG_MLX5_ESWITCH void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, @@ -16,6 +17,11 @@ void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx_create_attr *attr); int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, struct mlx5_flow_destination *dest); +int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_act *flow_act); +void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry); +int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, + u32 *ipsec_obj_id); #else static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx) {} @@ -35,5 +41,19 @@ static inline int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ips { return -EINVAL; } + +static inline int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_act *flow_act) +{ + return -EINVAL; +} + +static inline void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) {} + +static inline int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, + u32 *ipsec_obj_id) +{ + return -EINVAL; +} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESW_IPSEC_FS_H__ */ -- cgit From f46e92d664fb6a3751e90812419decf5e178e06a Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:18 +0300 Subject: net/mlx5e: Refactor IPsec TX tables creation Add attribute for IPsec TX creation, pass all needed parameters in it, so tx_create() can be used by eswitch. Signed-off-by: Jianbo Liu Reviewed-by: Leon Romanovsky Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/24d5ab988b0db2d39b7fde321b44ffe885d47828.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h | 8 +++++++ .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 26 +++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h index 168b9600bde3..9e7c42c2f77b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h @@ -213,6 +213,14 @@ struct mlx5e_ipsec_rx { struct xarray ipsec_obj_id_map; }; +struct mlx5e_ipsec_tx_create_attr { + int prio; + int pol_level; + int sa_level; + int cnt_level; + enum mlx5_flow_namespace_type chains_ns; +}; + struct mlx5e_ipsec { struct mlx5_core_dev *mdev; struct xarray sadb; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 84322e85cd23..6d4d2b824b75 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -569,15 +569,29 @@ static void tx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, mlx5_destroy_flow_table(tx->ft.status); } -static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, +static void ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx *tx, + struct mlx5e_ipsec_tx_create_attr *attr) +{ + attr->prio = 0; + attr->pol_level = 0; + attr->sa_level = 1; + attr->cnt_level = 2; + attr->chains_ns = MLX5_FLOW_NAMESPACE_EGRESS_IPSEC; +} + +static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, struct mlx5_ipsec_fs *roce) { + struct mlx5_core_dev *mdev = ipsec->mdev; + struct mlx5e_ipsec_tx_create_attr attr; struct mlx5_flow_destination dest = {}; struct mlx5_flow_table *ft; u32 flags = 0; int err; - ft = ipsec_ft_create(tx->ns, 2, 0, 1, 0); + ipsec_tx_create_attr_set(ipsec, tx, &attr); + ft = ipsec_ft_create(tx->ns, attr.cnt_level, attr.prio, 1, 0); if (IS_ERR(ft)) return PTR_ERR(ft); tx->ft.status = ft; @@ -590,7 +604,7 @@ static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (tx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - ft = ipsec_ft_create(tx->ns, 1, 0, 4, flags); + ft = ipsec_ft_create(tx->ns, attr.sa_level, attr.prio, 4, flags); if (IS_ERR(ft)) { err = PTR_ERR(ft); goto err_sa_ft; @@ -599,7 +613,7 @@ static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) { tx->chains = ipsec_chains_create( - mdev, tx->ft.sa, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC, 0, 0, + mdev, tx->ft.sa, attr.chains_ns, attr.prio, attr.pol_level, &tx->ft.pol); if (IS_ERR(tx->chains)) { err = PTR_ERR(tx->chains); @@ -609,7 +623,7 @@ static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, goto connect_roce; } - ft = ipsec_ft_create(tx->ns, 0, 0, 2, 0); + ft = ipsec_ft_create(tx->ns, attr.pol_level, attr.prio, 2, 0); if (IS_ERR(ft)) { err = PTR_ERR(ft); goto err_pol_ft; @@ -656,7 +670,7 @@ static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (tx->ft.refcnt) goto skip; - err = tx_create(mdev, tx, ipsec->roce); + err = tx_create(ipsec, tx, ipsec->roce); if (err) return err; -- cgit From c6c2bf5db4ea14b316af1fd03cc6c5c61f751f79 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:19 +0300 Subject: net/mlx5e: Support IPsec packet offload for TX in switchdev mode The IPsec encryption is done at the last, so add new prio for IPsec offload in FDB, and put it just lower than the slow path prio and higher than the per-vport prio. Three levels are added for TX. The first one is for ip xfrm policy. The sa table is created in the second level for ip xfrm state. The status table is created at the last to count the number of packets encrypted. The rules, which forward packets to uplink, are changed to forward them to IPsec TX tables first. These rules are restored after those tables are destroyed, which is done immediately when there is no reference to them, just as what does in legacy mode. The support for slow path is added here, by refreshing uplink's channels. But, the handling for TC fast path, which is more complicated, will be added later. Besides, reg c4 is used instead to match reqid. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/cfd0e6ffaf0b8c55ebaa9fb0649b7c504b6b8ec6.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 70 +++++++++++++++++++--- .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 16 +++++ .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h | 5 ++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 1 + .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 11 ++++ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 6 ++ 6 files changed, 100 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 6d4d2b824b75..36704c9fce33 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -10,6 +10,7 @@ #include "lib/ipsec_fs_roce.h" #include "lib/fs_chains.h" #include "esw/ipsec_fs.h" +#include "en_rep.h" #define NUM_IPSEC_FTE BIT(15) #define MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE 16 @@ -23,6 +24,7 @@ struct mlx5e_ipsec_fc { struct mlx5e_ipsec_tx { struct mlx5e_ipsec_ft ft; struct mlx5e_ipsec_miss pol; + struct mlx5e_ipsec_miss sa; struct mlx5e_ipsec_rule status; struct mlx5_flow_namespace *ns; struct mlx5e_ipsec_fc *fc; @@ -550,7 +552,7 @@ err_rule: } /* IPsec TX flow steering */ -static void tx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, +static void tx_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, struct mlx5_ipsec_fs *roce) { mlx5_ipsec_fs_roce_tx_destroy(roce); @@ -562,9 +564,13 @@ static void tx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, mlx5_destroy_flow_table(tx->ft.pol); } + if (tx == ipsec->tx_esw) { + mlx5_del_flow_rules(tx->sa.rule); + mlx5_destroy_flow_group(tx->sa.group); + } mlx5_destroy_flow_table(tx->ft.sa); if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); + mlx5_eswitch_unblock_encap(ipsec->mdev); mlx5_del_flow_rules(tx->status.rule); mlx5_destroy_flow_table(tx->ft.status); } @@ -573,6 +579,11 @@ static void ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, struct mlx5e_ipsec_tx_create_attr *attr) { + if (tx == ipsec->tx_esw) { + mlx5_esw_ipsec_tx_create_attr_set(ipsec, attr); + return; + } + attr->prio = 0; attr->pol_level = 0; attr->sa_level = 1; @@ -611,6 +622,15 @@ static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, } tx->ft.sa = ft; + if (tx == ipsec->tx_esw) { + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; + dest.vport.num = MLX5_VPORT_UPLINK; + err = ipsec_miss_create(mdev, tx->ft.sa, &tx->sa, &dest); + if (err) + goto err_sa_miss; + memset(&dest, 0, sizeof(dest)); + } + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) { tx->chains = ipsec_chains_create( mdev, tx->ft.sa, attr.chains_ns, attr.prio, attr.pol_level, @@ -652,6 +672,11 @@ err_roce: mlx5_destroy_flow_table(tx->ft.pol); } err_pol_ft: + if (tx == ipsec->tx_esw) { + mlx5_del_flow_rules(tx->sa.rule); + mlx5_destroy_flow_group(tx->sa.group); + } +err_sa_miss: mlx5_destroy_flow_table(tx->ft.sa); err_sa_ft: if (tx->allow_tunnel_mode) @@ -662,6 +687,25 @@ err_status_rule: return err; } +static void ipsec_esw_tx_ft_policy_set(struct mlx5_core_dev *mdev, + struct mlx5_flow_table *ft) +{ +#ifdef CONFIG_MLX5_ESWITCH + struct mlx5_eswitch *esw = mdev->priv.eswitch; + struct mlx5e_rep_priv *uplink_rpriv; + struct mlx5e_priv *priv; + + esw->offloads.ft_ipsec_tx_pol = ft; + uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); + priv = netdev_priv(uplink_rpriv->netdev); + if (!priv->channels.num) + return; + + mlx5e_rep_deactivate_channels(priv); + mlx5e_rep_activate_channels(priv); +#endif +} + static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) { @@ -674,6 +718,9 @@ static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (err) return err; + if (tx == ipsec->tx_esw) + ipsec_esw_tx_ft_policy_set(mdev, tx->ft.pol); + skip: tx->ft.refcnt++; return 0; @@ -684,7 +731,10 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) if (--tx->ft.refcnt) return; - tx_destroy(ipsec->mdev, tx, ipsec->roce); + if (tx == ipsec->tx_esw) + ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); + + tx_destroy(ipsec, tx, ipsec->roce); } static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, @@ -842,15 +892,15 @@ static void setup_fte_reg_a(struct mlx5_flow_spec *spec) misc_parameters_2.metadata_reg_a, MLX5_ETH_WQE_FT_META_IPSEC); } -static void setup_fte_reg_c0(struct mlx5_flow_spec *spec, u32 reqid) +static void setup_fte_reg_c4(struct mlx5_flow_spec *spec, u32 reqid) { /* Pass policy check before choosing this SA */ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; - MLX5_SET(fte_match_param, spec->match_criteria, - misc_parameters_2.metadata_reg_c_0, reqid); + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + misc_parameters_2.metadata_reg_c_4); MLX5_SET(fte_match_param, spec->match_value, - misc_parameters_2.metadata_reg_c_0, reqid); + misc_parameters_2.metadata_reg_c_4, reqid); } static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upspec *upspec) @@ -902,7 +952,7 @@ static int setup_modify_header(struct mlx5e_ipsec *ipsec, int type, u32 val, u8 break; case XFRM_DEV_OFFLOAD_OUT: MLX5_SET(set_action_in, action, field, - MLX5_ACTION_IN_FIELD_METADATA_REG_C_0); + MLX5_ACTION_IN_FIELD_METADATA_REG_C_4); break; default: return -EINVAL; @@ -1268,7 +1318,7 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) break; case XFRM_DEV_OFFLOAD_PACKET: if (attrs->reqid) - setup_fte_reg_c0(spec, attrs->reqid); + setup_fte_reg_c4(spec, attrs->reqid); err = setup_pkt_reformat(ipsec, attrs, &flow_act); if (err) goto err_pkt_reformat; @@ -1379,6 +1429,8 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) } flow_act.flags |= FLOW_ACT_NO_APPEND; + if (tx == ipsec->tx_esw && tx->chains) + flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; dest[dstn].ft = tx->ft.sa; dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dstn++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c index 0675587c1a79..e60cd3dc1b13 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -12,6 +12,12 @@ enum { MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL, }; +enum { + MLX5_ESW_IPSEC_TX_POL_FT_LEVEL, + MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL, + MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL, +}; + static void esw_ipsec_rx_status_drop_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx) { @@ -251,3 +257,13 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, return 0; } + +void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr) +{ + attr->prio = FDB_CRYPTO_EGRESS; + attr->pol_level = MLX5_ESW_IPSEC_TX_POL_FT_LEVEL; + attr->sa_level = MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL; + attr->cnt_level = MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL; + attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h index 44df34032d1e..275684f99ed3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h @@ -22,6 +22,8 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry); int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, u32 *ipsec_obj_id); +void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr); #else static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx) {} @@ -55,5 +57,8 @@ static inline int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, { return -EINVAL; } + +static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESW_IPSEC_FS_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 2944c9207487..c7b5faae20a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -254,6 +254,7 @@ struct mlx5_esw_offload { struct mlx5_flow_group *vport_rx_group; struct mlx5_flow_group *vport_rx_drop_group; struct mlx5_flow_handle *vport_rx_drop_rule; + struct mlx5_flow_table *ft_ipsec_tx_pol; struct xarray vport_reps; struct list_head peer_flows[MLX5_MAX_PORTS]; struct mutex peer_mutex; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index f83667b4339e..dc22a7f959e3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -884,6 +884,17 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw, dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + if (rep->vport == MLX5_VPORT_UPLINK && on_esw->offloads.ft_ipsec_tx_pol) { + dest.ft = on_esw->offloads.ft_ipsec_tx_pol; + flow_act.flags = FLOW_ACT_IGNORE_FLOW_LEVEL; + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + } else { + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; + dest.vport.num = rep->vport; + dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id); + dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; + } + if (MLX5_CAP_ESW_FLOWTABLE(on_esw->dev, flow_source) && rep->vport == MLX5_VPORT_UPLINK) spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 8ae1854d6b73..830ff8480fe1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -3015,6 +3015,12 @@ static int init_fdb_root_ns(struct mlx5_flow_steering *steering) goto out_err; } + maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_CRYPTO_EGRESS, 3); + if (IS_ERR(maj_prio)) { + err = PTR_ERR(maj_prio); + goto out_err; + } + /* We put this priority last, knowing that nothing will get here * unless explicitly forwarded to. This is possible because the * slow path tables have catch all rules and nothing gets passed -- cgit From 1632649d2dbd6353580273cc37dc269c02ce921f Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:20 +0300 Subject: net/mlx5: Compare with old_dest param to modify rule destination The rule destination must be compared with the old_dest passed in. Signed-off-by: Jianbo Liu Reviewed-by: Mark Bloch Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/24adc60d05d7492359ba343c6da1ebbe9fe284f6.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 830ff8480fe1..59df6156246e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1066,7 +1066,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle, } for (i = 0; i < handle->num_rules; i++) { - if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr)) + if (mlx5_flow_dests_cmp(old_dest, &handle->rule[i]->dest_attr)) return _mlx5_modify_rule_destination(handle->rule[i], new_dest); } -- cgit From 366e46242b8eebfa66cc0dbc85900115cbe6e167 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:21 +0300 Subject: net/mlx5e: Make IPsec offload work together with eswitch and TC The eswitch mode is not allowed to change if there are any IPsec rules. Besides, by using mlx5_esw_try_lock() to get eswitch mode lock, IPsec rules are not allowed to be offloaded if there are any TC rules. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/e442b512b21a931fbdfb87d57ae428c37badd58a.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 59 +++++++++++++----- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 14 +++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 70 ++++++++++++++++++++++ 3 files changed, 128 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 36704c9fce33..7eb926b527da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -254,8 +254,6 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, mlx5_del_flow_rules(rx->sa.rule); mlx5_destroy_flow_group(rx->sa.group); mlx5_destroy_flow_table(rx->ft.sa); - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); if (rx == ipsec->rx_esw) { mlx5_esw_ipsec_rx_status_destroy(ipsec, rx); } else { @@ -359,8 +357,6 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, goto err_add; /* Create FT */ - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (rx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(attr.ns, attr.sa_level, attr.prio, 2, flags); @@ -415,8 +411,6 @@ err_pol_ft: err_fs: mlx5_destroy_flow_table(rx->ft.sa); err_fs_ft: - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(rx->status.rule); mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); err_add: @@ -434,13 +428,26 @@ static int rx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (rx->ft.refcnt) goto skip; + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); + + err = mlx5_eswitch_block_mode_trylock(mdev); + if (err) + goto err_out; + err = rx_create(mdev, ipsec, rx, family); + mlx5_eswitch_block_mode_unlock(mdev, err); if (err) - return err; + goto err_out; skip: rx->ft.refcnt++; return 0; + +err_out: + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); + return err; } static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, @@ -449,7 +456,12 @@ static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, if (--rx->ft.refcnt) return; + mlx5_eswitch_unblock_mode_lock(ipsec->mdev); rx_destroy(ipsec->mdev, ipsec, rx, family); + mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); + + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(ipsec->mdev); } static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, @@ -569,8 +581,6 @@ static void tx_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, mlx5_destroy_flow_group(tx->sa.group); } mlx5_destroy_flow_table(tx->ft.sa); - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(ipsec->mdev); mlx5_del_flow_rules(tx->status.rule); mlx5_destroy_flow_table(tx->ft.status); } @@ -611,8 +621,6 @@ static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, if (err) goto err_status_rule; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (tx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(tx->ns, attr.sa_level, attr.prio, 4, flags); @@ -679,8 +687,6 @@ err_pol_ft: err_sa_miss: mlx5_destroy_flow_table(tx->ft.sa); err_sa_ft: - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(tx->status.rule); err_status_rule: mlx5_destroy_flow_table(tx->ft.status); @@ -714,16 +720,32 @@ static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (tx->ft.refcnt) goto skip; - err = tx_create(ipsec, tx, ipsec->roce); + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); + + err = mlx5_eswitch_block_mode_trylock(mdev); if (err) - return err; + goto err_out; + + err = tx_create(ipsec, tx, ipsec->roce); + if (err) { + mlx5_eswitch_block_mode_unlock(mdev, err); + goto err_out; + } if (tx == ipsec->tx_esw) ipsec_esw_tx_ft_policy_set(mdev, tx->ft.pol); + mlx5_eswitch_block_mode_unlock(mdev, err); + skip: tx->ft.refcnt++; return 0; + +err_out: + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); + return err; } static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) @@ -731,10 +753,17 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) if (--tx->ft.refcnt) return; + mlx5_eswitch_unblock_mode_lock(ipsec->mdev); + if (tx == ipsec->tx_esw) ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); tx_destroy(ipsec, tx, ipsec->roce); + + mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); + + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(ipsec->mdev); } static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index c7b5faae20a7..f4b52ab1ff07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -270,6 +270,7 @@ struct mlx5_esw_offload { u8 inline_mode; atomic64_t num_flows; u64 num_block_encap; + u64 num_block_mode; enum devlink_eswitch_encap_mode encap; struct ida vport_metadata_ida; unsigned int host_number; /* ECPF supports one external host */ @@ -784,6 +785,11 @@ int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev); void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev); +int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev); +void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err); +void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev); +void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev); + static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) { if (mlx5_esw_allowed(esw)) @@ -863,6 +869,14 @@ static inline bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev) static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) { } + +static inline int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) { return 0; } + +static inline void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) {} + +static inline void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) {} + +static inline void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESWITCH_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index dc22a7f959e3..6a7e1955eddf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3518,6 +3518,69 @@ static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink) return net_eq(devl_net, netdev_net); } +int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + struct mlx5_eswitch *esw; + int err; + + devl_lock(devlink); + esw = mlx5_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) { + /* Failure means no eswitch => not possible to change eswitch mode */ + devl_unlock(devlink); + return 0; + } + + err = mlx5_esw_try_lock(esw); + if (err < 0) { + devl_unlock(devlink); + return err; + } + + return 0; +} + +void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) +{ + struct devlink *devlink = priv_to_devlink(dev); + struct mlx5_eswitch *esw; + + esw = mlx5_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) + return; + + if (!err) + esw->offloads.num_block_mode++; + mlx5_esw_unlock(esw); + devl_unlock(devlink); +} + +void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + struct mlx5_eswitch *esw; + + esw = mlx5_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) + return; + + down_write(&esw->mode_lock); +} + +void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + struct mlx5_eswitch *esw; + + esw = mlx5_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) + return; + + esw->offloads.num_block_mode--; + up_write(&esw->mode_lock); +} + int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { @@ -3551,6 +3614,13 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, if (cur_mlx5_mode == mlx5_mode) goto unlock; + if (esw->offloads.num_block_mode) { + NL_SET_ERR_MSG_MOD(extack, + "Can't change eswitch mode when IPsec SA and/or policies are configured"); + err = -EOPNOTSUPP; + goto unlock; + } + mlx5_eswitch_disable_locked(esw); if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) { if (mlx5_devlink_trap_get_num_active(esw->dev)) { -- cgit From d1569537a837d66620aa7ffc2bddf918e902f227 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:22 +0300 Subject: net/mlx5e: Modify and restore TC rules for IPSec TX rules After IPsec policy/state TX rules are added, any TC flow rule, which forwards packets to uplink, is modified to forward to IPsec TX tables. As these tables are destroyed dynamically, whenever there is no reference to them, the destinations of this kind of rules must be restored to uplink. There is a special case for packet encapsulation, as the packet_reformat_id in the extended destination is used to reformat packets, but only for the VPORT destination. To forward packet to IPsec table and do encapsulation in one FTE, move the packet_reformat_id to flow context, instead of using the extended destination. As a limitation, multiple encapsulations with table forwarding, and one together with other VPORT destinations, are not allowed, so add a check when offloading TC rules. TC rules are not allowed before IPsec TX rule is added, so only need to restore TC rules after flush IPSec TX rules. As they are saved in the vport_rep rhashtables, we walk all the rules in the rhashtables, and find TC rules with destinations pointing to IPsec tables, and modify them one by one. To avoid concurrent issue, this handling is done under the protection of eswitch mode_lock. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/7bcb2c7e2ecf0e0d06b095c8dcc6a37ea7f02faf.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 4 +- .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 56 +++++++++++++ .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h | 3 + drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 + .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 93 +++++++++++++++++++++- 5 files changed, 154 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 7eb926b527da..f635b5f6e886 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -755,8 +755,10 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) mlx5_eswitch_unblock_mode_lock(ipsec->mdev); - if (tx == ipsec->tx_esw) + if (tx == ipsec->tx_esw) { + mlx5_esw_ipsec_restore_dest_uplink(ipsec->mdev); ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); + } tx_destroy(ipsec, tx, ipsec->roce); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c index e60cd3dc1b13..455746952260 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -5,6 +5,9 @@ #include "eswitch.h" #include "en_accel/ipsec.h" #include "esw/ipsec_fs.h" +#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) +#include "en/tc_priv.h" +#endif enum { MLX5_ESW_IPSEC_RX_POL_FT_LEVEL, @@ -267,3 +270,56 @@ void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, attr->cnt_level = MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL; attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB; } + +#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) +static int mlx5_esw_ipsec_modify_flow_dests(struct mlx5_eswitch *esw, + struct mlx5e_tc_flow *flow) +{ + struct mlx5_esw_flow_attr *esw_attr; + struct mlx5_flow_attr *attr; + int err; + + attr = flow->attr; + esw_attr = attr->esw_attr; + if (esw_attr->out_count - esw_attr->split_count > 1) + return 0; + + err = mlx5_eswitch_restore_ipsec_rule(esw, flow->rule[0], esw_attr, + esw_attr->out_count - 1); + + return err; +} +#endif + +void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) +{ +#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) + struct mlx5_eswitch *esw = mdev->priv.eswitch; + struct mlx5_eswitch_rep *rep; + struct mlx5e_rep_priv *rpriv; + struct rhashtable_iter iter; + struct mlx5e_tc_flow *flow; + unsigned long i; + int err; + + xa_for_each(&esw->offloads.vport_reps, i, rep) { + rpriv = rep->rep_data[REP_ETH].priv; + if (!rpriv || !rpriv->netdev) + continue; + + rhashtable_walk_enter(&rpriv->tc_ht, &iter); + rhashtable_walk_start(&iter); + while ((flow = rhashtable_walk_next(&iter)) != NULL) { + if (IS_ERR(flow)) + continue; + + err = mlx5_esw_ipsec_modify_flow_dests(esw, flow); + if (err) + mlx5_core_warn_once(mdev, + "Faided to modify flow dests for IPsec"); + } + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); + } +#endif +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h index 275684f99ed3..0c90f7a8b0d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h @@ -24,6 +24,7 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, u32 *ipsec_obj_id); void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx_create_attr *attr); +void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev); #else static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx) {} @@ -60,5 +61,7 @@ static inline int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx_create_attr *attr) {} + +static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESW_IPSEC_FS_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index f4b52ab1ff07..f3a6a1826e00 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -811,6 +811,8 @@ mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) return esw->fdb_table.offloads.slow_fdb; } +int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, + struct mlx5_esw_flow_attr *esw_attr, int attr_idx); #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 6a7e1955eddf..d3bcb632dd44 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -424,10 +424,51 @@ esw_cleanup_chain_dest(struct mlx5_fs_chains *chains, u32 chain, u32 prio, u32 l mlx5_chains_put_table(chains, chain, prio, level); } +static bool esw_same_vhca_id(struct mlx5_core_dev *mdev1, struct mlx5_core_dev *mdev2) +{ + return MLX5_CAP_GEN(mdev1, vhca_id) == MLX5_CAP_GEN(mdev2, vhca_id); +} + +static bool esw_setup_uplink_fwd_ipsec_needed(struct mlx5_eswitch *esw, + struct mlx5_esw_flow_attr *esw_attr, + int attr_idx) +{ + if (esw->offloads.ft_ipsec_tx_pol && + esw_attr->dests[attr_idx].rep && + esw_attr->dests[attr_idx].rep->vport == MLX5_VPORT_UPLINK && + /* To be aligned with software, encryption is needed only for tunnel device */ + (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP_VALID) && + esw_attr->dests[attr_idx].rep != esw_attr->in_rep && + esw_same_vhca_id(esw_attr->dests[attr_idx].mdev, esw->dev)) + return true; + + return false; +} + +static bool esw_flow_dests_fwd_ipsec_check(struct mlx5_eswitch *esw, + struct mlx5_esw_flow_attr *esw_attr) +{ + int i; + + if (!esw->offloads.ft_ipsec_tx_pol) + return true; + + for (i = 0; i < esw_attr->split_count; i++) + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, i)) + return false; + + for (i = esw_attr->split_count; i < esw_attr->out_count; i++) + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, i) && + (esw_attr->out_count - esw_attr->split_count > 1)) + return false; + + return true; +} + static void -esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, - struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, - int attr_idx, int dest_idx, bool pkt_reformat) +esw_setup_dest_fwd_vport(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, + int attr_idx, int dest_idx, bool pkt_reformat) { dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest[dest_idx].vport.num = esw_attr->dests[attr_idx].rep->vport; @@ -449,6 +490,33 @@ esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *f } } +static void +esw_setup_dest_fwd_ipsec(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, + int attr_idx, int dest_idx, bool pkt_reformat) +{ + dest[dest_idx].ft = esw->offloads.ft_ipsec_tx_pol; + dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + if (pkt_reformat && + esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP_VALID) { + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + flow_act->pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat; + } +} + +static void +esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, + int attr_idx, int dest_idx, bool pkt_reformat) +{ + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, attr_idx)) + esw_setup_dest_fwd_ipsec(dest, flow_act, esw, esw_attr, + attr_idx, dest_idx, pkt_reformat); + else + esw_setup_dest_fwd_vport(dest, flow_act, esw, esw_attr, + attr_idx, dest_idx, pkt_reformat); +} + static int esw_setup_vport_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, @@ -575,6 +643,9 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1)) return ERR_PTR(-EOPNOTSUPP); + if (!esw_flow_dests_fwd_ipsec_check(esw, esw_attr)) + return ERR_PTR(-EOPNOTSUPP); + dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL); if (!dest) return ERR_PTR(-ENOMEM); @@ -4374,3 +4445,19 @@ out: mutex_unlock(&esw->state_lock); return err; } + +int +mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, + struct mlx5_esw_flow_attr *esw_attr, int attr_idx) +{ + struct mlx5_flow_destination new_dest = {}; + struct mlx5_flow_destination old_dest = {}; + + if (!esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, attr_idx)) + return 0; + + esw_setup_dest_fwd_ipsec(&old_dest, NULL, esw, esw_attr, attr_idx, 0, false); + esw_setup_dest_fwd_vport(&new_dest, NULL, esw, esw_attr, attr_idx, 0, false); + + return mlx5_modify_rule_destination(rule, &new_dest, &old_dest); +} -- cgit From 6e56ab1c90593630d5e8799831e9dea4850128ea Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:23 +0300 Subject: net/mlx5e: Add get IPsec offload stats for uplink representor As IPsec offload is supported in switchdev mode, HW stats can be can be obtained from uplink rep. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/b43c91c452f1db9c35c10639a029aa10fd8b7895.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index ca4f57f5064f..d2fed9615804 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1338,6 +1338,7 @@ static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = { &MLX5E_STATS_GRP(channels), &MLX5E_STATS_GRP(per_port_buff_congest), #ifdef CONFIG_MLX5_EN_IPSEC + &MLX5E_STATS_GRP(ipsec_hw), &MLX5E_STATS_GRP(ipsec_sw), #endif &MLX5E_STATS_GRP(ptp), -- cgit From c8e350e62fc51f3fda28f166fc402f4fb539f528 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Mon, 31 Jul 2023 14:28:24 +0300 Subject: net/mlx5e: Make TC and IPsec offloads mutually exclusive on a netdev For IPsec packet offload mode, the order of TC offload and IPsec offload on the same netdevice is not aligned with the order in the non-offload software. For example, for RX, the software performs TC first and then IPsec transformation, but the implementation for offload does that in the opposite way. To resolve the difference for now, either IPsec offload or TC offload, not both, is allowed for a specific interface. Signed-off-by: Jianbo Liu Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/8e2e5e3b0984d785066e8663aaf97b3ba1bb873f.1690802064.git.leon@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 84 ++++++++++++++++++++-- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 47 ++++++++++++ 2 files changed, 127 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index f635b5f6e886..9a5b67344277 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -1717,12 +1717,68 @@ void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv, void *ipsec_stats) } } +#ifdef CONFIG_MLX5_ESWITCH +static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev) +{ + struct mlx5_eswitch *esw = mdev->priv.eswitch; + int err = 0; + + if (esw) + down_write(&esw->mode_lock); + + if (mdev->num_block_ipsec) { + err = -EBUSY; + goto unlock; + } + + mdev->num_block_tc++; + +unlock: + if (esw) + up_write(&esw->mode_lock); + + return err; +} +#else +static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev) +{ + if (mdev->num_block_ipsec) + return -EBUSY; + + mdev->num_block_tc++; + return 0; +} +#endif + +static void mlx5e_ipsec_unblock_tc_offload(struct mlx5_core_dev *mdev) +{ + mdev->num_block_tc++; +} + int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) { + int err; + + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) { + err = mlx5e_ipsec_block_tc_offload(sa_entry->ipsec->mdev); + if (err) + return err; + } + if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) - return tx_add_rule(sa_entry); + err = tx_add_rule(sa_entry); + else + err = rx_add_rule(sa_entry); + + if (err) + goto err_out; + + return 0; - return rx_add_rule(sa_entry); +err_out: + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) + mlx5e_ipsec_unblock_tc_offload(sa_entry->ipsec->mdev); + return err; } void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) @@ -1735,6 +1791,9 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) if (ipsec_rule->pkt_reformat) mlx5_packet_reformat_dealloc(mdev, ipsec_rule->pkt_reformat); + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) + mlx5e_ipsec_unblock_tc_offload(mdev); + if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) { tx_ft_put(sa_entry->ipsec, sa_entry->attrs.type); return; @@ -1747,10 +1806,25 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry) { + int err; + + err = mlx5e_ipsec_block_tc_offload(pol_entry->ipsec->mdev); + if (err) + return err; + if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) - return tx_add_policy(pol_entry); + err = tx_add_policy(pol_entry); + else + err = rx_add_policy(pol_entry); + + if (err) + goto err_out; + + return 0; - return rx_add_policy(pol_entry); +err_out: + mlx5e_ipsec_unblock_tc_offload(pol_entry->ipsec->mdev); + return err; } void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry) @@ -1760,6 +1834,8 @@ void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry) mlx5_del_flow_rules(ipsec_rule->rule); + mlx5e_ipsec_unblock_tc_offload(pol_entry->ipsec->mdev); + if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) { rx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.family, pol_entry->attrs.prio, pol_entry->attrs.type); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index dfd282319753..7d2a029e0932 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4606,6 +4606,46 @@ static bool is_flow_rule_duplicate_allowed(struct net_device *dev, return netif_is_lag_port(dev) && rpriv && rpriv->rep->vport != MLX5_VPORT_UPLINK; } +/* As IPsec and TC order is not aligned between software and hardware-offload, + * either IPsec offload or TC offload, not both, is allowed for a specific interface. + */ +static bool is_tc_ipsec_order_check_needed(struct net_device *filter, struct mlx5e_priv *priv) +{ + if (!IS_ENABLED(CONFIG_MLX5_EN_IPSEC)) + return false; + + if (filter != priv->netdev) + return false; + + if (mlx5e_eswitch_vf_rep(priv->netdev)) + return false; + + return true; +} + +static int mlx5e_tc_block_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + + if (!is_tc_ipsec_order_check_needed(filter, priv)) + return 0; + + if (mdev->num_block_tc) + return -EBUSY; + + mdev->num_block_ipsec++; + + return 0; +} + +static void mlx5e_tc_unblock_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) +{ + if (!is_tc_ipsec_order_check_needed(filter, priv)) + return; + + priv->mdev->num_block_ipsec--; +} + int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, struct flow_cls_offload *f, unsigned long flags) { @@ -4618,6 +4658,10 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, if (!mlx5_esw_hold(priv->mdev)) return -EBUSY; + err = mlx5e_tc_block_ipsec_offload(dev, priv); + if (err) + goto esw_release; + mlx5_esw_get(priv->mdev); rcu_read_lock(); @@ -4663,7 +4707,9 @@ rcu_unlock: err_free: mlx5e_flow_put(priv, flow); out: + mlx5e_tc_unblock_ipsec_offload(dev, priv); mlx5_esw_put(priv->mdev); +esw_release: mlx5_esw_release(priv->mdev); return err; } @@ -4704,6 +4750,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, trace_mlx5e_delete_flower(f); mlx5e_flow_put(priv, flow); + mlx5e_tc_unblock_ipsec_offload(dev, priv); mlx5_esw_put(priv->mdev); return 0; -- cgit From ce7c7fef147311d0675aa8351ff72e0be1d5b3eb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 1 Aug 2023 20:52:52 +0000 Subject: net: tun: change tun_alloc_skb() to allow bigger paged allocations tun_alloc_skb() is currently calling sock_alloc_send_pskb() forcing order-0 page allocations. Switch to PAGE_ALLOC_COSTLY_ORDER, to increase max allocation size by 8x. Also add logic to increase the linear part if needed. Signed-off-by: Eric Dumazet Cc: Tahsin Erdogan Reviewed-by: Willem de Bruijn Link: https://lore.kernel.org/r/20230801205254.400094-3-edumazet@google.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d75456adc62a..8a48431e8c5b 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1526,8 +1526,10 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, if (prepad + len < PAGE_SIZE || !linear) linear = len; + if (len - linear > MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) + linear = len - MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER); skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, - &err, 0); + &err, PAGE_ALLOC_COSTLY_ORDER); if (!skb) return ERR_PTR(err); -- cgit From 37dfe5b8ddeb7c0bb97e3643dcfd8f9f1421ad25 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 1 Aug 2023 20:52:54 +0000 Subject: net: tap: change tap_alloc_skb() to allow bigger paged allocations tap_alloc_skb() is currently calling sock_alloc_send_pskb() forcing order-0 page allocations. Switch to PAGE_ALLOC_COSTLY_ORDER, to increase max size by 8x. Also add logic to increase the linear part if needed. Signed-off-by: Eric Dumazet Cc: Tahsin Erdogan Reviewed-by: Willem de Bruijn Link: https://lore.kernel.org/r/20230801205254.400094-5-edumazet@google.com Signed-off-by: Jakub Kicinski --- drivers/net/tap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 9137fb8c1c42..01574b9d410f 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -614,8 +614,10 @@ static inline struct sk_buff *tap_alloc_skb(struct sock *sk, size_t prepad, if (prepad + len < PAGE_SIZE || !linear) linear = len; + if (len - linear > MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) + linear = len - MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER); skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, - err, 0); + err, PAGE_ALLOC_COSTLY_ORDER); if (!skb) return NULL; -- cgit From 0bca3f7f9acdf755f246b4febb0da59a4cd83638 Mon Sep 17 00:00:00 2001 From: Maxim Georgiev Date: Tue, 1 Aug 2023 17:28:16 +0300 Subject: net: macvlan: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() macvlan is one of the stackable net devices which pass the hardware timestamping ops to the real device through ndo_eth_ioctl(). This prevents converting any device driver to the new hwtimestamping API without regressions. Remove that limitation in macvlan by using the newly introduced helpers for timestamping through lower devices, that handle both the new and the old driver API. macvlan only implements ndo_eth_ioctl() for these 2 operations, so delete that method. Signed-off-by: Maxim Georgiev Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20230801142824.1772134-5-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/macvlan.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index ed908165a8b4..02bd201bc7e5 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -868,31 +868,24 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int macvlan_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int macvlan_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) { struct net_device *real_dev = macvlan_dev_real_dev(dev); - const struct net_device_ops *ops = real_dev->netdev_ops; - struct ifreq ifrr; - int err = -EOPNOTSUPP; - strscpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ); - ifrr.ifr_ifru = ifr->ifr_ifru; + return generic_hwtstamp_get_lower(real_dev, cfg); +} - switch (cmd) { - case SIOCSHWTSTAMP: - if (!net_eq(dev_net(dev), &init_net)) - break; - fallthrough; - case SIOCGHWTSTAMP: - if (netif_device_present(real_dev) && ops->ndo_eth_ioctl) - err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd); - break; - } +static int macvlan_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) +{ + struct net_device *real_dev = macvlan_dev_real_dev(dev); - if (!err) - ifr->ifr_ifru = ifrr.ifr_ifru; + if (!net_eq(dev_net(dev), &init_net)) + return -EOPNOTSUPP; - return err; + return generic_hwtstamp_set_lower(real_dev, cfg, extack); } /* @@ -1193,7 +1186,6 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_stop = macvlan_stop, .ndo_start_xmit = macvlan_start_xmit, .ndo_change_mtu = macvlan_change_mtu, - .ndo_eth_ioctl = macvlan_eth_ioctl, .ndo_fix_features = macvlan_fix_features, .ndo_change_rx_flags = macvlan_change_rx_flags, .ndo_set_mac_address = macvlan_set_mac_address, @@ -1212,6 +1204,8 @@ static const struct net_device_ops macvlan_netdev_ops = { #endif .ndo_get_iflink = macvlan_dev_get_iflink, .ndo_features_check = passthru_features_check, + .ndo_hwtstamp_get = macvlan_hwtstamp_get, + .ndo_hwtstamp_set = macvlan_hwtstamp_set, }; static void macvlan_dev_free(struct net_device *dev) -- cgit From c0dabeb4c666ec952a07e79790606974a3be4303 Mon Sep 17 00:00:00 2001 From: Maxim Georgiev Date: Tue, 1 Aug 2023 17:28:17 +0300 Subject: net: bonding: convert to ndo_hwtstamp_get() / ndo_hwtstamp_set() bonding is one of the stackable net devices which pass the hardware timestamping ops to the real device through ndo_eth_ioctl(). This prevents converting any device driver to the new hwtimestamping API without regressions. Remove that limitation in bonding by using the newly introduced helpers for timestamping through lower devices, that handle both the new and the old driver API. Signed-off-by: Maxim Georgiev Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20230801142824.1772134-6-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/bonding/bond_main.c | 105 +++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 484c9e3e5e82..f04d4f28eb1a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4446,11 +4446,6 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm { struct bonding *bond = netdev_priv(bond_dev); struct mii_ioctl_data *mii = NULL; - const struct net_device_ops *ops; - struct net_device *real_dev; - struct hwtstamp_config cfg; - struct ifreq ifrr; - int res = 0; netdev_dbg(bond_dev, "bond_eth_ioctl: cmd=%d\n", cmd); @@ -4477,44 +4472,11 @@ static int bond_eth_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cm } break; - case SIOCSHWTSTAMP: - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - if (!(cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX)) - return -EOPNOTSUPP; - - fallthrough; - case SIOCGHWTSTAMP: - real_dev = bond_option_active_slave_get_rcu(bond); - if (!real_dev) - return -EOPNOTSUPP; - - strscpy_pad(ifrr.ifr_name, real_dev->name, IFNAMSIZ); - ifrr.ifr_ifru = ifr->ifr_ifru; - - ops = real_dev->netdev_ops; - if (netif_device_present(real_dev) && ops->ndo_eth_ioctl) { - res = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd); - if (res) - return res; - - ifr->ifr_ifru = ifrr.ifr_ifru; - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - /* Set the BOND_PHC_INDEX flag to notify user space */ - cfg.flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX; - - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? - -EFAULT : 0; - } - fallthrough; default: - res = -EOPNOTSUPP; + return -EOPNOTSUPP; } - return res; + return 0; } static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd) @@ -5688,6 +5650,67 @@ static u32 bond_mode_bcast_speed(struct slave *slave, u32 speed) return speed; } +/* Set the BOND_PHC_INDEX flag to notify user space */ +static int bond_set_phc_index_flag(struct kernel_hwtstamp_config *kernel_cfg) +{ + struct ifreq *ifr = kernel_cfg->ifr; + struct hwtstamp_config cfg; + + if (kernel_cfg->copied_to_user) { + /* Lower device has a legacy implementation */ + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + cfg.flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX; + if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) + return -EFAULT; + } else { + kernel_cfg->flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX; + } + + return 0; +} + +static int bond_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) +{ + struct bonding *bond = netdev_priv(dev); + struct net_device *real_dev; + int err; + + real_dev = bond_option_active_slave_get_rcu(bond); + if (!real_dev) + return -EOPNOTSUPP; + + err = generic_hwtstamp_get_lower(real_dev, cfg); + if (err) + return err; + + return bond_set_phc_index_flag(cfg); +} + +static int bond_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) +{ + struct bonding *bond = netdev_priv(dev); + struct net_device *real_dev; + int err; + + if (!(cfg->flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX)) + return -EOPNOTSUPP; + + real_dev = bond_option_active_slave_get_rcu(bond); + if (!real_dev) + return -EOPNOTSUPP; + + err = generic_hwtstamp_set_lower(real_dev, cfg, extack); + if (err) + return err; + + return bond_set_phc_index_flag(cfg); +} + static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev, struct ethtool_link_ksettings *cmd) { @@ -5836,6 +5859,8 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_bpf = bond_xdp, .ndo_xdp_xmit = bond_xdp_xmit, .ndo_xdp_get_xmit_slave = bond_xdp_get_xmit_slave, + .ndo_hwtstamp_get = bond_hwtstamp_get, + .ndo_hwtstamp_set = bond_hwtstamp_set, }; static const struct device_type bond_type = { -- cgit From ef5eb9c5ce45deb4af0898778e2536fda80bc362 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:18 +0300 Subject: net: fec: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() The hardware timestamping through ndo_eth_ioctl() is going away. Convert the FEC driver to the new API before that can be removed. After removing the timestamping logic from fec_enet_ioctl(), the rest is equivalent to phy_do_ioctl_running(). Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Reviewed-by: Wei Fang Link: https://lore.kernel.org/r/20230801142824.1772134-7-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec.h | 5 ++- drivers/net/ethernet/freescale/fec_main.c | 73 +++++++++++++++++++------------ drivers/net/ethernet/freescale/fec_ptp.c | 31 +++++-------- 3 files changed, 59 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 8f1edcca96c4..ec64067ca782 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -699,8 +699,9 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx); void fec_ptp_stop(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); void fec_ptp_disable_hwts(struct net_device *ndev); -int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); -int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); +int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); +void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config); /****************************************************************************/ #endif /* FEC_H */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 14d0dc7ba3c9..bbd0cc97905a 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3203,33 +3203,6 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .self_test = net_selftest, }; -static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = ndev->phydev; - - if (!netif_running(ndev)) - return -EINVAL; - - if (!phydev) - return -ENODEV; - - if (fep->bufdesc_ex) { - bool use_fec_hwts = !phy_has_hwtstamp(phydev); - - if (cmd == SIOCSHWTSTAMP) { - if (use_fec_hwts) - return fec_ptp_set(ndev, rq); - fec_ptp_disable_hwts(ndev); - } else if (cmd == SIOCGHWTSTAMP) { - if (use_fec_hwts) - return fec_ptp_get(ndev, rq); - } - } - - return phy_mii_ioctl(phydev, rq, cmd); -} - static void fec_enet_free_buffers(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); @@ -3895,6 +3868,48 @@ static int fec_enet_xdp_xmit(struct net_device *dev, return sent_frames; } +static int fec_hwtstamp_get(struct net_device *ndev, + struct kernel_hwtstamp_config *config) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + struct phy_device *phydev = ndev->phydev; + + if (phy_has_hwtstamp(phydev)) + return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP); + + if (!netif_running(ndev)) + return -EINVAL; + + if (!fep->bufdesc_ex) + return -EOPNOTSUPP; + + fec_ptp_get(ndev, config); + + return 0; +} + +static int fec_hwtstamp_set(struct net_device *ndev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + struct phy_device *phydev = ndev->phydev; + + if (phy_has_hwtstamp(phydev)) { + fec_ptp_disable_hwts(ndev); + + return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP); + } + + if (!netif_running(ndev)) + return -EINVAL; + + if (!fep->bufdesc_ex) + return -EOPNOTSUPP; + + return fec_ptp_set(ndev, config, extack); +} + static const struct net_device_ops fec_netdev_ops = { .ndo_open = fec_enet_open, .ndo_stop = fec_enet_close, @@ -3904,13 +3919,15 @@ static const struct net_device_ops fec_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = fec_timeout, .ndo_set_mac_address = fec_set_mac_address, - .ndo_eth_ioctl = fec_enet_ioctl, + .ndo_eth_ioctl = phy_do_ioctl_running, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = fec_poll_controller, #endif .ndo_set_features = fec_set_features, .ndo_bpf = fec_enet_bpf, .ndo_xdp_xmit = fec_enet_xdp_xmit, + .ndo_hwtstamp_get = fec_hwtstamp_get, + .ndo_hwtstamp_set = fec_hwtstamp_set, }; static const unsigned short offset_des_active_rxq[] = { diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index fc4674cb65be..befd49b8bd71 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -617,16 +617,12 @@ void fec_ptp_disable_hwts(struct net_device *ndev) fep->hwts_rx_en = 0; } -int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) +int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { struct fec_enet_private *fep = netdev_priv(ndev); - struct hwtstamp_config config; - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - switch (config.tx_type) { + switch (config->tx_type) { case HWTSTAMP_TX_OFF: fep->hwts_tx_en = 0; break; @@ -637,33 +633,28 @@ int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) return -ERANGE; } - switch (config.rx_filter) { + switch (config->rx_filter) { case HWTSTAMP_FILTER_NONE: fep->hwts_rx_en = 0; break; default: fep->hwts_rx_en = 1; - config.rx_filter = HWTSTAMP_FILTER_ALL; + config->rx_filter = HWTSTAMP_FILTER_ALL; break; } - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } -int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr) +void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config) { struct fec_enet_private *fep = netdev_priv(ndev); - struct hwtstamp_config config; - - config.flags = 0; - config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; - config.rx_filter = (fep->hwts_rx_en ? - HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + config->flags = 0; + config->tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config->rx_filter = (fep->hwts_rx_en ? + HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); } /* -- cgit From 547b006d192261067323efe4b1a12287cf3e4ac2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:19 +0300 Subject: net: fec: delete fec_ptp_disable_hwts() Commit 340746398b67 ("net: fec: fix hardware time stamping by external devices") was overly cautious with calling fec_ptp_disable_hwts() when cmd == SIOCSHWTSTAMP and use_fec_hwts == false, because use_fec_hwts is based on a runtime invariant (phy_has_hwtstamp()). Thus, if use_fec_hwts is false, then fep->hwts_tx_en and fep->hwts_rx_en cannot be changed at runtime; their values depend on the initial memory allocation, which already sets them to zeroes. If the core will ever gain support for switching timestamping layers, it will arrange for a more organized calling convention and disable timestamping in the previous layer as a first step. This means that the code in the FEC driver is not necessary in any case. The purpose of this change is to arrange the phy_has_hwtstamp() code in a way in which it can be refactored away into generic logic. Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Reviewed-by: Wei Fang Link: https://lore.kernel.org/r/20230801142824.1772134-8-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_main.c | 5 +---- drivers/net/ethernet/freescale/fec_ptp.c | 12 ------------ 3 files changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index ec64067ca782..110f2e9f3e3f 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -698,7 +698,6 @@ struct fec_enet_private { void fec_ptp_init(struct platform_device *pdev, int irq_idx); void fec_ptp_stop(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); -void fec_ptp_disable_hwts(struct net_device *ndev); int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config, struct netlink_ext_ack *extack); void fec_ptp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index bbd0cc97905a..6d81fff0227e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3895,11 +3895,8 @@ static int fec_hwtstamp_set(struct net_device *ndev, struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = ndev->phydev; - if (phy_has_hwtstamp(phydev)) { - fec_ptp_disable_hwts(ndev); - + if (phy_has_hwtstamp(phydev)) return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP); - } if (!netif_running(ndev)) return -EINVAL; diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index befd49b8bd71..181d9bfbee22 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -605,18 +605,6 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, } } -/** - * fec_ptp_disable_hwts - disable hardware time stamping - * @ndev: pointer to net_device - */ -void fec_ptp_disable_hwts(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - fep->hwts_tx_en = 0; - fep->hwts_rx_en = 0; -} - int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config, struct netlink_ext_ack *extack) { -- cgit From 7bdde44463b2980dac9577604a27ae69c2bbd0a1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:20 +0300 Subject: net: sparx5: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() The hardware timestamping through ndo_eth_ioctl() is going away. Convert the sparx5 driver to the new API before that can be removed. After removing the timestamping logic from sparx5_port_ioctl(), the rest is equivalent to phy_do_ioctl(). Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Reviewed-by: Steen Hegelund Link: https://lore.kernel.org/r/20230801142824.1772134-9-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/microchip/sparx5/sparx5_main.h | 9 +++-- .../net/ethernet/microchip/sparx5/sparx5_netdev.c | 41 +++++++++++++++------- drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c | 24 ++++++------- 3 files changed, 46 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index 62c85463b634..89a9a7afa32c 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -205,7 +205,7 @@ enum sparx5_core_clockfreq { struct sparx5_phc { struct ptp_clock *clock; struct ptp_clock_info info; - struct hwtstamp_config hwtstamp_config; + struct kernel_hwtstamp_config hwtstamp_config; struct sparx5 *sparx5; u8 index; }; @@ -388,8 +388,11 @@ void sparx5_unregister_netdevs(struct sparx5 *sparx5); /* sparx5_ptp.c */ int sparx5_ptp_init(struct sparx5 *sparx5); void sparx5_ptp_deinit(struct sparx5 *sparx5); -int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr); -int sparx5_ptp_hwtstamp_get(struct sparx5_port *port, struct ifreq *ifr); +int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack); +void sparx5_ptp_hwtstamp_get(struct sparx5_port *port, + struct kernel_hwtstamp_config *cfg); void sparx5_ptp_rxtstamp(struct sparx5 *sparx5, struct sk_buff *skb, u64 timestamp); int sparx5_ptp_txtstamp_request(struct sparx5_port *port, diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index d078156581d5..e01d3b1e17e0 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -210,22 +210,37 @@ static int sparx5_get_port_parent_id(struct net_device *dev, return 0; } -static int sparx5_port_ioctl(struct net_device *dev, struct ifreq *ifr, - int cmd) +static int sparx5_port_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) { struct sparx5_port *sparx5_port = netdev_priv(dev); struct sparx5 *sparx5 = sparx5_port->sparx5; - if (!phy_has_hwtstamp(dev->phydev) && sparx5->ptp) { - switch (cmd) { - case SIOCSHWTSTAMP: - return sparx5_ptp_hwtstamp_set(sparx5_port, ifr); - case SIOCGHWTSTAMP: - return sparx5_ptp_hwtstamp_get(sparx5_port, ifr); - } - } + if (phy_has_hwtstamp(dev->phydev)) + return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP); + + if (!sparx5->ptp) + return -EOPNOTSUPP; + + sparx5_ptp_hwtstamp_get(sparx5_port, cfg); + + return 0; +} + +static int sparx5_port_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) +{ + struct sparx5_port *sparx5_port = netdev_priv(dev); + struct sparx5 *sparx5 = sparx5_port->sparx5; + + if (phy_has_hwtstamp(dev->phydev)) + return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP); + + if (!sparx5->ptp) + return -EOPNOTSUPP; - return phy_mii_ioctl(dev->phydev, ifr, cmd); + return sparx5_ptp_hwtstamp_set(sparx5_port, cfg, extack); } static const struct net_device_ops sparx5_port_netdev_ops = { @@ -238,8 +253,10 @@ static const struct net_device_ops sparx5_port_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_get_stats64 = sparx5_get_stats64, .ndo_get_port_parent_id = sparx5_get_port_parent_id, - .ndo_eth_ioctl = sparx5_port_ioctl, + .ndo_eth_ioctl = phy_do_ioctl, .ndo_setup_tc = sparx5_port_setup_tc, + .ndo_hwtstamp_get = sparx5_port_hwtstamp_get, + .ndo_hwtstamp_set = sparx5_port_hwtstamp_set, }; bool sparx5_netdevice_check(const struct net_device *dev) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c index 0edb98cef7e4..5a932460db58 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c @@ -74,10 +74,11 @@ static u64 sparx5_ptp_get_nominal_value(struct sparx5 *sparx5) return res; } -int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr) +int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) { struct sparx5 *sparx5 = port->sparx5; - struct hwtstamp_config cfg; struct sparx5_phc *phc; /* For now don't allow to run ptp on ports that are part of a bridge, @@ -88,10 +89,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr) if (test_bit(port->portno, sparx5->bridge_mask)) return -EINVAL; - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - switch (cfg.tx_type) { + switch (cfg->tx_type) { case HWTSTAMP_TX_ON: port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; break; @@ -105,7 +103,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr) return -ERANGE; } - switch (cfg.rx_filter) { + switch (cfg->rx_filter) { case HWTSTAMP_FILTER_NONE: break; case HWTSTAMP_FILTER_ALL: @@ -122,7 +120,7 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL: - cfg.rx_filter = HWTSTAMP_FILTER_ALL; + cfg->rx_filter = HWTSTAMP_FILTER_ALL; break; default: return -ERANGE; @@ -131,20 +129,20 @@ int sparx5_ptp_hwtstamp_set(struct sparx5_port *port, struct ifreq *ifr) /* Commit back the result & save it */ mutex_lock(&sparx5->ptp_lock); phc = &sparx5->phc[SPARX5_PHC_PORT]; - memcpy(&phc->hwtstamp_config, &cfg, sizeof(cfg)); + phc->hwtstamp_config = *cfg; mutex_unlock(&sparx5->ptp_lock); - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + return 0; } -int sparx5_ptp_hwtstamp_get(struct sparx5_port *port, struct ifreq *ifr) +void sparx5_ptp_hwtstamp_get(struct sparx5_port *port, + struct kernel_hwtstamp_config *cfg) { struct sparx5 *sparx5 = port->sparx5; struct sparx5_phc *phc; phc = &sparx5->phc[SPARX5_PHC_PORT]; - return copy_to_user(ifr->ifr_data, &phc->hwtstamp_config, - sizeof(phc->hwtstamp_config)) ? -EFAULT : 0; + *cfg = phc->hwtstamp_config; } static void sparx5_ptp_classify(struct sparx5_port *port, struct sk_buff *skb, -- cgit From 54e1ed69c40a3ea9a82cb59ad88e00af98a6628e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:21 +0300 Subject: net: lan966x: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() The hardware timestamping through ndo_eth_ioctl() is going away. Convert the lan966x driver to the new API before that can be removed. After removing the timestamping logic from lan966x_port_ioctl(), the rest is equivalent to phy_do_ioctl(). Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Tested-by: Horatiu Vultur Link: https://lore.kernel.org/r/20230801142824.1772134-10-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/microchip/lan966x/lan966x_main.c | 59 ++++++++++++---------- .../net/ethernet/microchip/lan966x/lan966x_main.h | 12 +++-- .../net/ethernet/microchip/lan966x/lan966x_ptp.c | 34 +++++-------- 3 files changed, 55 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 73f20683210e..1baa94a98fe3 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -450,39 +450,44 @@ static int lan966x_port_get_parent_id(struct net_device *dev, return 0; } -static int lan966x_port_ioctl(struct net_device *dev, struct ifreq *ifr, - int cmd) +static int lan966x_port_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) { struct lan966x_port *port = netdev_priv(dev); - int err; - if (cmd == SIOCSHWTSTAMP) { - err = lan966x_ptp_setup_traps(port, ifr); - if (err) - return err; - } + if (phy_has_hwtstamp(dev->phydev)) + return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP); - if (!phy_has_hwtstamp(dev->phydev) && port->lan966x->ptp) { - switch (cmd) { - case SIOCSHWTSTAMP: - err = lan966x_ptp_hwtstamp_set(port, ifr); - if (err) - lan966x_ptp_del_traps(port); + if (!port->lan966x->ptp) + return -EOPNOTSUPP; - return err; - case SIOCGHWTSTAMP: - return lan966x_ptp_hwtstamp_get(port, ifr); - } - } + lan966x_ptp_hwtstamp_get(port, cfg); - if (!dev->phydev) - return -ENODEV; + return 0; +} - err = phy_mii_ioctl(dev->phydev, ifr, cmd); - if (err && cmd == SIOCSHWTSTAMP) - lan966x_ptp_del_traps(port); +static int lan966x_port_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) +{ + struct lan966x_port *port = netdev_priv(dev); + int err; - return err; + err = lan966x_ptp_setup_traps(port, cfg); + if (err) + return err; + + if (phy_has_hwtstamp(dev->phydev)) { + err = phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP); + if (err) + lan966x_ptp_del_traps(port); + return err; + } + + if (!port->lan966x->ptp) + return -EOPNOTSUPP; + + return lan966x_ptp_hwtstamp_set(port, cfg, extack); } static const struct net_device_ops lan966x_port_netdev_ops = { @@ -495,10 +500,12 @@ static const struct net_device_ops lan966x_port_netdev_ops = { .ndo_get_stats64 = lan966x_stats_get, .ndo_set_mac_address = lan966x_port_set_mac_address, .ndo_get_port_parent_id = lan966x_port_get_parent_id, - .ndo_eth_ioctl = lan966x_port_ioctl, + .ndo_eth_ioctl = phy_do_ioctl, .ndo_setup_tc = lan966x_tc_setup, .ndo_bpf = lan966x_xdp, .ndo_xdp_xmit = lan966x_xdp_xmit, + .ndo_hwtstamp_get = lan966x_port_hwtstamp_get, + .ndo_hwtstamp_set = lan966x_port_hwtstamp_set, }; bool lan966x_netdevice_check(const struct net_device *dev) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 27f272831ea5..b538d496e8d7 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -298,7 +298,7 @@ struct lan966x_phc { struct ptp_clock *clock; struct ptp_clock_info info; struct ptp_pin_desc pins[LAN966X_PHC_PINS_NUM]; - struct hwtstamp_config hwtstamp_config; + struct kernel_hwtstamp_config hwtstamp_config; struct lan966x *lan966x; u8 index; }; @@ -578,8 +578,11 @@ void lan966x_mdb_restore_entries(struct lan966x *lan966x); int lan966x_ptp_init(struct lan966x *lan966x); void lan966x_ptp_deinit(struct lan966x *lan966x); -int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr); -int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr); +int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack); +void lan966x_ptp_hwtstamp_get(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg); void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, u64 src_port, u64 timestamp); int lan966x_ptp_txtstamp_request(struct lan966x_port *port, @@ -590,7 +593,8 @@ irqreturn_t lan966x_ptp_irq_handler(int irq, void *args); irqreturn_t lan966x_ptp_ext_irq_handler(int irq, void *args); u32 lan966x_ptp_get_period_ps(void); int lan966x_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts); -int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr); +int lan966x_ptp_setup_traps(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg); int lan966x_ptp_del_traps(struct lan966x_port *port); int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c index 266a21a2d124..60bd0cff6677 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c @@ -248,29 +248,23 @@ int lan966x_ptp_del_traps(struct lan966x_port *port) return err; } -int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr) +int lan966x_ptp_setup_traps(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg) { - struct hwtstamp_config cfg; - - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - if (cfg.rx_filter == HWTSTAMP_FILTER_NONE) + if (cfg->rx_filter == HWTSTAMP_FILTER_NONE) return lan966x_ptp_del_traps(port); else return lan966x_ptp_add_traps(port); } -int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) +int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) { struct lan966x *lan966x = port->lan966x; - struct hwtstamp_config cfg; struct lan966x_phc *phc; - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - switch (cfg.tx_type) { + switch (cfg->tx_type) { case HWTSTAMP_TX_ON: port->ptp_tx_cmd = IFH_REW_OP_TWO_STEP_PTP; break; @@ -284,7 +278,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) return -ERANGE; } - switch (cfg.rx_filter) { + switch (cfg->rx_filter) { case HWTSTAMP_FILTER_NONE: port->ptp_rx_cmd = false; break; @@ -303,7 +297,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL: port->ptp_rx_cmd = true; - cfg.rx_filter = HWTSTAMP_FILTER_ALL; + cfg->rx_filter = HWTSTAMP_FILTER_ALL; break; default: return -ERANGE; @@ -312,20 +306,20 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) /* Commit back the result & save it */ mutex_lock(&lan966x->ptp_lock); phc = &lan966x->phc[LAN966X_PHC_PORT]; - memcpy(&phc->hwtstamp_config, &cfg, sizeof(cfg)); + phc->hwtstamp_config = *cfg; mutex_unlock(&lan966x->ptp_lock); - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + return 0; } -int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr) +void lan966x_ptp_hwtstamp_get(struct lan966x_port *port, + struct kernel_hwtstamp_config *cfg) { struct lan966x *lan966x = port->lan966x; struct lan966x_phc *phc; phc = &lan966x->phc[LAN966X_PHC_PORT]; - return copy_to_user(ifr->ifr_data, &phc->hwtstamp_config, - sizeof(phc->hwtstamp_config)) ? -EFAULT : 0; + *cfg = phc->hwtstamp_config; } static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb) -- cgit From 70ef7d87f62a86674c21a99341dabc175c19681a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:22 +0300 Subject: net: transfer rtnl_lock() requirement from ethtool_set_ethtool_phy_ops() to caller phy_init() and phy_exit() will have to do more stuff under rtnl_lock() in a future change. Since rtnl_unlock() -> netdev_run_todo() does a lot of stuff under the hood, it's a pity to lock and unlock the rtnetlink mutex twice in a row. Change the calling convention such that the only caller of ethtool_set_ethtool_phy_ops(), phy_device.c, provides a context where the rtnl_mutex is already acquired. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230801142824.1772134-11-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 61921d4dbb13..98b8ac28e5a1 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -3451,7 +3452,9 @@ static int __init phy_init(void) { int rc; + rtnl_lock(); ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops); + rtnl_unlock(); rc = mdio_bus_init(); if (rc) @@ -3474,7 +3477,9 @@ err_c45: err_mdio_bus: mdio_bus_exit(); err_ethtool_phy_ops: + rtnl_lock(); ethtool_set_ethtool_phy_ops(NULL); + rtnl_unlock(); return rc; } @@ -3484,7 +3489,9 @@ static void __exit phy_exit(void) phy_driver_unregister(&genphy_c45_driver); phy_driver_unregister(&genphy_driver); mdio_bus_exit(); + rtnl_lock(); ethtool_set_ethtool_phy_ops(NULL); + rtnl_unlock(); } subsys_initcall(phy_init); -- cgit From 60495b6622ca67f5180343b89bd932d28d23f63a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:23 +0300 Subject: net: phy: provide phylib stubs for hardware timestamping operations net/core/dev_ioctl.c (built-in code) will want to call phy_mii_ioctl() for hardware timestamping purposes. This is not directly possible, because phy_mii_ioctl() is a symbol provided under CONFIG_PHYLIB. Do something similar to what was done in DSA in commit 5a17818682cf ("net: dsa: replace NETDEV_PRE_CHANGE_HWTSTAMP notifier with a stub"), and arrange some indirect calls to phy_mii_ioctl() through a stub structure containing function pointers, that's provided by phylib as built-in even when CONFIG_PHYLIB=m, and which phy_init() populates at runtime (module insertion). Note: maybe the ownership of the ethtool_phy_ops singleton is backwards, and the methods exposed by that should be later merged into phylib_stubs. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230801142824.1772134-12-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/Makefile | 2 ++ drivers/net/phy/phy.c | 34 ++++++++++++++++++++++++++++++++++ drivers/net/phy/phy_device.c | 19 +++++++++++++++++++ drivers/net/phy/stubs.c | 10 ++++++++++ 4 files changed, 65 insertions(+) create mode 100644 drivers/net/phy/stubs.c (limited to 'drivers/net') diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 35142780fc9d..c945ed9bd14b 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -14,6 +14,8 @@ endif # dedicated loadable module, so we bundle them all together into libphy.ko ifdef CONFIG_PHYLIB libphy-y += $(mdio-bus-y) +# the stubs are built-in whenever PHYLIB is built-in or module +obj-y += stubs.o else obj-$(CONFIG_MDIO_DEVICE) += mdio-bus.o endif diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bdf00b2b2c1d..8aec8e83038c 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -455,6 +455,40 @@ int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd) } EXPORT_SYMBOL(phy_do_ioctl_running); +/** + * __phy_hwtstamp_get - Get hardware timestamping configuration from PHY + * + * @phydev: the PHY device structure + * @config: structure holding the timestamping configuration + * + * Query the PHY device for its current hardware timestamping configuration. + */ +int __phy_hwtstamp_get(struct phy_device *phydev, + struct kernel_hwtstamp_config *config) +{ + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP); +} + +/** + * __phy_hwtstamp_set - Modify PHY hardware timestamping configuration + * + * @phydev: the PHY device structure + * @config: structure holding the timestamping configuration + * @extack: netlink extended ack structure, for error reporting + */ +int __phy_hwtstamp_set(struct phy_device *phydev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) +{ + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP); +} + /** * phy_queue_state_machine - Trigger the state machine to run soon * diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 98b8ac28e5a1..e19c4fee8d22 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -3448,12 +3449,28 @@ static const struct ethtool_phy_ops phy_ethtool_phy_ops = { .start_cable_test_tdr = phy_start_cable_test_tdr, }; +static const struct phylib_stubs __phylib_stubs = { + .hwtstamp_get = __phy_hwtstamp_get, + .hwtstamp_set = __phy_hwtstamp_set, +}; + +static void phylib_register_stubs(void) +{ + phylib_stubs = &__phylib_stubs; +} + +static void phylib_unregister_stubs(void) +{ + phylib_stubs = NULL; +} + static int __init phy_init(void) { int rc; rtnl_lock(); ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops); + phylib_register_stubs(); rtnl_unlock(); rc = mdio_bus_init(); @@ -3478,6 +3495,7 @@ err_mdio_bus: mdio_bus_exit(); err_ethtool_phy_ops: rtnl_lock(); + phylib_unregister_stubs(); ethtool_set_ethtool_phy_ops(NULL); rtnl_unlock(); @@ -3490,6 +3508,7 @@ static void __exit phy_exit(void) phy_driver_unregister(&genphy_driver); mdio_bus_exit(); rtnl_lock(); + phylib_unregister_stubs(); ethtool_set_ethtool_phy_ops(NULL); rtnl_unlock(); } diff --git a/drivers/net/phy/stubs.c b/drivers/net/phy/stubs.c new file mode 100644 index 000000000000..cfb9f275eb18 --- /dev/null +++ b/drivers/net/phy/stubs.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Stubs for PHY library functionality called by the core network stack. + * These are necessary because CONFIG_PHYLIB can be a module, and built-in + * code cannot directly call symbols exported by modules. + */ +#include + +const struct phylib_stubs *phylib_stubs; +EXPORT_SYMBOL_GPL(phylib_stubs); -- cgit From fd770e856e226f80fe6e1dc9d1861bcb135cdf0b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 1 Aug 2023 17:28:24 +0300 Subject: net: remove phy_has_hwtstamp() -> phy_mii_ioctl() decision from converted drivers It is desirable that the new .ndo_hwtstamp_set() API gives more uniformity, less overhead and future flexibility w.r.t. the PHY timestamping behavior. Currently there are some drivers which allow PHY timestamping through the procedure mentioned in Documentation/networking/timestamping.rst. They don't do anything locally if phy_has_hwtstamp() is set, except for lan966x which installs PTP packet traps. Centralize that behavior in a new dev_set_hwtstamp_phylib() code function, which calls either phy_mii_ioctl() for the phylib PHY, or .ndo_hwtstamp_set() of the netdev, based on a single policy (currently simplistic: phy_has_hwtstamp()). Any driver converted to .ndo_hwtstamp_set() will automatically opt into the centralized phylib timestamping policy. Unconverted drivers still get to choose whether they let the PHY handle timestamping or not. Netdev drivers with integrated PHY drivers that don't use phylib presumably don't set dev->phydev, and those will always see HWTSTAMP_SOURCE_NETDEV requests even when converted. The timestamping policy will remain 100% up to them. Signed-off-by: Vladimir Oltean Reviewed-by: Jacob Keller Tested-by: Horatiu Vultur Link: https://lore.kernel.org/r/20230801142824.1772134-13-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 8 ------- .../net/ethernet/microchip/lan966x/lan966x_main.c | 25 ++++++++++++---------- .../net/ethernet/microchip/sparx5/sparx5_netdev.c | 6 ------ 3 files changed, 14 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 6d81fff0227e..43f14cec91e9 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3872,10 +3872,6 @@ static int fec_hwtstamp_get(struct net_device *ndev, struct kernel_hwtstamp_config *config) { struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = ndev->phydev; - - if (phy_has_hwtstamp(phydev)) - return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP); if (!netif_running(ndev)) return -EINVAL; @@ -3893,10 +3889,6 @@ static int fec_hwtstamp_set(struct net_device *ndev, struct netlink_ext_ack *extack) { struct fec_enet_private *fep = netdev_priv(ndev); - struct phy_device *phydev = ndev->phydev; - - if (phy_has_hwtstamp(phydev)) - return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP); if (!netif_running(ndev)) return -EINVAL; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 1baa94a98fe3..4a1acc7234f6 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -455,9 +455,6 @@ static int lan966x_port_hwtstamp_get(struct net_device *dev, { struct lan966x_port *port = netdev_priv(dev); - if (phy_has_hwtstamp(dev->phydev)) - return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP); - if (!port->lan966x->ptp) return -EOPNOTSUPP; @@ -473,21 +470,26 @@ static int lan966x_port_hwtstamp_set(struct net_device *dev, struct lan966x_port *port = netdev_priv(dev); int err; + if (cfg->source != HWTSTAMP_SOURCE_NETDEV && + cfg->source != HWTSTAMP_SOURCE_PHYLIB) + return -EOPNOTSUPP; + err = lan966x_ptp_setup_traps(port, cfg); if (err) return err; - if (phy_has_hwtstamp(dev->phydev)) { - err = phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP); - if (err) + if (cfg->source == HWTSTAMP_SOURCE_NETDEV) { + if (!port->lan966x->ptp) + return -EOPNOTSUPP; + + err = lan966x_ptp_hwtstamp_set(port, cfg, extack); + if (err) { lan966x_ptp_del_traps(port); - return err; + return err; + } } - if (!port->lan966x->ptp) - return -EOPNOTSUPP; - - return lan966x_ptp_hwtstamp_set(port, cfg, extack); + return 0; } static const struct net_device_ops lan966x_port_netdev_ops = { @@ -815,6 +817,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p, NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_TC; dev->hw_features |= NETIF_F_HW_TC; + dev->priv_flags |= IFF_SEE_ALL_HWTSTAMP_REQUESTS; dev->needed_headroom = IFH_LEN_BYTES; eth_hw_addr_gen(dev, lan966x->base_mac, p + 1); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index e01d3b1e17e0..705a004b324f 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -216,9 +216,6 @@ static int sparx5_port_hwtstamp_get(struct net_device *dev, struct sparx5_port *sparx5_port = netdev_priv(dev); struct sparx5 *sparx5 = sparx5_port->sparx5; - if (phy_has_hwtstamp(dev->phydev)) - return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCGHWTSTAMP); - if (!sparx5->ptp) return -EOPNOTSUPP; @@ -234,9 +231,6 @@ static int sparx5_port_hwtstamp_set(struct net_device *dev, struct sparx5_port *sparx5_port = netdev_priv(dev); struct sparx5 *sparx5 = sparx5_port->sparx5; - if (phy_has_hwtstamp(dev->phydev)) - return phy_mii_ioctl(dev->phydev, cfg->ifr, SIOCSHWTSTAMP); - if (!sparx5->ptp) return -EOPNOTSUPP; -- cgit From 80662d9430757302176a4c2e1d7577184eb76adc Mon Sep 17 00:00:00 2001 From: Frank Jungclaus Date: Fri, 28 Jul 2023 17:08:57 +0200 Subject: can: esd_usb: Add support for esd CAN-USB/3 Add support for esd CAN-USB/3 and CAN FD to esd_usb.c. Signed-off-by: Frank Jungclaus Reviewed-by: Simon Horman Link: https://lore.kernel.org/all/20230728150857.2374886-2-frank.jungclaus@esd.eu Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/esd_usb.c | 275 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 244 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index 6201637ac0ff..41a0e4261d15 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro + * CAN driver for esd electronics gmbh CAN-USB/2, CAN-USB/3 and CAN-USB/Micro * * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus @@ -19,17 +19,19 @@ MODULE_AUTHOR("Matthias Fuchs "); MODULE_AUTHOR("Frank Jungclaus "); -MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro interfaces"); +MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2, CAN-USB/3 and CAN-USB/Micro interfaces"); MODULE_LICENSE("GPL v2"); /* USB vendor and product ID */ #define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4 #define ESD_USB_CANUSB2_PRODUCT_ID 0x0010 #define ESD_USB_CANUSBM_PRODUCT_ID 0x0011 +#define ESD_USB_CANUSB3_PRODUCT_ID 0x0014 /* CAN controller clock frequencies */ #define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */ #define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */ +#define ESD_USB_3_CAN_CLOCK (80 * MEGA) /* Hz */ /* Maximum number of CAN nets */ #define ESD_USB_MAX_NETS 2 @@ -44,6 +46,9 @@ MODULE_LICENSE("GPL v2"); /* esd CAN message flags - dlc field */ #define ESD_USB_RTR BIT(4) +#define ESD_USB_NO_BRS BIT(4) +#define ESD_USB_ESI BIT(5) +#define ESD_USB_FD BIT(7) /* esd CAN message flags - id field */ #define ESD_USB_EXTID BIT(29) @@ -65,6 +70,9 @@ MODULE_LICENSE("GPL v2"); #define ESD_USB_M_SJW_SHIFT 24 #define ESD_USB_TRIPLE_SAMPLES BIT(23) +/* Transmitter Delay Compensation */ +#define ESD_USB_3_TDC_MODE_AUTO 0 + /* esd IDADD message */ #define ESD_USB_ID_ENABLE BIT(7) #define ESD_USB_MAX_ID_SEGMENT 64 @@ -88,6 +96,21 @@ MODULE_LICENSE("GPL v2"); #define ESD_USB_MAX_RX_URBS 4 #define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */ +/* Modes for CAN-USB/3, to be used for esd_usb_3_set_baudrate_msg_x.mode */ +#define ESD_USB_3_BAUDRATE_MODE_DISABLE 0 /* remove from bus */ +#define ESD_USB_3_BAUDRATE_MODE_INDEX 1 /* ESD (CiA) bit rate idx */ +#define ESD_USB_3_BAUDRATE_MODE_BTR_CTRL 2 /* BTR values (controller)*/ +#define ESD_USB_3_BAUDRATE_MODE_BTR_CANONICAL 3 /* BTR values (canonical) */ +#define ESD_USB_3_BAUDRATE_MODE_NUM 4 /* numerical bit rate */ +#define ESD_USB_3_BAUDRATE_MODE_AUTOBAUD 5 /* autobaud */ + +/* Flags for CAN-USB/3, to be used for esd_usb_3_set_baudrate_msg_x.flags */ +#define ESD_USB_3_BAUDRATE_FLAG_FD BIT(0) /* enable CAN FD mode */ +#define ESD_USB_3_BAUDRATE_FLAG_LOM BIT(1) /* enable listen only mode */ +#define ESD_USB_3_BAUDRATE_FLAG_STM BIT(2) /* enable self test mode */ +#define ESD_USB_3_BAUDRATE_FLAG_TRS BIT(3) /* enable triple sampling */ +#define ESD_USB_3_BAUDRATE_FLAG_TXP BIT(4) /* enable transmit pause */ + struct esd_usb_header_msg { u8 len; /* total message length in 32bit words */ u8 cmd; @@ -122,6 +145,7 @@ struct esd_usb_rx_msg { __le32 id; /* upper 3 bits contain flags */ union { u8 data[CAN_MAX_DLEN]; + u8 data_fd[CANFD_MAX_DLEN]; struct { u8 status; /* CAN Controller Status */ u8 ecc; /* Error Capture Register */ @@ -138,7 +162,10 @@ struct esd_usb_tx_msg { u8 dlc; u32 hnd; /* opaque handle, not used by device */ __le32 id; /* upper 3 bits contain flags */ - u8 data[CAN_MAX_DLEN]; + union { + u8 data[CAN_MAX_DLEN]; + u8 data_fd[CANFD_MAX_DLEN]; + }; }; struct esd_usb_tx_done_msg { @@ -166,6 +193,50 @@ struct esd_usb_set_baudrate_msg { __le32 baud; }; +/* CAN-USB/3 baudrate configuration, used for nominal as well as for data bit rate */ +struct esd_usb_3_baudrate_cfg { + __le16 brp; /* bit rate pre-scaler */ + __le16 tseg1; /* time segment before sample point */ + __le16 tseg2; /* time segment after sample point */ + __le16 sjw; /* synchronization jump Width */ +}; + +/* In principle, the esd CAN-USB/3 supports Transmitter Delay Compensation (TDC), + * but currently only the automatic TDC mode is supported by this driver. + * An implementation for manual TDC configuration will follow. + * + * For information about struct esd_usb_3_tdc_cfg, see + * NTCAN Application Developers Manual, 6.2.25 NTCAN_TDC_CFG + related chapters + * https://esd.eu/fileadmin/esd/docs/manuals/NTCAN_Part1_Function_API_Manual_en_56.pdf + */ +struct esd_usb_3_tdc_cfg { + u8 tdc_mode; /* transmitter delay compensation mode */ + u8 ssp_offset; /* secondary sample point offset in mtq */ + s8 ssp_shift; /* secondary sample point shift in mtq */ + u8 tdc_filter; /* TDC filter in mtq */ +}; + +/* Extended version of the above set_baudrate_msg for a CAN-USB/3 + * to define the CAN bit timing configuration of the CAN controller in + * CAN FD mode as well as in Classical CAN mode. + * + * The payload of this command is a NTCAN_BAUDRATE_X structure according to + * esd electronics gmbh, NTCAN Application Developers Manual, 6.2.15 NTCAN_BAUDRATE_X + * https://esd.eu/fileadmin/esd/docs/manuals/NTCAN_Part1_Function_API_Manual_en_56.pdf + */ +struct esd_usb_3_set_baudrate_msg_x { + u8 len; /* total message length in 32bit words */ + u8 cmd; + u8 net; + u8 rsvd; /*reserved */ + /* Payload ... */ + __le16 mode; /* mode word, see ESD_USB_3_BAUDRATE_MODE_xxx */ + __le16 flags; /* control flags, see ESD_USB_3_BAUDRATE_FLAG_xxx */ + struct esd_usb_3_tdc_cfg tdc; /* TDC configuration */ + struct esd_usb_3_baudrate_cfg nom; /* nominal bit rate */ + struct esd_usb_3_baudrate_cfg data; /* data bit rate */ +}; + /* Main message type used between library and application */ union __packed esd_usb_msg { struct esd_usb_header_msg hdr; @@ -175,12 +246,14 @@ union __packed esd_usb_msg { struct esd_usb_tx_msg tx; struct esd_usb_tx_done_msg txdone; struct esd_usb_set_baudrate_msg setbaud; + struct esd_usb_3_set_baudrate_msg_x setbaud_x; struct esd_usb_id_filter_msg filter; }; static struct usb_device_id esd_usb_table[] = { {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)}, {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB3_PRODUCT_ID)}, {} }; MODULE_DEVICE_TABLE(usb, esd_usb_table); @@ -321,9 +394,10 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, { struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; + struct canfd_frame *cfd; struct sk_buff *skb; - int i; u32 id; + u8 len; if (!netif_device_present(priv->netdev)) return; @@ -333,27 +407,42 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, if (id & ESD_USB_EVENT) { esd_usb_rx_event(priv, msg); } else { - skb = alloc_can_skb(priv->netdev, &cf); + if (msg->rx.dlc & ESD_USB_FD) { + skb = alloc_canfd_skb(priv->netdev, &cfd); + } else { + skb = alloc_can_skb(priv->netdev, &cf); + cfd = (struct canfd_frame *)cf; + } + if (skb == NULL) { stats->rx_dropped++; return; } - cf->can_id = id & ESD_USB_IDMASK; - can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR, - priv->can.ctrlmode); - - if (id & ESD_USB_EXTID) - cf->can_id |= CAN_EFF_FLAG; + cfd->can_id = id & ESD_USB_IDMASK; - if (msg->rx.dlc & ESD_USB_RTR) { - cf->can_id |= CAN_RTR_FLAG; + if (msg->rx.dlc & ESD_USB_FD) { + /* masking by 0x0F is already done within can_fd_dlc2len() */ + cfd->len = can_fd_dlc2len(msg->rx.dlc); + len = cfd->len; + if ((msg->rx.dlc & ESD_USB_NO_BRS) == 0) + cfd->flags |= CANFD_BRS; + if (msg->rx.dlc & ESD_USB_ESI) + cfd->flags |= CANFD_ESI; } else { - for (i = 0; i < cf->len; i++) - cf->data[i] = msg->rx.data[i]; - - stats->rx_bytes += cf->len; + can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR, priv->can.ctrlmode); + len = cf->len; + if (msg->rx.dlc & ESD_USB_RTR) { + cf->can_id |= CAN_RTR_FLAG; + len = 0; + } } + + if (id & ESD_USB_EXTID) + cfd->can_id |= CAN_EFF_FLAG; + + memcpy(cfd->data, msg->rx.data_fd, len); + stats->rx_bytes += len; stats->rx_packets++; netif_rx(skb); @@ -728,7 +817,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, struct esd_usb *dev = priv->usb; struct esd_tx_urb_context *context = NULL; struct net_device_stats *stats = &netdev->stats; - struct can_frame *cf = (struct can_frame *)skb->data; + struct canfd_frame *cfd = (struct canfd_frame *)skb->data; union esd_usb_msg *msg; struct urb *urb; u8 *buf; @@ -762,20 +851,29 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32); msg->hdr.cmd = ESD_USB_CMD_CAN_TX; msg->tx.net = priv->index; - msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); - msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); - if (cf->can_id & CAN_RTR_FLAG) - msg->tx.dlc |= ESD_USB_RTR; + if (can_is_canfd_skb(skb)) { + msg->tx.dlc = can_fd_len2dlc(cfd->len); + msg->tx.dlc |= ESD_USB_FD; + + if ((cfd->flags & CANFD_BRS) == 0) + msg->tx.dlc |= ESD_USB_NO_BRS; + } else { + msg->tx.dlc = can_get_cc_dlc((struct can_frame *)cfd, priv->can.ctrlmode); + + if (cfd->can_id & CAN_RTR_FLAG) + msg->tx.dlc |= ESD_USB_RTR; + } + + msg->tx.id = cpu_to_le32(cfd->can_id & CAN_ERR_MASK); - if (cf->can_id & CAN_EFF_FLAG) + if (cfd->can_id & CAN_EFF_FLAG) msg->tx.id |= cpu_to_le32(ESD_USB_EXTID); - for (i = 0; i < cf->len; i++) - msg->tx.data[i] = cf->data[i]; + memcpy(msg->tx.data_fd, cfd->data, cfd->len); /* round up, then divide by 4 to add the payload length as # of 32bit words */ - msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32)); + msg->hdr.len += DIV_ROUND_UP(cfd->len, sizeof(u32)); for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) { if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) { @@ -962,6 +1060,105 @@ static int esd_usb_2_set_bittiming(struct net_device *netdev) return err; } +/* Nominal bittiming constants, see + * Microchip SAM E70/S70/V70/V71, Data Sheet, Rev. G - 07/2022 + * 48.6.8 MCAN Nominal Bit Timing and Prescaler Register + */ +static const struct can_bittiming_const esd_usb_3_nom_bittiming_const = { + .name = "esd_usb_3", + .tseg1_min = 2, + .tseg1_max = 256, + .tseg2_min = 2, + .tseg2_max = 128, + .sjw_max = 128, + .brp_min = 1, + .brp_max = 512, + .brp_inc = 1, +}; + +/* Data bittiming constants, see + * Microchip SAM E70/S70/V70/V71, Data Sheet, Rev. G - 07/2022 + * 48.6.4 MCAN Data Bit Timing and Prescaler Register + */ +static const struct can_bittiming_const esd_usb_3_data_bittiming_const = { + .name = "esd_usb_3", + .tseg1_min = 2, + .tseg1_max = 32, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 8, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + +static int esd_usb_3_set_bittiming(struct net_device *netdev) +{ + const struct can_bittiming_const *nom_btc = &esd_usb_3_nom_bittiming_const; + const struct can_bittiming_const *data_btc = &esd_usb_3_data_bittiming_const; + struct esd_usb_net_priv *priv = netdev_priv(netdev); + struct can_bittiming *nom_bt = &priv->can.bittiming; + struct can_bittiming *data_bt = &priv->can.data_bittiming; + struct esd_usb_3_set_baudrate_msg_x *baud_x; + union esd_usb_msg *msg; + u16 flags = 0; + int err; + + msg = kmalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + baud_x = &msg->setbaud_x; + + /* Canonical is the most reasonable mode for SocketCAN on CAN-USB/3 ... */ + baud_x->mode = cpu_to_le16(ESD_USB_3_BAUDRATE_MODE_BTR_CANONICAL); + + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + flags |= ESD_USB_3_BAUDRATE_FLAG_LOM; + + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + flags |= ESD_USB_3_BAUDRATE_FLAG_TRS; + + baud_x->nom.brp = cpu_to_le16(nom_bt->brp & (nom_btc->brp_max - 1)); + baud_x->nom.sjw = cpu_to_le16(nom_bt->sjw & (nom_btc->sjw_max - 1)); + baud_x->nom.tseg1 = cpu_to_le16((nom_bt->prop_seg + nom_bt->phase_seg1) + & (nom_btc->tseg1_max - 1)); + baud_x->nom.tseg2 = cpu_to_le16(nom_bt->phase_seg2 & (nom_btc->tseg2_max - 1)); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + baud_x->data.brp = cpu_to_le16(data_bt->brp & (data_btc->brp_max - 1)); + baud_x->data.sjw = cpu_to_le16(data_bt->sjw & (data_btc->sjw_max - 1)); + baud_x->data.tseg1 = cpu_to_le16((data_bt->prop_seg + data_bt->phase_seg1) + & (data_btc->tseg1_max - 1)); + baud_x->data.tseg2 = cpu_to_le16(data_bt->phase_seg2 & (data_btc->tseg2_max - 1)); + flags |= ESD_USB_3_BAUDRATE_FLAG_FD; + } + + /* Currently this driver only supports the automatic TDC mode */ + baud_x->tdc.tdc_mode = ESD_USB_3_TDC_MODE_AUTO; + baud_x->tdc.ssp_offset = 0; + baud_x->tdc.ssp_shift = 0; + baud_x->tdc.tdc_filter = 0; + + baud_x->flags = cpu_to_le16(flags); + baud_x->net = priv->index; + baud_x->rsvd = 0; + + /* set len as # of 32bit words */ + msg->hdr.len = sizeof(struct esd_usb_3_set_baudrate_msg_x) / sizeof(u32); + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; + + netdev_dbg(netdev, + "ctrlmode=%#x/%#x, esd-net=%u, esd-mode=%#x, esd-flags=%#x\n", + priv->can.ctrlmode, priv->can.ctrlmode_supported, + priv->index, le16_to_cpu(baud_x->mode), flags); + + err = esd_usb_send_msg(priv->usb, msg); + + kfree(msg); + return err; +} + static int esd_usb_get_berr_counter(const struct net_device *netdev, struct can_berr_counter *bec) { @@ -1019,16 +1216,32 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_BERR_REPORTING; - if (le16_to_cpu(dev->udev->descriptor.idProduct) == - ESD_USB_CANUSBM_PRODUCT_ID) + switch (le16_to_cpu(dev->udev->descriptor.idProduct)) { + case ESD_USB_CANUSB3_PRODUCT_ID: + priv->can.clock.freq = ESD_USB_3_CAN_CLOCK; + priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const; + priv->can.data_bittiming_const = &esd_usb_3_data_bittiming_const; + priv->can.do_set_bittiming = esd_usb_3_set_bittiming; + priv->can.do_set_data_bittiming = esd_usb_3_set_bittiming; + break; + + case ESD_USB_CANUSBM_PRODUCT_ID: priv->can.clock.freq = ESD_USB_M_CAN_CLOCK; - else { + priv->can.bittiming_const = &esd_usb_2_bittiming_const; + priv->can.do_set_bittiming = esd_usb_2_set_bittiming; + break; + + case ESD_USB_CANUSB2_PRODUCT_ID: + default: priv->can.clock.freq = ESD_USB_2_CAN_CLOCK; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + priv->can.bittiming_const = &esd_usb_2_bittiming_const; + priv->can.do_set_bittiming = esd_usb_2_set_bittiming; + break; } - priv->can.bittiming_const = &esd_usb_2_bittiming_const; - priv->can.do_set_bittiming = esd_usb_2_set_bittiming; priv->can.do_set_mode = esd_usb_set_mode; priv->can.do_get_berr_counter = esd_usb_get_berr_counter; -- cgit From f11e5bd159b08976db9e7a9eabbf0318dfe5429d Mon Sep 17 00:00:00 2001 From: Mateusz Kowalski Date: Tue, 1 Aug 2023 14:37:50 +0200 Subject: bonding: support balance-alb with openvswitch Commit d5410ac7b0ba ("net:bonding:support balance-alb interface with vlan to bridge") introduced a support for balance-alb mode for interfaces connected to the linux bridge by fixing missing matching of MAC entry in FDB. In our testing we discovered that it still does not work when the bond is connected to the OVS bridge as show in diagram below: eth1(mac:eth1_mac)--bond0(balance-alb,mac:eth0_mac)--eth0(mac:eth0_mac) | bond0.150(mac:eth0_mac) | ovs_bridge(ip:bridge_ip,mac:eth0_mac) This patch fixes it by checking not only if the device is a bridge but also if it is an openvswitch. Signed-off-by: Mateusz Kowalski Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/9fe7297c-609e-208b-c77b-3ceef6eb51a4@redhat.com Signed-off-by: Paolo Abeni --- drivers/net/bonding/bond_alb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index b9dbad3a8af8..cc5049eb25f8 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -668,7 +668,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) dev = ip_dev_find(dev_net(bond->dev), arp->ip_src); if (dev) { - if (netif_is_bridge_master(dev)) { + if (netif_is_any_bridge_master(dev)) { dev_put(dev); return NULL; } -- cgit From e22f5b780c691ae2ed0d5e7743ccd6183baf5dc2 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:00 +0300 Subject: wifi: ath12k: rename HE capabilities setup/copy functions Functions ath12k_mac_setup_he_cap() and ath12k_mac_copy_he_cap() propagate HE and 6GHz capabilities to the userspace using an instance of struct ieee80211_sband_iftype_data. This structure now has a new member 'eht_cap' to include EHT capabilities as well. Rename the above mentioned functions to indicate that their use is not limited to HE. Also, replace the local variable 'band' with 'sband' and reuse 'band' for the type enum nl80211_band. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-2-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 4fa565a115e3..4d04b6f67043 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4222,10 +4222,10 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap, return cpu_to_le16(bcap->he_6ghz_capa); } -static int ath12k_mac_copy_he_cap(struct ath12k *ar, - struct ath12k_pdev_cap *cap, - struct ieee80211_sband_iftype_data *data, - int band) +static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, + struct ath12k_pdev_cap *cap, + struct ieee80211_sband_iftype_data *data, + int band) { int i, idx = 0; @@ -4310,38 +4310,42 @@ static int ath12k_mac_copy_he_cap(struct ath12k *ar, return idx; } -static void ath12k_mac_setup_he_cap(struct ath12k *ar, - struct ath12k_pdev_cap *cap) +static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar, + struct ath12k_pdev_cap *cap) { - struct ieee80211_supported_band *band; + struct ieee80211_supported_band *sband; + enum nl80211_band band; int count; if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) { - count = ath12k_mac_copy_he_cap(ar, cap, - ar->mac.iftype[NL80211_BAND_2GHZ], - NL80211_BAND_2GHZ); - band = &ar->mac.sbands[NL80211_BAND_2GHZ]; - band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ]; - band->n_iftype_data = count; + band = NL80211_BAND_2GHZ; + count = ath12k_mac_copy_sband_iftype_data(ar, cap, + ar->mac.iftype[band], + band); + sband = &ar->mac.sbands[band]; + sband->iftype_data = ar->mac.iftype[band]; + sband->n_iftype_data = count; } if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) { - count = ath12k_mac_copy_he_cap(ar, cap, - ar->mac.iftype[NL80211_BAND_5GHZ], - NL80211_BAND_5GHZ); - band = &ar->mac.sbands[NL80211_BAND_5GHZ]; - band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ]; - band->n_iftype_data = count; + band = NL80211_BAND_5GHZ; + count = ath12k_mac_copy_sband_iftype_data(ar, cap, + ar->mac.iftype[band], + band); + sband = &ar->mac.sbands[band]; + sband->iftype_data = ar->mac.iftype[band]; + sband->n_iftype_data = count; } if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) { - count = ath12k_mac_copy_he_cap(ar, cap, - ar->mac.iftype[NL80211_BAND_6GHZ], - NL80211_BAND_6GHZ); - band = &ar->mac.sbands[NL80211_BAND_6GHZ]; - band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ]; - band->n_iftype_data = count; + band = NL80211_BAND_6GHZ; + count = ath12k_mac_copy_sband_iftype_data(ar, cap, + ar->mac.iftype[band], + band); + sband = &ar->mac.sbands[band]; + sband->iftype_data = ar->mac.iftype[band]; + sband->n_iftype_data = count; } } @@ -4386,7 +4390,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant) /* Reload HT/VHT/HE capability */ ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL); - ath12k_mac_setup_he_cap(ar, &ar->pdev->cap); + ath12k_mac_setup_sband_iftype_data(ar, &ar->pdev->cap); return 0; } @@ -6888,7 +6892,7 @@ static int __ath12k_mac_register(struct ath12k *ar) goto err; ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap); - ath12k_mac_setup_he_cap(ar, cap); + ath12k_mac_setup_sband_iftype_data(ar, cap); ret = ath12k_mac_setup_iface_combinations(ar); if (ret) { -- cgit From a7a6a45d37fe868b30363255d3a37a44acd1cf37 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:01 +0300 Subject: wifi: ath12k: move HE capabilities processing to a new function The function ath12k_mac_copy_sband_iftype_data() is currently used HE capabilities propagation but it can be extended to include EHT data. Move the HE specific functionality from to ath12k_mac_copy_he_cap() to make EHT additions easier. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-3-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 111 +++++++++++++++++----------------- 1 file changed, 55 insertions(+), 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 4d04b6f67043..8fedbf4879d6 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4222,18 +4222,69 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap, return cpu_to_le16(bcap->he_6ghz_capa); } +static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap, + int iftype, u8 num_tx_chains, + struct ieee80211_sta_he_cap *he_cap) +{ + struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; + struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp; + + he_cap->has_he = true; + memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info, + sizeof(he_cap_elem->mac_cap_info)); + memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info, + sizeof(he_cap_elem->phy_cap_info)); + + he_cap_elem->mac_cap_info[1] &= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; + + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK; + he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1; + + switch (iftype) { + case NL80211_IFTYPE_AP: + he_cap_elem->phy_cap_info[3] &= + ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; + break; + case NL80211_IFTYPE_STATION: + he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES; + he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; + break; + case NL80211_IFTYPE_MESH_POINT: + ath12k_mac_filter_he_cap_mesh(he_cap_elem); + break; + } + + mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); + mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff); + mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) + ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres); +} + static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, struct ath12k_pdev_cap *cap, struct ieee80211_sband_iftype_data *data, int band) { + struct ath12k_band_cap *band_cap = &cap->band[band]; int i, idx = 0; for (i = 0; i < NUM_NL80211_IFTYPES; i++) { struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap; - struct ath12k_band_cap *band_cap = &cap->band[band]; - struct ieee80211_he_cap_elem *he_cap_elem = - &he_cap->he_cap_elem; switch (i) { case NL80211_IFTYPE_STATION: @@ -4246,60 +4297,8 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, } data[idx].types_mask = BIT(i); - he_cap->has_he = true; - memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info, - sizeof(he_cap_elem->mac_cap_info)); - memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info, - sizeof(he_cap_elem->phy_cap_info)); - - he_cap_elem->mac_cap_info[1] &= - IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; - - he_cap_elem->phy_cap_info[5] &= - ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; - he_cap_elem->phy_cap_info[5] &= - ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK; - he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1; - - switch (i) { - case NL80211_IFTYPE_AP: - he_cap_elem->phy_cap_info[3] &= - ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK; - he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; - break; - case NL80211_IFTYPE_STATION: - he_cap_elem->mac_cap_info[0] &= - ~IEEE80211_HE_MAC_CAP0_TWT_RES; - he_cap_elem->mac_cap_info[0] |= - IEEE80211_HE_MAC_CAP0_TWT_REQ; - he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; - break; - case NL80211_IFTYPE_MESH_POINT: - ath12k_mac_filter_he_cap_mesh(he_cap_elem); - break; - } - - he_cap->he_mcs_nss_supp.rx_mcs_80 = - cpu_to_le16(band_cap->he_mcs & 0xffff); - he_cap->he_mcs_nss_supp.tx_mcs_80 = - cpu_to_le16(band_cap->he_mcs & 0xffff); - he_cap->he_mcs_nss_supp.rx_mcs_160 = - cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); - he_cap->he_mcs_nss_supp.tx_mcs_160 = - cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); - he_cap->he_mcs_nss_supp.rx_mcs_80p80 = - cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); - he_cap->he_mcs_nss_supp.tx_mcs_80p80 = - cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); - - memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); - if (he_cap_elem->phy_cap_info[6] & - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) - ath12k_gen_ppe_thresh(&band_cap->he_ppet, - he_cap->ppe_thres); + ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap); if (band == NL80211_BAND_6GHZ) { data[idx].he_6ghz_capa.capa = ath12k_mac_setup_he_6ghz_cap(cap, band_cap); -- cgit From 1476014fadb6625c6720c4439ff0c4b5b5431137 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:02 +0300 Subject: wifi: ath12k: WMI support to process EHT capabilities Add WMI support to process the EHT capabilities passed by the firmware. Add required EHT specific definitions in structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse. For single_pdev chip such as WCN7850, only one pdev is created and only one hardware is registered to mac80211. This one pdev manages both 2.4 GHz radio and 5 GHz/6 GHz radio. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Aloka Dixit Co-developed-by: Pradeep Kumar Chitrapu Signed-off-by: Pradeep Kumar Chitrapu Co-developed-by: Wen Gong Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-4-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/core.h | 33 ++++++++ drivers/net/wireless/ath/ath12k/wmi.c | 147 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 38 +++++++++ 3 files changed, 218 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 2f93296db792..d0b625fea633 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -580,6 +580,14 @@ struct ath12k_band_cap { u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE]; struct ath12k_wmi_ppe_threshold_arg he_ppet; u16 he_6ghz_capa; + u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 eht_cap_phy_info[WMI_MAX_EHTCAP_PHY_SIZE]; + u32 eht_mcs_20_only; + u32 eht_mcs_80; + u32 eht_mcs_160; + u32 eht_mcs_320; + struct ath12k_wmi_ppe_threshold_arg eht_ppet; + u32 eht_cap_info_internal; }; struct ath12k_pdev_cap { @@ -614,6 +622,12 @@ struct ath12k_pdev { struct mlo_timestamp timestamp; }; +struct ath12k_fw_pdev { + u32 pdev_id; + u32 phy_id; + u32 supported_bands; +}; + struct ath12k_board_data { const struct firmware *fw; const void *data; @@ -669,7 +683,26 @@ struct ath12k_base { struct mutex core_lock; /* Protects data like peers */ spinlock_t base_lock; + + /* Single pdev device (struct ath12k_hw_params::single_pdev_only): + * + * Firmware maintains data for all bands but advertises a single + * phy to the host which is stored as a single element in this + * array. + * + * Other devices: + * + * This array will contain as many elements as the number of + * radios. + */ struct ath12k_pdev pdevs[MAX_RADIOS]; + + /* struct ath12k_hw_params::single_pdev_only devices use this to + * store phy specific data + */ + struct ath12k_fw_pdev fw_pdev[MAX_RADIOS]; + u8 fw_pdev_count; + struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS]; struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS]; unsigned long long free_vdev_map; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index e6033ab15825..63e6c08c767c 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -65,6 +65,8 @@ struct ath12k_wmi_svc_rdy_ext_parse { struct ath12k_wmi_svc_rdy_ext2_parse { struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse; bool dma_ring_cap_done; + bool spectral_bin_scaling_done; + bool mac_phy_caps_ext_done; }; struct ath12k_wmi_rdy_parse { @@ -445,8 +447,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps; const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps; const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps; + struct ath12k_base *ab = wmi_handle->wmi_ab->ab; struct ath12k_band_cap *cap_band; struct ath12k_pdev_cap *pdev_cap = &pdev->cap; + struct ath12k_fw_pdev *fw_pdev; u32 phy_map; u32 hw_idx, phy_idx = 0; int i; @@ -475,6 +479,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands); pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density); + fw_pdev = &ab->fw_pdev[ab->fw_pdev_count]; + fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands); + fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id); + fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id); + ab->fw_pdev_count++; + /* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from * band to band for a single radio, need to see how this should be * handled. @@ -3815,6 +3825,7 @@ static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc, soc->num_radios = 0; phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map); + soc->fw_pdev_count = 0; while (phy_id_map && soc->num_radios < MAX_RADIOS) { ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle, @@ -4042,6 +4053,125 @@ err: return ret; } +static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band, + const __le32 cap_mac_info[], + const __le32 cap_phy_info[], + const __le32 supp_mcs[], + const struct ath12k_wmi_ppe_threshold_params *ppet, + __le32 cap_info_internal) +{ + struct ath12k_band_cap *cap_band = &pdev->cap.band[band]; + u8 i; + + for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++) + cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]); + + for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++) + cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]); + + cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]); + cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]); + if (band != NL80211_BAND_2GHZ) { + cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]); + cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]); + } + + cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1); + cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info); + for (i = 0; i < WMI_MAX_NUM_SS; i++) + cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] = + le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]); + + cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal); +} + +static int +ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab, + const struct ath12k_wmi_caps_ext_params *caps, + struct ath12k_pdev *pdev) +{ + u32 bands; + int i; + + if (ab->hw_params->single_pdev_only) { + for (i = 0; i < ab->fw_pdev_count; i++) { + struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i]; + + if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) && + fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) { + bands = fw_pdev->supported_bands; + break; + } + } + + if (i == ab->fw_pdev_count) + return -EINVAL; + } else { + bands = pdev->cap.supported_bands; + } + + if (bands & WMI_HOST_WLAN_2G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ, + caps->eht_cap_mac_info_2ghz, + caps->eht_cap_phy_info_2ghz, + caps->eht_supp_mcs_ext_2ghz, + &caps->eht_ppet_2ghz, + caps->eht_cap_info_internal); + } + + if (bands & WMI_HOST_WLAN_5G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + } + + return 0; +} + +static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag, + u16 len, const void *ptr, + void *data) +{ + const struct ath12k_wmi_caps_ext_params *caps = ptr; + int i = 0, ret; + + if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT) + return -EPROTO; + + if (ab->hw_params->single_pdev_only) { + if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id)) + return 0; + } else { + for (i = 0; i < ab->num_radios; i++) { + if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id)) + break; + } + + if (i == ab->num_radios) + return -EINVAL; + } + + ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]); + if (ret) { + ath12k_warn(ab, + "failed to parse extended MAC PHY capabilities for pdev %d: %d\n", + ret, ab->pdevs[i].pdev_id); + return ret; + } + + return 0; +} + static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) @@ -4058,6 +4188,23 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, return ret; parse->dma_ring_cap_done = true; + } else if (!parse->spectral_bin_scaling_done) { + /* TODO: This is a place-holder as WMI tag for + * spectral scaling is before + * WMI_TAG_MAC_PHY_CAPABILITIES_EXT + */ + parse->spectral_bin_scaling_done = true; + } else if (!parse->mac_phy_caps_ext_done) { + ret = ath12k_wmi_tlv_iter(ab, ptr, len, + ath12k_wmi_tlv_mac_phy_caps_ext, + parse); + if (ret) { + ath12k_warn(ab, "failed to parse extended MAC PHY capabilities WMI TLV: %d\n", + ret); + return ret; + } + + parse->mac_phy_caps_ext_done = true; } break; default: diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 9b8ba8704904..bafcaa7f1629 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2581,6 +2581,44 @@ struct ath12k_wmi_soc_hal_reg_caps_params { __le32 num_phy; } __packed; +#define WMI_MAX_EHTCAP_MAC_SIZE 2 +#define WMI_MAX_EHTCAP_PHY_SIZE 3 + +/* Used for EHT MCS-NSS array. Data at each array index follows the format given + * in IEEE P802.11be/D2.0, May 20229.4.2.313.4. + * + * Index interpretation: + * 0 - 20 MHz only sta, all 4 bytes valid + * 1 - index for bandwidths <= 80 MHz except 20 MHz-only, first 3 bytes valid + * 2 - index for 160 MHz, first 3 bytes valid + * 3 - index for 320 MHz, first 3 bytes valid + */ +#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2 +#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4 + +struct ath12k_wmi_caps_ext_params { + __le32 hw_mode_id; + union { + struct { + __le16 pdev_id; + __le16 hw_link_id; + } __packed ath12k_wmi_pdev_to_link_map; + __le32 pdev_id; + }; + __le32 phy_id; + __le32 wireless_modes_ext; + __le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 eht_cap_mac_info_5ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 rsvd0[2]; + __le32 eht_cap_phy_info_2ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + __le32 eht_cap_phy_info_5ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz; + struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz; + __le32 eht_cap_info_internal; + __le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE]; + __le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE]; +} __packed; + /* 2 word representation of MAC addr */ struct ath12k_wmi_mac_addr_params { u8 addr[ETH_ALEN]; -- cgit From dbe90679bfa1287651b8bb8304b7ce46b00a5f81 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:02 +0300 Subject: wifi: ath12k: propagate EHT capabilities to userspace Propagate EHT capabilities to the userspace using a new member 'eht_cap' in structure ieee80211_sband_iftype_data. MCS-NSS capabilities are copied depending on the supported bandwidths for the given band. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-5-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 111 ++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 8fedbf4879d6..c64cd8079e20 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4275,6 +4275,115 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap, ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres); } +static void +ath12k_mac_copy_eht_mcs_nss(struct ath12k_band_cap *band_cap, + struct ieee80211_eht_mcs_nss_supp *mcs_nss, + const struct ieee80211_he_cap_elem *he_cap, + const struct ieee80211_eht_cap_elem_fixed *eht_cap) +{ + if ((he_cap->phy_cap_info[0] & + (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) + memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only, + sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only)); + + if (he_cap->phy_cap_info[0] & + (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) + memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80, + sizeof(struct ieee80211_eht_mcs_nss_supp_bw)); + + if (he_cap->phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160, + sizeof(struct ieee80211_eht_mcs_nss_supp_bw)); + + if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320, + sizeof(struct ieee80211_eht_mcs_nss_supp_bw)); +} + +static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet, + struct ieee80211_sta_eht_cap *cap) +{ + u16 bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE; + u8 i, nss, ru, ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2; + + u8p_replace_bits(&cap->eht_ppe_thres[0], fw_ppet->numss_m1, + IEEE80211_EHT_PPE_THRES_NSS_MASK); + + u16p_replace_bits((u16 *)&cap->eht_ppe_thres[0], fw_ppet->ru_bit_mask, + IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); + + for (nss = 0; nss <= fw_ppet->numss_m1; nss++) { + for (ru = 0; + ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); + ru++) { + u32 val = 0; + + if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0) + continue; + + u32p_replace_bits(&val, fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> + (ru * ppet_bit_len_per_ru), + GENMASK(ppet_bit_len_per_ru - 1, 0)); + + for (i = 0; i < ppet_bit_len_per_ru; i++) { + cap->eht_ppe_thres[bit / 8] |= + (((val >> i) & 0x1) << ((bit % 8))); + bit++; + } + } + } +} + +static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap, + struct ieee80211_he_cap_elem *he_cap_elem, + int iftype, + struct ieee80211_sta_eht_cap *eht_cap) +{ + struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem; + + memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap)); + eht_cap->has_eht = true; + memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info, + sizeof(eht_cap_elem->mac_cap_info)); + memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info, + sizeof(eht_cap_elem->phy_cap_info)); + + switch (iftype) { + case NL80211_IFTYPE_AP: + eht_cap_elem->phy_cap_info[0] &= + ~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ; + eht_cap_elem->phy_cap_info[4] &= + ~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO; + eht_cap_elem->phy_cap_info[5] &= + ~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP; + break; + case NL80211_IFTYPE_STATION: + eht_cap_elem->phy_cap_info[7] &= + ~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ); + eht_cap_elem->phy_cap_info[7] &= + ~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ); + break; + default: + break; + } + + ath12k_mac_copy_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp, + he_cap_elem, eht_cap_elem); + + if (eht_cap_elem->phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) + ath12k_mac_copy_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap); +} + static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, struct ath12k_pdev_cap *cap, struct ieee80211_sband_iftype_data *data, @@ -4303,6 +4412,8 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, data[idx].he_6ghz_capa.capa = ath12k_mac_setup_he_6ghz_cap(cap, band_cap); } + ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i, + &data[idx].eht_cap); idx++; } -- cgit From 38013653a69734e2bcf84ce951f7a4aee3966320 Mon Sep 17 00:00:00 2001 From: Muna Sinada Date: Wed, 2 Aug 2023 20:04:03 +0300 Subject: wifi: ath12k: add EHT PHY modes Add support to retrieve and configure the phy modes supported by the hardware. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Muna Sinada Signed-off-by: Aloka Dixit Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-6-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 101 +++++++++++++++++++++++++++------- drivers/net/wireless/ath/ath12k/mac.h | 2 +- drivers/net/wireless/ath/ath12k/wmi.h | 13 ++++- 3 files changed, 94 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index c64cd8079e20..8ea1ac5ab356 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -182,32 +182,35 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = { [NL80211_BAND_2GHZ] = { [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN, - [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G, - [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G, - [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G, - [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G, + [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20_2G, + [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20_2G, + [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40_2G, + [NL80211_CHAN_WIDTH_80] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN, + [NL80211_CHAN_WIDTH_320] = MODE_UNKNOWN, }, [NL80211_BAND_5GHZ] = { [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN, - [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20, - [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20, - [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40, - [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80, - [NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160, - [NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80, + [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20, + [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20, + [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40, + [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80, + [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160, + [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80, + [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320, }, [NL80211_BAND_6GHZ] = { [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN, - [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20, - [NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20, - [NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40, - [NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80, - [NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160, - [NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80, + [NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20, + [NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20, + [NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40, + [NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80, + [NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160, + [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80, + [NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320, }, }; @@ -292,6 +295,24 @@ static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode) return "11ax-he40-2g"; case MODE_11AX_HE80_2G: return "11ax-he80-2g"; + case MODE_11BE_EHT20: + return "11be-eht20"; + case MODE_11BE_EHT40: + return "11be-eht40"; + case MODE_11BE_EHT80: + return "11be-eht80"; + case MODE_11BE_EHT80_80: + return "11be-eht80+80"; + case MODE_11BE_EHT160: + return "11be-eht160"; + case MODE_11BE_EHT160_160: + return "11be-eht160+160"; + case MODE_11BE_EHT320: + return "11be-eht320"; + case MODE_11BE_EHT20_2G: + return "11be-eht20-2g"; + case MODE_11BE_EHT40_2G: + return "11be-eht40-2g"; case MODE_UNKNOWN: /* skip */ break; @@ -1929,6 +1950,41 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar, return MODE_UNKNOWN; } +static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar, + struct ieee80211_sta *sta) +{ + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) + if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return MODE_11BE_EHT320; + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { + if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11BE_EHT160; + + if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) + return MODE_11BE_EHT80_80; + + ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n", + sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]); + + return MODE_11BE_EHT160; + } + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11BE_EHT80; + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11BE_EHT40; + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11BE_EHT20; + + return MODE_UNKNOWN; +} + static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1950,7 +2006,12 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, switch (band) { case NL80211_BAND_2GHZ: - if (sta->deflink.he_cap.has_he) { + if (sta->deflink.eht_cap.has_eht) { + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11BE_EHT40_2G; + else + phymode = MODE_11BE_EHT20_2G; + } else if (sta->deflink.he_cap.has_he) { if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) phymode = MODE_11AX_HE80_2G; else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) @@ -1977,8 +2038,10 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, break; case NL80211_BAND_5GHZ: case NL80211_BAND_6GHZ: - /* Check HE first */ - if (sta->deflink.he_cap.has_he) { + /* Check EHT first */ + if (sta->deflink.eht_cap.has_eht) { + phymode = ath12k_mac_get_phymode_eht(ar, sta); + } else if (sta->deflink.he_cap.has_he) { phymode = ath12k_mac_get_phymode_he(ar, sta); } else if (sta->deflink.vht_cap.vht_supported && !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 57f4295420bb..7b16b70df4fa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -33,7 +33,7 @@ struct ath12k_generic_iter { #define IEEE80211_VHT_MCS_SUPPORT_0_11_MASK GENMASK(23, 16) #define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24) -#define ATH12K_CHAN_WIDTH_NUM 8 +#define ATH12K_CHAN_WIDTH_NUM 14 #define ATH12K_TX_POWER_MAX_VAL 70 #define ATH12K_TX_POWER_MIN_VAL 0 diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index bafcaa7f1629..0aa73908a65f 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2796,8 +2796,17 @@ enum wmi_phy_mode { MODE_11AX_HE20_2G = 21, MODE_11AX_HE40_2G = 22, MODE_11AX_HE80_2G = 23, - MODE_UNKNOWN = 24, - MODE_MAX = 24 + MODE_11BE_EHT20 = 24, + MODE_11BE_EHT40 = 25, + MODE_11BE_EHT80 = 26, + MODE_11BE_EHT80_80 = 27, + MODE_11BE_EHT160 = 28, + MODE_11BE_EHT160_160 = 29, + MODE_11BE_EHT320 = 30, + MODE_11BE_EHT20_2G = 31, + MODE_11BE_EHT40_2G = 32, + MODE_UNKNOWN = 33, + MODE_MAX = 33, }; struct wmi_vdev_start_req_arg { -- cgit From 17bbb8aa74fded03527427c25f43a29590c6a9ab Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:04 +0300 Subject: wifi: ath12k: prepare EHT peer assoc parameters Add new parameters and prepare the association data for an EHT peer. MCS data uses the format described in IEEE P802.11be/D2.0, May 2022, 9.4.2.313.4, convert it into the format expected by the firmware. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-7-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/mac.c | 144 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 17 ++++ 2 files changed, 161 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 8ea1ac5ab356..5b7a892e1f79 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -2067,6 +2067,149 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, WARN_ON(phymode == MODE_UNKNOWN); } +static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9, + u8 rx_tx_mcs11, u8 rx_tx_mcs13, + u32 *rx_mcs, u32 *tx_mcs) +{ + *rx_mcs = 0; + u32p_replace_bits(rx_mcs, + u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX), + WMI_EHT_MCS_NSS_0_7); + u32p_replace_bits(rx_mcs, + u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX), + WMI_EHT_MCS_NSS_8_9); + u32p_replace_bits(rx_mcs, + u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX), + WMI_EHT_MCS_NSS_10_11); + u32p_replace_bits(rx_mcs, + u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX), + WMI_EHT_MCS_NSS_12_13); + + *tx_mcs = 0; + u32p_replace_bits(tx_mcs, + u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX), + WMI_EHT_MCS_NSS_0_7); + u32p_replace_bits(tx_mcs, + u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX), + WMI_EHT_MCS_NSS_8_9); + u32p_replace_bits(tx_mcs, + u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX), + WMI_EHT_MCS_NSS_10_11); + u32p_replace_bits(tx_mcs, + u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX), + WMI_EHT_MCS_NSS_12_13); +} + +static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres, + struct ath12k_wmi_ppe_threshold_arg *ppet) +{ + u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE, val; + u8 nss, ru, i; + u8 ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2; + + ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK); + ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres), + IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); + + for (nss = 0; nss <= ppet->numss_m1; nss++) { + for (ru = 0; + ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); + ru++) { + if ((ppet->ru_bit_mask & BIT(ru)) == 0) + continue; + + val = 0; + for (i = 0; i < ppet_bit_len_per_ru; i++) { + val |= (((ppe_thres[bit_pos / 8] >> + (bit_pos % 8)) & 0x1) << i); + bit_pos++; + } + ppet->ppet16_ppet8_ru3_ru0[nss] |= + (val << (ru * ppet_bit_len_per_ru)); + } + } +} + +static void ath12k_peer_assoc_h_eht(struct ath12k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ath12k_wmi_peer_assoc_arg *arg) +{ + const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; + const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; + const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20; + const struct ieee80211_eht_mcs_nss_supp_bw *bw; + u32 *rx_mcs, *tx_mcs; + + if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) + return; + + arg->eht_flag = true; + + if ((eht_cap->eht_cap_elem.phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) && + eht_cap->eht_ppe_thres[0] != 0) + ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres, + &arg->peer_eht_ppet); + + memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info, + sizeof(eht_cap->eht_cap_elem.mac_cap_info)); + memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info, + sizeof(eht_cap->eht_cap_elem.phy_cap_info)); + + rx_mcs = arg->peer_eht_rx_mcs_set; + tx_mcs = arg->peer_eht_tx_mcs_set; + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_320: + bw = &eht_cap->eht_mcs_nss_supp.bw._320; + ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs11_max_nss, + bw->rx_tx_mcs13_max_nss, + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320], + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]); + arg->peer_eht_mcs_count++; + fallthrough; + case IEEE80211_STA_RX_BW_160: + bw = &eht_cap->eht_mcs_nss_supp.bw._160; + ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs11_max_nss, + bw->rx_tx_mcs13_max_nss, + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160], + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]); + arg->peer_eht_mcs_count++; + fallthrough; + default: + if ((he_cap->he_cap_elem.phy_cap_info[0] & + (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) { + bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz; + + ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss, + bw_20->rx_tx_mcs9_max_nss, + bw_20->rx_tx_mcs11_max_nss, + bw_20->rx_tx_mcs13_max_nss, + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80], + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]); + } else { + bw = &eht_cap->eht_mcs_nss_supp.bw._80; + ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs9_max_nss, + bw->rx_tx_mcs11_max_nss, + bw->rx_tx_mcs13_max_nss, + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80], + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]); + } + + arg->peer_eht_mcs_count++; + break; + } +} + static void ath12k_peer_assoc_prepare(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2086,6 +2229,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, ath12k_peer_assoc_h_ht(ar, vif, sta, arg); ath12k_peer_assoc_h_vht(ar, vif, sta, arg); ath12k_peer_assoc_h_he(ar, vif, sta, arg); + ath12k_peer_assoc_h_eht(ar, vif, sta, arg); ath12k_peer_assoc_h_qos(ar, vif, sta, arg); ath12k_peer_assoc_h_phymode(ar, vif, sta, arg); ath12k_peer_assoc_h_smps(sta, arg); diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 0aa73908a65f..dae895b479c7 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2583,6 +2583,7 @@ struct ath12k_wmi_soc_hal_reg_caps_params { #define WMI_MAX_EHTCAP_MAC_SIZE 2 #define WMI_MAX_EHTCAP_PHY_SIZE 3 +#define WMI_MAX_EHTCAP_RATE_SET 3 /* Used for EHT MCS-NSS array. Data at each array index follows the format given * in IEEE P802.11be/D2.0, May 20229.4.2.313.4. @@ -2596,6 +2597,15 @@ struct ath12k_wmi_soc_hal_reg_caps_params { #define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2 #define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4 +#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_80 0 +#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_160 1 +#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_320 2 + +#define WMI_EHT_MCS_NSS_0_7 GENMASK(3, 0) +#define WMI_EHT_MCS_NSS_8_9 GENMASK(7, 4) +#define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8) +#define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12) + struct ath12k_wmi_caps_ext_params { __le32 hw_mode_id; union { @@ -3564,6 +3574,13 @@ struct ath12k_wmi_peer_assoc_arg { bool twt_responder; bool twt_requester; struct ath12k_wmi_ppe_threshold_arg peer_ppet; + bool eht_flag; + u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; + u32 peer_eht_mcs_count; + u32 peer_eht_rx_mcs_set[WMI_MAX_EHTCAP_RATE_SET]; + u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET]; + struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet; }; struct wmi_peer_assoc_complete_cmd { -- cgit From 5b70ec6036c1c755fd1c1aa80ace3d349d91f3a5 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:04 +0300 Subject: wifi: ath12k: add WMI support for EHT peer Add new WMI tag and pass the EHT parameters for peer association to firmware. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-8-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 40 ++++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath12k/wmi.h | 20 ++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 63e6c08c767c..b1bc227ad54e 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -1801,6 +1801,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, bool hw_crypto_disabled) { cmd->peer_flags = 0; + cmd->peer_flags_ext = 0; if (arg->is_wme_set) { if (arg->qos_flag) @@ -1842,6 +1843,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_REQ); if (arg->twt_responder) cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_RESP); + if (arg->eht_flag) + cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_EHT); } /* Suppress authorization for all AUTH modes that need 4-way handshake @@ -1886,6 +1889,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, struct wmi_peer_assoc_complete_cmd *cmd; struct ath12k_wmi_vht_rate_set_params *mcs; struct ath12k_wmi_he_rate_set_params *he_mcs; + struct ath12k_wmi_eht_rate_set_params *eht_mcs; struct sk_buff *skb; struct wmi_tlv *tlv; void *ptr; @@ -1902,7 +1906,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) + TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) + sizeof(*mcs) + TLV_HDR_SIZE + - (sizeof(*he_mcs) * arg->peer_he_mcs_count); + (sizeof(*he_mcs) * arg->peer_he_mcs_count) + + TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count); skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) @@ -1949,6 +1954,16 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, cmd->peer_ppet.ppet16_ppet8_ru3_ru0[i] = cpu_to_le32(arg->peer_ppet.ppet16_ppet8_ru3_ru0[i]); + /* Update 11be capabilities */ + memcpy_and_pad(cmd->peer_eht_cap_mac, sizeof(cmd->peer_eht_cap_mac), + arg->peer_eht_cap_mac, sizeof(arg->peer_eht_cap_mac), + 0); + memcpy_and_pad(cmd->peer_eht_cap_phy, sizeof(cmd->peer_eht_cap_phy), + arg->peer_eht_cap_phy, sizeof(arg->peer_eht_cap_phy), + 0); + memcpy_and_pad(&cmd->peer_eht_ppet, sizeof(cmd->peer_eht_ppet), + &arg->peer_eht_ppet, sizeof(arg->peer_eht_ppet), 0); + /* Update peer legacy rate information */ ptr += sizeof(*cmd); @@ -2015,8 +2030,24 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, ptr += sizeof(*he_mcs); } + /* Loop through the EHT rate set */ + len = arg->peer_eht_mcs_count * sizeof(*eht_mcs); + tlv = ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len); + ptr += TLV_HDR_SIZE; + + for (i = 0; i < arg->peer_eht_mcs_count; i++) { + eht_mcs = ptr; + eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET, + sizeof(*eht_mcs)); + + eht_mcs->rx_mcs_set = cpu_to_le32(arg->peer_eht_rx_mcs_set[i]); + eht_mcs->tx_mcs_set = cpu_to_le32(arg->peer_eht_tx_mcs_set[i]); + ptr += sizeof(*eht_mcs); + } + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, - "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n", + "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n", cmd->vdev_id, cmd->peer_associd, arg->peer_mac, cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps, cmd->peer_listen_intval, cmd->peer_ht_caps, @@ -2026,7 +2057,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, cmd->peer_he_ops, cmd->peer_he_cap_info_ext, cmd->peer_he_cap_phy[0], cmd->peer_he_cap_phy[1], cmd->peer_he_cap_phy[2], - cmd->peer_bw_rxnss_override); + cmd->peer_bw_rxnss_override, cmd->peer_flags_ext, + cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1], + cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1], + cmd->peer_eht_cap_phy[2]); ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID); if (ret) { diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index dae895b479c7..5e8c4a23c6ba 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -1167,6 +1167,10 @@ enum wmi_tlv_peer_flags { }; +enum wmi_tlv_peer_flags_ext { + WMI_PEER_EXT_EHT = BIT(0), +}; + /** Enum list of TLV Tags for each parameter structure type. */ enum wmi_tlv_tag { WMI_TAG_LAST_RESERVED = 15, @@ -1924,6 +1928,7 @@ enum wmi_tlv_tag { WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, + WMI_TAG_EHT_RATE_SET = 0x3C4, WMI_TAG_MAX }; @@ -3612,6 +3617,15 @@ struct wmi_peer_assoc_complete_cmd { __le32 peer_he_cap_info_internal; __le32 min_data_rate; __le32 peer_he_caps_6ghz; + __le32 sta_type; + __le32 bss_max_idle_option; + __le32 auth_mode; + __le32 peer_flags_ext; + __le32 puncture_20mhz_bitmap; + __le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; + __le32 peer_eht_ops; + struct ath12k_wmi_ppe_threshold_params peer_eht_ppet; } __packed; struct wmi_stop_scan_cmd { @@ -3839,6 +3853,12 @@ struct ath12k_wmi_he_rate_set_params { __le32 tx_mcs_set; } __packed; +struct ath12k_wmi_eht_rate_set_params { + __le32 tlv_header; + __le32 rx_mcs_set; + __le32 tx_mcs_set; +} __packed; + #define MAX_REG_RULES 10 #define REG_ALPHA2_LEN 2 #define MAX_6G_REG_RULES 5 -- cgit From 6734cf9b4cc7ae017ec1e9ab44a8ba0d8c512d5d Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:05 +0300 Subject: wifi: ath12k: peer assoc for 320 MHz Add required peer association definitions and processing if the bandwidth is 320 MHz. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-9-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ drivers/net/wireless/ath/ath12k/wmi.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index b1bc227ad54e..6e9b7c5fb028 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -1816,6 +1816,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, cmd->peer_flags |= cpu_to_le32(WMI_PEER_80MHZ); if (arg->bw_160) cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ); + if (arg->bw_320) + cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ); /* Typically if STBC is enabled for VHT it should be enabled * for HT as well diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 5e8c4a23c6ba..93a70426df28 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -1169,6 +1169,7 @@ enum wmi_tlv_peer_flags { enum wmi_tlv_peer_flags_ext { WMI_PEER_EXT_EHT = BIT(0), + WMI_PEER_EXT_320MHZ = BIT(1), }; /** Enum list of TLV Tags for each parameter structure type. */ @@ -3552,6 +3553,7 @@ struct ath12k_wmi_peer_assoc_arg { bool bw_40; bool bw_80; bool bw_160; + bool bw_320; bool stbc_flag; bool ldpc_flag; bool static_mimops_flag; -- cgit From 22e1d1166c27ed9099f1312cd2043a480b1bda14 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Wed, 2 Aug 2023 20:04:06 +0300 Subject: wifi: ath12k: add MLO header in peer association Add tags with length 0 for MLO header and partner links which are required by the firmware for a successful association. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Aloka Dixit Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-10-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 6e9b7c5fb028..24f6c1dbd743 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -1909,7 +1909,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) + sizeof(*mcs) + TLV_HDR_SIZE + (sizeof(*he_mcs) * arg->peer_he_mcs_count) + - TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count); + TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count) + + TLV_HDR_SIZE + TLV_HDR_SIZE; skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) @@ -2032,6 +2033,12 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, ptr += sizeof(*he_mcs); } + /* MLO header tag with 0 length */ + len = 0; + tlv = ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len); + ptr += TLV_HDR_SIZE; + /* Loop through the EHT rate set */ len = arg->peer_eht_mcs_count * sizeof(*eht_mcs); tlv = ptr; @@ -2048,6 +2055,12 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, ptr += sizeof(*eht_mcs); } + /* ML partner links tag with 0 length */ + len = 0; + tlv = ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len); + ptr += TLV_HDR_SIZE; + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n", cmd->vdev_id, cmd->peer_associd, arg->peer_mac, -- cgit From 9211df5c025a5e50de8b8cb0798c1120f8593d8a Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:06 +0300 Subject: wifi: ath12k: parse WMI service ready ext2 event Parse WMI service ready ext2 event. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-11-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 48 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 16 ++++++++++++ 2 files changed, 64 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 24f6c1dbd743..35f65b7e2392 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -62,7 +62,23 @@ struct ath12k_wmi_svc_rdy_ext_parse { bool dma_ring_cap_done; }; +struct ath12k_wmi_svc_rdy_ext2_arg { + u32 reg_db_version; + u32 hw_min_max_tx_power_2ghz; + u32 hw_min_max_tx_power_5ghz; + u32 chwidth_num_peer_caps; + u32 preamble_puncture_bw; + u32 max_user_per_ppdu_ofdma; + u32 max_user_per_ppdu_mumimo; + u32 target_cap_flags; + u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 max_num_linkview_peers; + u32 max_num_msduq_supported_per_tid; + u32 default_num_msduq_supported_per_tid; +}; + struct ath12k_wmi_svc_rdy_ext2_parse { + struct ath12k_wmi_svc_rdy_ext2_arg arg; struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse; bool dma_ring_cap_done; bool spectral_bin_scaling_done; @@ -4102,6 +4118,26 @@ err: return ret; } +static int ath12k_pull_svc_ready_ext2(struct ath12k_wmi_pdev *wmi_handle, + const void *ptr, + struct ath12k_wmi_svc_rdy_ext2_arg *arg) +{ + const struct wmi_service_ready_ext2_event *ev = ptr; + + if (!ev) + return -EINVAL; + + arg->reg_db_version = le32_to_cpu(ev->reg_db_version); + arg->hw_min_max_tx_power_2ghz = le32_to_cpu(ev->hw_min_max_tx_power_2ghz); + arg->hw_min_max_tx_power_5ghz = le32_to_cpu(ev->hw_min_max_tx_power_5ghz); + arg->chwidth_num_peer_caps = le32_to_cpu(ev->chwidth_num_peer_caps); + arg->preamble_puncture_bw = le32_to_cpu(ev->preamble_puncture_bw); + arg->max_user_per_ppdu_ofdma = le32_to_cpu(ev->max_user_per_ppdu_ofdma); + arg->max_user_per_ppdu_mumimo = le32_to_cpu(ev->max_user_per_ppdu_mumimo); + arg->target_cap_flags = le32_to_cpu(ev->target_cap_flags); + return 0; +} + static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band, const __le32 cap_mac_info[], const __le32 cap_phy_info[], @@ -4225,10 +4261,22 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) { + struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0]; struct ath12k_wmi_svc_rdy_ext2_parse *parse = data; int ret; switch (tag) { + case WMI_TAG_SERVICE_READY_EXT2_EVENT: + ret = ath12k_pull_svc_ready_ext2(wmi_handle, ptr, + &parse->arg); + if (ret) { + ath12k_warn(ab, + "failed to extract wmi service ready ext2 parameters: %d\n", + ret); + return ret; + } + break; + case WMI_TAG_ARRAY_STRUCT: if (!parse->dma_ring_cap_done) { ret = ath12k_wmi_dma_ring_caps(ab, len, ptr, diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 93a70426df28..fdb79124ad9d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -1925,6 +1925,7 @@ enum wmi_tlv_tag { /* TODO add all the missing cmds */ WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, + WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334, WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, @@ -2612,6 +2613,21 @@ struct ath12k_wmi_soc_hal_reg_caps_params { #define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8) #define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12) +struct wmi_service_ready_ext2_event { + __le32 reg_db_version; + __le32 hw_min_max_tx_power_2ghz; + __le32 hw_min_max_tx_power_5ghz; + __le32 chwidth_num_peer_caps; + __le32 preamble_puncture_bw; + __le32 max_user_per_ppdu_ofdma; + __le32 max_user_per_ppdu_mumimo; + __le32 target_cap_flags; + __le32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 max_num_linkview_peers; + __le32 max_num_msduq_supported_per_tid; + __le32 default_num_msduq_supported_per_tid; +} __packed; + struct ath12k_wmi_caps_ext_params { __le32 hw_mode_id; union { -- cgit From 07c01b86f21dd499bd487b70c1536f868fede241 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 2 Aug 2023 20:04:07 +0300 Subject: wifi: ath12k: configure puncturing bitmap Enable the feature flag to indicate the driver support for preamble puncturing. Firmware will support this feature by default from IEEE 802.11be onwards. Configure the bitmap as part of VDEV start/restart and peer association commands. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit Signed-off-by: Muna Sinada Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230725224034.14045-12-quic_alokad@quicinc.com --- drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/mac.c | 16 ++++++++++++++-- drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ drivers/net/wireless/ath/ath12k/wmi.h | 12 +++++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index d0b625fea633..4389ff40b49d 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -238,6 +238,7 @@ struct ath12k_vif { u32 key_cipher; u8 tx_encap_type; u8 vdev_stats_id; + u32 punct_bitmap; }; struct ath12k_vif_iter { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 5b7a892e1f79..48cf3f10a3bc 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -842,6 +842,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id, arg.pref_tx_streams = ar->num_tx_chains; arg.pref_rx_streams = ar->num_rx_chains; + arg.punct_bitmap = 0xFFFFFFFF; arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); @@ -2139,6 +2140,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar, const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20; const struct ieee80211_eht_mcs_nss_supp_bw *bw; + struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv; u32 *rx_mcs, *tx_mcs; if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) @@ -2208,6 +2210,8 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar, arg->peer_eht_mcs_count++; break; } + + arg->punct_bitmap = ~arvif->punct_bitmap; } static void ath12k_peer_assoc_prepare(struct ath12k *ar, @@ -2761,6 +2765,9 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP) ath12k_mac_fils_discovery(arvif, info); + if (changed & BSS_CHANGED_EHT_PUNCTURING) + arvif->punct_bitmap = info->eht_puncturing; + mutex_unlock(&ar->conf_mutex); } @@ -5800,6 +5807,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, arg.vdev_id = arvif->vdev_id; arg.dtim_period = arvif->dtim_period; arg.bcn_intval = arvif->beacon_interval; + arg.punct_bitmap = ~arvif->punct_bitmap; arg.freq = chandef->chan->center_freq; arg.band_center_freq1 = chandef->center_freq1; @@ -5842,9 +5850,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); ath12k_dbg(ab, ATH12K_DBG_MAC, - "mac vdev %d start center_freq %d phymode %s\n", + "mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n", arg.vdev_id, arg.freq, - ath12k_mac_phymode_str(arg.mode)); + ath12k_mac_phymode_str(arg.mode), arg.punct_bitmap); ret = ath12k_wmi_vdev_start(ar, &arg, restart); if (ret) { @@ -6171,6 +6179,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, "mac chanctx assign ptr %pK vdev_id %i\n", ctx, arvif->vdev_id); + arvif->punct_bitmap = link_conf->eht_puncturing; + /* for some targets bss peer must be created before vdev_start */ if (ab->hw_params->vdev_start_delay && arvif->vdev_type != WMI_VDEV_TYPE_AP && @@ -7298,6 +7308,8 @@ static int __ath12k_mac_register(struct ath12k *ar) NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); } + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_PUNCT); + ath12k_reg_init(ar); if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 35f65b7e2392..c611a19c7364 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -1021,6 +1021,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg, cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms); cmd->regdomain = cpu_to_le32(arg->regdomain); cmd->he_ops = cpu_to_le32(arg->he_ops); + cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap); if (!restart) { if (arg->ssid) { @@ -1942,6 +1943,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, cmd->peer_new_assoc = cpu_to_le32(arg->peer_new_assoc); cmd->peer_associd = cpu_to_le32(arg->peer_associd); + cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap); ath12k_wmi_copy_peer_flags(cmd, arg, test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index fdb79124ad9d..8c047a9623f9 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2775,6 +2775,11 @@ struct wmi_vdev_start_request_cmd { __le32 he_ops; __le32 cac_duration_ms; __le32 regdomain; + __le32 min_data_rate; + __le32 mbssid_flags; + __le32 mbssid_tx_vdev_id; + __le32 eht_ops; + __le32 punct_bitmap; } __packed; #define MGMT_TX_DL_FRM_LEN 64 @@ -2874,6 +2879,10 @@ struct wmi_vdev_start_req_arg { u32 pref_rx_streams; u32 pref_tx_streams; u32 num_noa_descriptors; + u32 min_data_rate; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; + u32 punct_bitmap; }; struct ath12k_wmi_peer_create_arg { @@ -3604,6 +3613,7 @@ struct ath12k_wmi_peer_assoc_arg { u32 peer_eht_rx_mcs_set[WMI_MAX_EHTCAP_RATE_SET]; u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET]; struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet; + u32 punct_bitmap; }; struct wmi_peer_assoc_complete_cmd { @@ -3639,7 +3649,7 @@ struct wmi_peer_assoc_complete_cmd { __le32 bss_max_idle_option; __le32 auth_mode; __le32 peer_flags_ext; - __le32 puncture_20mhz_bitmap; + __le32 punct_bitmap; __le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; __le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; __le32 peer_eht_ops; -- cgit From 89a9dda1430a71fe95ad2b4f8056e7aa15b4aee7 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 20:04:09 +0300 Subject: wifi: ath12k: relax list iteration in ath12k_mac_vif_unref() In ath12k_mac_vif_unref() dp->tx_desc_used_list[i] is not altered so list_for_each_entry() should be safe. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230704173718.73462-1-dmantipov@yandex.ru --- drivers/net/wireless/ath/ath12k/mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 48cf3f10a3bc..0f2af2f14ef7 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -5542,7 +5542,7 @@ err: static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif) { - struct ath12k_tx_desc_info *tx_desc_info, *tmp1; + struct ath12k_tx_desc_info *tx_desc_info; struct ath12k_skb_cb *skb_cb; struct sk_buff *skb; int i; @@ -5550,8 +5550,8 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { spin_lock_bh(&dp->tx_desc_lock[i]); - list_for_each_entry_safe(tx_desc_info, tmp1, &dp->tx_desc_used_list[i], - list) { + list_for_each_entry(tx_desc_info, &dp->tx_desc_used_list[i], + list) { skb = tx_desc_info->skb; if (!skb) continue; -- cgit From 9632ea57be659887ab0d28a2a1d7b901dfddd263 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Sun, 16 Jul 2023 23:44:57 -0400 Subject: wifi: ath12k: add handler for scan event WMI_SCAN_EVENT_DEQUEUED When wlan interface is up, and 11d scan is sent to the firmware, then firmware needs to spend couple of seconds to complete the 11d scan. If normal scan from user space arrives to ath12k at this moment, then the normal scan request is also sent to the firmware, but the scan started event will be reported to ath12k until the 11d scan complete. When timed out for the scan started in ath12k, ath12k stops the normal scan and the firmware reports WMI_SCAN_EVENT_DEQUEUED to ath12k for the normal scan. ath12k has no handler for the event and then timed out for the scan completed in ath12k_scan_stop(), and ath12k prints the following error message. [ 1491.604750] ath12k_pci 0000:02:00.0: failed to receive scan abort comple: timed out [ 1491.604756] ath12k_pci 0000:02:00.0: failed to stop scan: -110 [ 1491.604758] ath12k_pci 0000:02:00.0: failed to start hw scan: -110 Add a handler for WMI_SCAN_EVENT_DEQUEUED and then complete the scan to get rid of the above error message. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230717034457.22162-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index c611a19c7364..fab4d33c8984 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -5948,6 +5948,8 @@ static void ath12k_scan_event(struct ath12k_base *ab, struct sk_buff *skb) ath12k_wmi_event_scan_start_failed(ar); break; case WMI_SCAN_EVENT_DEQUEUED: + __ath12k_mac_scan_finish(ar); + break; case WMI_SCAN_EVENT_PREEMPTED: case WMI_SCAN_EVENT_RESTARTED: case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT: -- cgit From 8198950ccb7d311f8b4389441d8dcb597f926340 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 17 Jul 2023 22:47:24 -0400 Subject: wifi: ath12k: avoid deadlock by change ieee80211_queue_work for regd_update_work Deadlock is easily happened while shutdown wlan interface such as run "ifconfig wlan0 down". The reason is because when ar->regd_update_work is ran, it will call wiphy_lock(ar->hw->wiphy) in function ath12k_regd_update() which is running in workqueue of ieee80211_local queued by ieee80211_queue_work(). Another thread from "ifconfig wlan0 down" will also accuqire the lock by wiphy_lock(sdata->local->hw.wiphy) in function ieee80211_stop(), and then it call ieee80211_stop_device() to flush_workqueue(local->workqueue), this will wait the workqueue of ieee80211_local finished. Then deadlock will happen easily if the two thread run meanwhile. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230718024724.29120-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index fab4d33c8984..9ed33e2d6da0 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -5473,7 +5473,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk ar = ab->pdevs[pdev_idx].ar; kfree(ab->new_regd[pdev_idx]); ab->new_regd[pdev_idx] = regd; - ieee80211_queue_work(ar->hw, &ar->regd_update_work); + queue_work(ab->workqueue, &ar->regd_update_work); } else { /* Multiple events for the same *ar is not expected. But we * can still clear any previously stored default_regd if we -- cgit From 571e9c4968875a78495eccfa26901083d0e6f833 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 2 Aug 2023 04:31:09 +0100 Subject: net: ethernet: mtk_eth_soc: support per-flow accounting on MT7988 NETSYS_V3 uses 64 bits for each counters while older SoCs are using 48/40 bits for each counter. Support reading per-flow byte and package counters on NETSYS_V3. Signed-off-by: Daniel Golle Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/37a0928fa8c1253b197884c68ce1f54239421ac5.1690946442.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + drivers/net/ethernet/mediatek/mtk_ppe.c | 21 ++++++++++++++------- drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 05be702f19c5..1b89f800f6df 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -5064,6 +5064,7 @@ static const struct mtk_soc_data mt7988_data = { .version = 3, .offload_version = 2, .hash_offset = 4, + .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index bf1ecb0c1c10..86f32f486043 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -92,7 +92,6 @@ static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) { - u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; u32 val, cnt_r0, cnt_r1, cnt_r2; int ret; @@ -107,12 +106,20 @@ static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *p cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); - byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); - byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); - pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); - pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); - *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; - *packets = (pkt_cnt_high << 16) | pkt_cnt_low; + if (mtk_is_netsys_v3_or_greater(ppe->eth)) { + /* 64 bit for each counter */ + u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); + *bytes = ((u64)cnt_r1 << 32) | cnt_r0; + *packets = ((u64)cnt_r3 << 32) | cnt_r2; + } else { + /* 48 bit byte counter, 40 bit packet counter */ + u32 byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); + u32 byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); + u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); + u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); + *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; + *packets = ((u64)pkt_cnt_high << 16) | pkt_cnt_low; + } return 0; } diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h index a2e61b3eb006..3ce088eef0ef 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h @@ -163,6 +163,8 @@ enum { #define MTK_PPE_MIB_SER_R2 0x348 #define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) +#define MTK_PPE_MIB_SER_R3 0x34c + #define MTK_PPE_MIB_CACHE_CTL 0x350 #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) -- cgit From 0520841960dee1e53449019d4409f0c3c03fb64f Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Tue, 1 Aug 2023 10:11:20 +0800 Subject: wifi: rtw89: recognize log format from firmware file Firmware log format is an element of multi-firmware file and used for firmware to provide log with formatted text. Driver needs to recognize it in advance if it exists. Signed-off-by: Chin-Yen Lee Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 4 ++++ drivers/net/wireless/realtek/rtw89/fw.c | 25 +++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index f3f7abddd3c0..695e8eb5780b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3548,6 +3548,7 @@ enum rtw89_fw_type { RTW89_FW_NORMAL = 1, RTW89_FW_WOWLAN = 3, RTW89_FW_NORMAL_CE = 5, + RTW89_FW_LOGFMT = 255, }; enum rtw89_fw_feature { @@ -3607,6 +3608,7 @@ struct rtw89_fw_info { u8 c2h_counter; struct rtw89_fw_suit normal; struct rtw89_fw_suit wowlan; + struct rtw89_fw_suit logfmt; bool fw_log_enable; u32 feature_map; }; @@ -5143,6 +5145,8 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev, if (type == RTW89_FW_WOWLAN) return &fw_info->wowlan; + else if (type == RTW89_FW_LOGFMT) + return &fw_info->logfmt; return &fw_info->normal; } diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index f8616c178de7..f27eb09d2bab 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -178,19 +178,22 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, for (i = 0; i < mfw_hdr->fw_nr; i++) { mfw_info = &mfw_hdr->info[i]; - if (mfw_info->cv != rtwdev->hal.cv || - mfw_info->type != type || - mfw_info->mp) - continue; - - fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); - fw_suit->size = le32_to_cpu(mfw_info->size); - return 0; + if (mfw_info->type == type) { + if (mfw_info->cv == rtwdev->hal.cv && !mfw_info->mp) + goto found; + if (type == RTW89_FW_LOGFMT) + goto found; + } } if (!nowarn) rtw89_err(rtwdev, "no suitable firmware found\n"); return -ENOENT; + +found: + fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); + fw_suit->size = le32_to_cpu(mfw_info->size); + return 0; } static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev, @@ -199,6 +202,9 @@ static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev, { const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data; + if (type == RTW89_FW_LOGFMT) + return; + fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION); fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION); fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION); @@ -365,6 +371,9 @@ normal_done: /* It still works if wowlan firmware isn't existing. */ __rtw89_fw_recognize(rtwdev, RTW89_FW_WOWLAN, false); + /* It still works if log format file isn't existing. */ + __rtw89_fw_recognize(rtwdev, RTW89_FW_LOGFMT, true); + rtw89_fw_recognize_features(rtwdev); rtw89_coex_recognize_ver(rtwdev); -- cgit From cad2bd8a136cb1231e8b43996be7133ccf92ef48 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Tue, 1 Aug 2023 10:11:21 +0800 Subject: wifi: rtw89: support firmware log with formatted text Original firmware log which is sent via C2H message bloats code size of firmware and is also length-limited. So we put some common log into format file, and firmware could use a log ID and some variables in C2H message to map a formatted text via pre-designed rule. Signed-off-by: Chin-Yen Lee Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 2 +- drivers/net/wireless/realtek/rtw89/core.h | 14 ++- drivers/net/wireless/realtek/rtw89/debug.c | 14 +-- drivers/net/wireless/realtek/rtw89/fw.c | 146 ++++++++++++++++++++++++++++- drivers/net/wireless/realtek/rtw89/fw.h | 31 +++++- drivers/net/wireless/realtek/rtw89/mac.c | 3 +- 6 files changed, 194 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index ec244849e501..ecdd05b851b7 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3508,7 +3508,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) set_bit(RTW89_FLAG_RUNNING, rtwdev->flags); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); - rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable); + rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.log.enable); rtw89_fw_h2c_init_ba_cam(rtwdev); return 0; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 695e8eb5780b..f05086b27b26 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3599,6 +3599,15 @@ struct rtw89_fw_req_info { struct completion completion; }; +struct rtw89_fw_log { + struct rtw89_fw_suit suit; + bool enable; + u32 last_fmt_id; + u32 fmt_count; + const __le32 *fmt_ids; + const char *(*fmts)[]; +}; + struct rtw89_fw_info { struct rtw89_fw_req_info req; int fw_format; @@ -3608,8 +3617,7 @@ struct rtw89_fw_info { u8 c2h_counter; struct rtw89_fw_suit normal; struct rtw89_fw_suit wowlan; - struct rtw89_fw_suit logfmt; - bool fw_log_enable; + struct rtw89_fw_log log; u32 feature_map; }; @@ -5146,7 +5154,7 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev, if (type == RTW89_FW_WOWLAN) return &fw_info->wowlan; else if (type == RTW89_FW_LOGFMT) - return &fw_info->logfmt; + return &fw_info->log.suit; return &fw_info->normal; } diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index f67af8aa2358..f1e5ac4186c2 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3204,20 +3204,22 @@ static ssize_t rtw89_debug_priv_btc_manual_set(struct file *filp, return count; } -static ssize_t rtw89_debug_fw_log_btc_manual_set(struct file *filp, - const char __user *user_buf, - size_t count, loff_t *loff) +static ssize_t rtw89_debug_fw_log_manual_set(struct file *filp, + const char __user *user_buf, + size_t count, loff_t *loff) { struct rtw89_debugfs_priv *debugfs_priv = filp->private_data; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; - struct rtw89_fw_info *fw_info = &rtwdev->fw; + struct rtw89_fw_log *log = &rtwdev->fw.log; bool fw_log_manual; if (kstrtobool_from_user(user_buf, count, &fw_log_manual)) goto out; mutex_lock(&rtwdev->mutex); - fw_info->fw_log_enable = fw_log_manual; + log->enable = fw_log_manual; + if (log->enable) + rtw89_fw_log_prepare(rtwdev); rtw89_fw_h2c_fw_log(rtwdev, fw_log_manual); mutex_unlock(&rtwdev->mutex); out: @@ -3584,7 +3586,7 @@ static struct rtw89_debugfs_priv rtw89_debug_priv_btc_manual = { }; static struct rtw89_debugfs_priv rtw89_debug_priv_fw_log_manual = { - .cb_write = rtw89_debug_fw_log_btc_manual_set, + .cb_write = rtw89_debug_fw_log_manual_set, }; static struct rtw89_debugfs_priv rtw89_debug_priv_phy_info = { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index f27eb09d2bab..cbb0e953fbbf 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -697,6 +697,150 @@ void rtw89_unload_firmware(struct rtw89_dev *rtwdev) */ fw->req.firmware = NULL; } + + kfree(fw->log.fmts); +} + +static u32 rtw89_fw_log_get_fmt_idx(struct rtw89_dev *rtwdev, u32 fmt_id) +{ + struct rtw89_fw_log *fw_log = &rtwdev->fw.log; + u32 i; + + if (fmt_id > fw_log->last_fmt_id) + return 0; + + for (i = 0; i < fw_log->fmt_count; i++) { + if (le32_to_cpu(fw_log->fmt_ids[i]) == fmt_id) + return i; + } + return 0; +} + +static int rtw89_fw_log_create_fmts_dict(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_log *log = &rtwdev->fw.log; + const struct rtw89_fw_logsuit_hdr *suit_hdr; + struct rtw89_fw_suit *suit = &log->suit; + const void *fmts_ptr, *fmts_end_ptr; + u32 fmt_count; + int i; + + suit_hdr = (const struct rtw89_fw_logsuit_hdr *)suit->data; + fmt_count = le32_to_cpu(suit_hdr->count); + log->fmt_ids = suit_hdr->ids; + fmts_ptr = &suit_hdr->ids[fmt_count]; + fmts_end_ptr = suit->data + suit->size; + log->fmts = kcalloc(fmt_count, sizeof(char *), GFP_KERNEL); + if (!log->fmts) + return -ENOMEM; + + for (i = 0; i < fmt_count; i++) { + fmts_ptr = memchr_inv(fmts_ptr, 0, fmts_end_ptr - fmts_ptr); + if (!fmts_ptr) + break; + + (*log->fmts)[i] = fmts_ptr; + log->last_fmt_id = le32_to_cpu(log->fmt_ids[i]); + log->fmt_count++; + fmts_ptr += strlen(fmts_ptr); + } + + return 0; +} + +int rtw89_fw_log_prepare(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_log *log = &rtwdev->fw.log; + struct rtw89_fw_suit *suit = &log->suit; + + if (!suit || !suit->data) { + rtw89_debug(rtwdev, RTW89_DBG_FW, "no log format file\n"); + return -EINVAL; + } + if (log->fmts) + return 0; + + return rtw89_fw_log_create_fmts_dict(rtwdev); +} + +static void rtw89_fw_log_dump_data(struct rtw89_dev *rtwdev, + const struct rtw89_fw_c2h_log_fmt *log_fmt, + u32 fmt_idx, u8 para_int, bool raw_data) +{ + const char *(*fmts)[] = rtwdev->fw.log.fmts; + char str_buf[RTW89_C2H_FW_LOG_STR_BUF_SIZE]; + u32 args[RTW89_C2H_FW_LOG_MAX_PARA_NUM] = {0}; + int i; + + if (log_fmt->argc > RTW89_C2H_FW_LOG_MAX_PARA_NUM) { + rtw89_warn(rtwdev, "C2H log: Arg count is unexpected %d\n", + log_fmt->argc); + return; + } + + if (para_int) + for (i = 0 ; i < log_fmt->argc; i++) + args[i] = le32_to_cpu(log_fmt->u.argv[i]); + + if (raw_data) { + if (para_int) + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, + "fw_enc(%d, %d, %d) %*ph", le32_to_cpu(log_fmt->fmt_id), + para_int, log_fmt->argc, (int)sizeof(args), args); + else + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, + "fw_enc(%d, %d, %d, %s)", le32_to_cpu(log_fmt->fmt_id), + para_int, log_fmt->argc, log_fmt->u.raw); + } else { + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, (*fmts)[fmt_idx], + args[0x0], args[0x1], args[0x2], args[0x3], args[0x4], + args[0x5], args[0x6], args[0x7], args[0x8], args[0x9], + args[0xa], args[0xb], args[0xc], args[0xd], args[0xe], + args[0xf]); + } + + rtw89_info(rtwdev, "C2H log: %s", str_buf); +} + +void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) +{ + const struct rtw89_fw_c2h_log_fmt *log_fmt; + u8 para_int; + u32 fmt_idx; + + if (len < RTW89_C2H_HEADER_LEN) { + rtw89_err(rtwdev, "c2h log length is wrong!\n"); + return; + } + + buf += RTW89_C2H_HEADER_LEN; + len -= RTW89_C2H_HEADER_LEN; + log_fmt = (const struct rtw89_fw_c2h_log_fmt *)buf; + + if (len < RTW89_C2H_FW_FORMATTED_LOG_MIN_LEN) + goto plain_log; + + if (log_fmt->signature != cpu_to_le16(RTW89_C2H_FW_LOG_SIGNATURE)) + goto plain_log; + + if (!rtwdev->fw.log.fmts) + return; + + para_int = u8_get_bits(log_fmt->feature, RTW89_C2H_FW_LOG_FEATURE_PARA_INT); + fmt_idx = rtw89_fw_log_get_fmt_idx(rtwdev, le32_to_cpu(log_fmt->fmt_id)); + + if (!para_int && log_fmt->argc != 0 && fmt_idx != 0) + rtw89_info(rtwdev, "C2H log: %s%s", + (*rtwdev->fw.log.fmts)[fmt_idx], log_fmt->u.raw); + else if (fmt_idx != 0 && para_int) + rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, false); + else + rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, true); + return; + +plain_log: + rtw89_info(rtwdev, "C2H log: %*s", len, buf); + } #define H2C_CAM_LEN 60 @@ -910,7 +1054,7 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable) } skb_put(skb, H2C_LOG_CFG_LEN); - SET_LOG_CFG_LEVEL(skb->data, RTW89_FW_LOG_LEVEL_SER); + SET_LOG_CFG_LEVEL(skb->data, RTW89_FW_LOG_LEVEL_LOUD); SET_LOG_CFG_PATH(skb->data, BIT(RTW89_FW_LOG_LEVEL_C2H)); SET_LOG_CFG_COMP(skb->data, comp); SET_LOG_CFG_COMP_EXT(skb->data, 0); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 49ecf070de71..ad1a621783f9 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3125,9 +3125,6 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb) return (struct rtw89_fw_c2h_attr *)skb->cb; } -#define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2) -#define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN) - struct rtw89_c2h_done_ack { __le32 w0; __le32 w1; @@ -3149,6 +3146,26 @@ struct rtw89_c2h_done_ack { #define RTW89_GET_MAC_C2H_REV_ACK_H2C_SEQ(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16)) +struct rtw89_fw_c2h_log_fmt { + __le16 signature; + u8 feature; + u8 syntax; + __le32 fmt_id; + u8 file_num; + __le16 line_num; + u8 argc; + union { + DECLARE_FLEX_ARRAY(u8, raw); + DECLARE_FLEX_ARRAY(__le32, argv); + } __packed u; +} __packed; + +#define RTW89_C2H_FW_FORMATTED_LOG_MIN_LEN 11 +#define RTW89_C2H_FW_LOG_FEATURE_PARA_INT BIT(2) +#define RTW89_C2H_FW_LOG_MAX_PARA_NUM 16 +#define RTW89_C2H_FW_LOG_SIGNATURE 0xA5A5 +#define RTW89_C2H_FW_LOG_STR_BUF_SIZE 512 + struct rtw89_c2h_mac_bcnfltr_rpt { __le32 w0; __le32 w1; @@ -3327,6 +3344,12 @@ struct rtw89_mfw_hdr { struct rtw89_mfw_info info[]; } __packed; +struct rtw89_fw_logsuit_hdr { + __le32 rsvd; + __le32 count; + __le32 ids[]; +} __packed; + struct fwcmd_hdr { __le32 hdr0; __le32 hdr1; @@ -3517,6 +3540,8 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type); void rtw89_load_firmware_work(struct work_struct *work); void rtw89_unload_firmware(struct rtw89_dev *rtwdev); int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev); +int rtw89_fw_log_prepare(struct rtw89_dev *rtwdev); +void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len); void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index b114babec698..1efa4da3cebc 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4437,8 +4437,7 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le static void rtw89_mac_c2h_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { - rtw89_info(rtwdev, "%*s", RTW89_GET_C2H_LOG_LEN(len), - RTW89_GET_C2H_LOG_SRT_PRT(c2h->data)); + rtw89_fw_log_dump(rtwdev, c2h->data, len); } static void -- cgit From 1b073b350d24b9481f0dffea9e9dec05c838098a Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:22 +0800 Subject: wifi: rtw89: introduce v1 format of firmware header New firmware header is used by upcoming WiFi 7 chips to have more information, so use common field w3[31:24] to determine header version, and then use corresponding function to read firmware version and commit ID: rtw89_8852be 0000:03:00.0: Firmware version 0.29.29.1 (799134c3), cmd version 1, type 5 rtw89_8852be 0000:03:00.0: Firmware version 0.29.29.1 (799134c3), cmd version 1, type 3 Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 3 ++ drivers/net/wireless/realtek/rtw89/fw.c | 66 +++++++++++++++++++++++++------ drivers/net/wireless/realtek/rtw89/fw.h | 33 ++++++++++++++++ 3 files changed, 89 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index f05086b27b26..01f79f2a8e2b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3563,6 +3563,7 @@ enum rtw89_fw_feature { }; struct rtw89_fw_suit { + enum rtw89_fw_type type; const u8 *data; u32 size; u8 major_ver; @@ -3575,6 +3576,8 @@ struct rtw89_fw_suit { u16 build_hour; u16 build_min; u8 cmd_ver; + u8 hdr_ver; + u32 commitid; }; #define RTW89_FW_VER_CODE(major, minor, sub, idx) \ diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index cbb0e953fbbf..a57d075db74a 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -196,30 +196,72 @@ found: return 0; } -static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev, - enum rtw89_fw_type type, - struct rtw89_fw_suit *fw_suit) +static void rtw89_fw_update_ver_v0(struct rtw89_dev *rtwdev, + struct rtw89_fw_suit *fw_suit, + const struct rtw89_fw_hdr *hdr) { - const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data; - - if (type == RTW89_FW_LOGFMT) - return; - fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION); fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION); fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION); fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX); + fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_W2_COMMITID); fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR); fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH); fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE); fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR); fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN); fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION); +} + +static void rtw89_fw_update_ver_v1(struct rtw89_dev *rtwdev, + struct rtw89_fw_suit *fw_suit, + const struct rtw89_fw_hdr_v1 *hdr) +{ + fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MAJOR_VERSION); + fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MINOR_VERSION); + fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBVERSION); + fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBINDEX); + fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_V1_W2_COMMITID); + fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_V1_W5_YEAR); + fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MONTH); + fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_V1_W4_DATE); + fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_V1_W4_HOUR); + fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MIN); + fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_V1_W3_CMD_VERSERION); +} + +static int rtw89_fw_update_ver(struct rtw89_dev *rtwdev, + enum rtw89_fw_type type, + struct rtw89_fw_suit *fw_suit) +{ + const struct rtw89_fw_hdr *v0 = (const struct rtw89_fw_hdr *)fw_suit->data; + const struct rtw89_fw_hdr_v1 *v1 = (const struct rtw89_fw_hdr_v1 *)fw_suit->data; + + if (type == RTW89_FW_LOGFMT) + return 0; + + fw_suit->type = type; + fw_suit->hdr_ver = le32_get_bits(v0->w3, FW_HDR_W3_HDR_VER); + + switch (fw_suit->hdr_ver) { + case 0: + rtw89_fw_update_ver_v0(rtwdev, fw_suit, v0); + break; + case 1: + rtw89_fw_update_ver_v1(rtwdev, fw_suit, v1); + break; + default: + rtw89_err(rtwdev, "Unknown firmware header version %u\n", + fw_suit->hdr_ver); + return -ENOENT; + } rtw89_info(rtwdev, - "Firmware version %u.%u.%u.%u, cmd version %u, type %u\n", + "Firmware version %u.%u.%u.%u (%08x), cmd version %u, type %u\n", fw_suit->major_ver, fw_suit->minor_ver, fw_suit->sub_ver, - fw_suit->sub_idex, fw_suit->cmd_ver, type); + fw_suit->sub_idex, fw_suit->commitid, fw_suit->cmd_ver, type); + + return 0; } static @@ -233,9 +275,7 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, if (ret) return ret; - rtw89_fw_update_ver(rtwdev, type, fw_suit); - - return 0; + return rtw89_fw_update_ver(rtwdev, type, fw_suit); } #define __DEF_FW_FEAT_COND(__cond, __op) \ diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index ad1a621783f9..366645bcead5 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -463,7 +463,9 @@ struct rtw89_fw_hdr { #define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8) #define FW_HDR_W1_SUBVERSION GENMASK(23, 16) #define FW_HDR_W1_SUBINDEX GENMASK(31, 24) +#define FW_HDR_W2_COMMITID GENMASK(31, 0) #define FW_HDR_W3_LEN GENMASK(23, 16) +#define FW_HDR_W3_HDR_VER GENMASK(31, 24) #define FW_HDR_W4_MONTH GENMASK(7, 0) #define FW_HDR_W4_DATE GENMASK(15, 8) #define FW_HDR_W4_HOUR GENMASK(23, 16) @@ -473,6 +475,37 @@ struct rtw89_fw_hdr { #define FW_HDR_W7_DYN_HDR BIT(16) #define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24) +struct rtw89_fw_hdr_v1 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; +} __packed; + +#define FW_HDR_V1_W1_MAJOR_VERSION GENMASK(7, 0) +#define FW_HDR_V1_W1_MINOR_VERSION GENMASK(15, 8) +#define FW_HDR_V1_W1_SUBVERSION GENMASK(23, 16) +#define FW_HDR_V1_W1_SUBINDEX GENMASK(31, 24) +#define FW_HDR_V1_W2_COMMITID GENMASK(31, 0) +#define FW_HDR_V1_W3_CMD_VERSERION GENMASK(23, 16) +#define FW_HDR_V1_W3_HDR_VER GENMASK(31, 24) +#define FW_HDR_V1_W4_MONTH GENMASK(7, 0) +#define FW_HDR_V1_W4_DATE GENMASK(15, 8) +#define FW_HDR_V1_W4_HOUR GENMASK(23, 16) +#define FW_HDR_V1_W4_MIN GENMASK(31, 24) +#define FW_HDR_V1_W5_YEAR GENMASK(15, 0) +#define FW_HDR_V1_W5_HDR_SIZE GENMASK(31, 16) +#define FW_HDR_V1_W6_SEC_NUM GENMASK(15, 8) +#define FW_HDR_V1_W7_DYN_HDR BIT(16) + static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) { le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0)); -- cgit From 12b1a12548eb31812f0a6128a0796d1656e2abb2 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:23 +0800 Subject: wifi: rtw89: add firmware parser for v1 format A firmware with v1 format contains many sections to download. Add parser to read section type, target address, length, checksum and so on, and then download the section to WiFi CPU with proper location. The additional dynamic header length named dynamic_hdr_len is used to skip content of dynamic header containing compiler flags of firmware, which can help to determine variant firmware build, but currently rtw89 only use single one variant. So, just skip the content. The layout of a WiFi CPU firmware with v1 format looks like: +---------------------------------------+ | Header (12 words) | +---------------------------------------+ | Section header 1 (4 words) | | Section header 2 (4 words) | | Section header 3 (4 words) | | ... | +---------------------------------------+ | Dynamic header (variable length) | +---------------------------------------+ | Data used & pointed by section | | ... | +---------------------------------------+ Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/fw.c | 106 ++++++++++++++++++++++++++++---- drivers/net/wireless/realtek/rtw89/fw.h | 17 +++++ 2 files changed, 111 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index a57d075db74a..d8bcc51242ff 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -86,8 +86,8 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev) return 0; } -static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, - struct rtw89_fw_bin_info *info) +static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, + struct rtw89_fw_bin_info *info) { const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw; struct rtw89_fw_hdr_section_info *section_info; @@ -154,6 +154,94 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, return 0; } +static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, + struct rtw89_fw_bin_info *info) +{ + const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw; + struct rtw89_fw_hdr_section_info *section_info; + const struct rtw89_fw_dynhdr_hdr *fwdynhdr; + const struct rtw89_fw_hdr_section_v1 *section; + const u8 *fw_end = fw + len; + const u8 *bin; + u32 base_hdr_len; + u32 mssc_len = 0; + u32 i; + + info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_SEC_NUM); + base_hdr_len = struct_size(fw_hdr, sections, info->section_num); + info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR); + + if (info->dynamic_hdr_en) { + info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE); + info->dynamic_hdr_len = info->hdr_len - base_hdr_len; + fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len); + if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) { + rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n"); + return -EINVAL; + } + } else { + info->hdr_len = base_hdr_len; + info->dynamic_hdr_len = 0; + } + + bin = fw + info->hdr_len; + + /* jump to section header */ + section_info = info->section_info; + for (i = 0; i < info->section_num; i++) { + section = &fw_hdr->sections[i]; + section_info->type = + le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SECTIONTYPE); + if (section_info->type == FWDL_SECURITY_SECTION_TYPE) { + section_info->mssc = + le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC); + mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN; + } else { + section_info->mssc = 0; + } + + section_info->len = + le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SEC_SIZE); + if (le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_CHECKSUM)) + section_info->len += FWDL_SECTION_CHKSUM_LEN; + section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_REDL); + section_info->dladdr = + le32_get_bits(section->w0, FWSECTION_HDR_V1_W0_DL_ADDR); + section_info->addr = bin; + bin += section_info->len; + section_info++; + } + + if (fw_end != bin + mssc_len) { + rtw89_err(rtwdev, "[ERR]fw bin size\n"); + return -EINVAL; + } + + return 0; +} + +static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, + const struct rtw89_fw_suit *fw_suit, + struct rtw89_fw_bin_info *info) +{ + const u8 *fw = fw_suit->data; + u32 len = fw_suit->size; + + if (!fw || !len) { + rtw89_err(rtwdev, "fw type %d isn't recognized\n", fw_suit->type); + return -ENOENT; + } + + switch (fw_suit->hdr_ver) { + case 0: + return rtw89_fw_hdr_parser_v0(rtwdev, fw, len, info); + case 1: + return rtw89_fw_hdr_parser_v1(rtwdev, fw, len, info); + default: + return -ENOENT; + } +} + static int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, struct rtw89_fw_suit *fw_suit, bool nowarn) @@ -621,8 +709,6 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) struct rtw89_fw_info *fw_info = &rtwdev->fw; struct rtw89_fw_suit *fw_suit = rtw89_fw_suit_get(rtwdev, type); struct rtw89_fw_bin_info info; - const u8 *fw = fw_suit->data; - u32 len = fw_suit->size; u8 val; int ret; @@ -631,12 +717,7 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) if (ret) return ret; - if (!fw || !len) { - rtw89_err(rtwdev, "fw type %d isn't recognized\n", type); - return -ENOENT; - } - - ret = rtw89_fw_hdr_parser(rtwdev, fw, len, &info); + ret = rtw89_fw_hdr_parser(rtwdev, fw_suit, &info); if (ret) { rtw89_err(rtwdev, "parse fw header fail\n"); goto fwdl_err; @@ -650,13 +731,14 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) goto fwdl_err; } - ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len - info.dynamic_hdr_len); + ret = rtw89_fw_download_hdr(rtwdev, fw_suit->data, info.hdr_len - + info.dynamic_hdr_len); if (ret) { ret = -EBUSY; goto fwdl_err; } - ret = rtw89_fw_download_main(rtwdev, fw, &info); + ret = rtw89_fw_download_main(rtwdev, fw_suit->data, &info); if (ret) { ret = -EBUSY; goto fwdl_err; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 366645bcead5..8961958009dd 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -475,6 +475,22 @@ struct rtw89_fw_hdr { #define FW_HDR_W7_DYN_HDR BIT(16) #define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24) +struct rtw89_fw_hdr_section_v1 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; +} __packed; + +#define FWSECTION_HDR_V1_W0_DL_ADDR GENMASK(31, 0) +#define FWSECTION_HDR_V1_W1_METADATA GENMASK(31, 24) +#define FWSECTION_HDR_V1_W1_SECTIONTYPE GENMASK(27, 24) +#define FWSECTION_HDR_V1_W1_SEC_SIZE GENMASK(23, 0) +#define FWSECTION_HDR_V1_W1_CHECKSUM BIT(28) +#define FWSECTION_HDR_V1_W1_REDL BIT(29) +#define FWSECTION_HDR_V1_W2_MSSC GENMASK(7, 0) +#define FWSECTION_HDR_V1_W2_BBMCU_IDX GENMASK(27, 24) + struct rtw89_fw_hdr_v1 { __le32 w0; __le32 w1; @@ -488,6 +504,7 @@ struct rtw89_fw_hdr_v1 { __le32 w9; __le32 w10; __le32 w11; + struct rtw89_fw_hdr_section_v1 sections[]; } __packed; #define FW_HDR_V1_W1_MAJOR_VERSION GENMASK(7, 0) -- cgit From 7d112665982b0b78e6bcf4173c8231838c158187 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:24 +0800 Subject: wifi: rtw89: add firmware suit for BB MCU 0/1 For existing chips, firmware is only for WiFi CPU, but WiFi 7 chips add new hardware component BB MCU that needs firmware as well. The firmwares of BB MCU 0/1 are also downloaded via the same path like WiFi CPU firmware, and use the same firmware header format, so add firmware suits to access them commonly. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 01f79f2a8e2b..aaee0733301a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3548,6 +3548,8 @@ enum rtw89_fw_type { RTW89_FW_NORMAL = 1, RTW89_FW_WOWLAN = 3, RTW89_FW_NORMAL_CE = 5, + RTW89_FW_BBMCU0 = 64, + RTW89_FW_BBMCU1 = 65, RTW89_FW_LOGFMT = 255, }; @@ -3620,6 +3622,8 @@ struct rtw89_fw_info { u8 c2h_counter; struct rtw89_fw_suit normal; struct rtw89_fw_suit wowlan; + struct rtw89_fw_suit bbmcu0; + struct rtw89_fw_suit bbmcu1; struct rtw89_fw_log log; u32 feature_map; }; @@ -5154,10 +5158,19 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev, { struct rtw89_fw_info *fw_info = &rtwdev->fw; - if (type == RTW89_FW_WOWLAN) + switch (type) { + case RTW89_FW_WOWLAN: return &fw_info->wowlan; - else if (type == RTW89_FW_LOGFMT) + case RTW89_FW_LOGFMT: return &fw_info->log.suit; + case RTW89_FW_BBMCU0: + return &fw_info->bbmcu0; + case RTW89_FW_BBMCU1: + return &fw_info->bbmcu1; + default: + break; + } + return &fw_info->normal; } -- cgit From a337d4331fd64652a9ad459049713ba5b1f8e0bd Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:25 +0800 Subject: wifi: rtw89: introduce infrastructure of firmware elements In order to pack more data into firmware file, we introduce firmware elements and append BB_MCU firmware first. The first part of new firmware file is still unchanged firmware of WiFi CPU, so the new firmware format can be backward compatible to old format. The new elements part consists of ID and size basically, which can append more elements simply. To avoid unaligned access in certain platform and be easy to read, headers of all elements start at 16-byte aligned address. +===========================================+ | original firmware | | +-------------+ | | padding | +===========================================+ | elm ID 1 | elm size | other header data | +----------+----------+ | | | +-------------------------------------------+ | content (variable length) | | +-------------+ | | padding | +===========================================+ | elm ID 2 | elm size | other header data | +----------+----------+ | | | +-------------------------------------------+ | content (variable length) | | +-----------------------+ | | (no padding for the last one) +===================+ More detail of element header is shown below. The additional fields 'version' and 'element_priv[]' are meta data of elements, so that we can know element version easily, and element_priv[] provide specific fields for certain element, such as RF path index for RF parameter tables. +===========================================+ | elm ID | elm size | version | rsvd0 | +----------+----------+----------+----------+ | rsvd1/2 | element_priv[] | +-------------------------------------------+ Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-7-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 6 ++ drivers/net/wireless/realtek/rtw89/fw.c | 98 +++++++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 31 ++++++++++ 3 files changed, 135 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index ecdd05b851b7..62c21c09cf92 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3779,6 +3779,12 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) return ret; } + ret = rtw89_fw_recognize_elements(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware elements\n"); + return ret; + } + ret = rtw89_chip_efuse_info_setup(rtwdev); if (ret) return ret; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d8bcc51242ff..d36fbbb6c549 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -284,6 +284,26 @@ found: return 0; } +static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_info *fw_info = &rtwdev->fw; + const struct firmware *firmware = fw_info->req.firmware; + const struct rtw89_mfw_hdr *mfw_hdr = + (const struct rtw89_mfw_hdr *)firmware->data; + const struct rtw89_mfw_info *mfw_info; + u32 size; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { + rtw89_warn(rtwdev, "not mfw format\n"); + return 0; + } + + mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1]; + size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size); + + return size; +} + static void rtw89_fw_update_ver_v0(struct rtw89_dev *rtwdev, struct rtw89_fw_suit *fw_suit, const struct rtw89_fw_hdr *hdr) @@ -366,6 +386,21 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, return rtw89_fw_update_ver(rtwdev, type, fw_suit); } +static +int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const void *data) +{ + enum rtw89_fw_type type = (enum rtw89_fw_type)data; + struct rtw89_fw_suit *fw_suit; + + fw_suit = rtw89_fw_suit_get(rtwdev, type); + fw_suit->data = elm->u.common.contents; + fw_suit->size = le32_to_cpu(elm->size); + + return rtw89_fw_update_ver(rtwdev, type, fw_suit); +} + #define __DEF_FW_FEAT_COND(__cond, __op) \ static bool __fw_feat_cond_ ## __cond(u32 suit_ver_code, u32 comp_ver_code) \ { \ @@ -509,6 +544,69 @@ normal_done: return 0; } +struct rtw89_fw_element_handler { + int (*fn)(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, const void *data); + const void *data; + const char *name; +}; + +static const struct rtw89_fw_element_handler __fw_element_handlers[] = { + [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm, + (const void *)RTW89_FW_BBMCU0, NULL}, + [RTW89_FW_ELEMENT_ID_BBMCU1] = {__rtw89_fw_recognize_from_elm, + (const void *)RTW89_FW_BBMCU1, NULL}, +}; + +int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_info *fw_info = &rtwdev->fw; + const struct firmware *firmware = fw_info->req.firmware; + const struct rtw89_fw_element_handler *handler; + const struct rtw89_fw_element_hdr *hdr; + u32 elm_size; + u32 elem_id; + u32 offset; + int ret; + + offset = rtw89_mfw_get_size(rtwdev); + offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); + if (offset == 0) + return -EINVAL; + + while (offset + sizeof(*hdr) < firmware->size) { + hdr = (const struct rtw89_fw_element_hdr *)(firmware->data + offset); + + elm_size = le32_to_cpu(hdr->size); + if (offset + elm_size >= firmware->size) { + rtw89_warn(rtwdev, "firmware element size exceeds\n"); + break; + } + + elem_id = le32_to_cpu(hdr->id); + if (elem_id >= ARRAY_SIZE(__fw_element_handlers)) + goto next; + + handler = &__fw_element_handlers[elem_id]; + if (!handler->fn) + goto next; + + ret = handler->fn(rtwdev, hdr, handler->data); + if (ret) + return ret; + + if (handler->name) + rtw89_info(rtwdev, "Firmware element %s version: %4ph\n", + handler->name, hdr->ver); + +next: + offset += sizeof(*hdr) + elm_size; + offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); + } + + return 0; +} + void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len) diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 8961958009dd..cb9eed8c2f1d 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3400,6 +3400,36 @@ struct rtw89_fw_logsuit_hdr { __le32 ids[]; } __packed; +#define RTW89_FW_ELEMENT_ALIGN 16 + +enum rtw89_fw_element_id { + RTW89_FW_ELEMENT_ID_BBMCU0 = 0, + RTW89_FW_ELEMENT_ID_BBMCU1 = 1, +}; + +struct rtw89_fw_element_hdr { + __le32 id; /* enum rtw89_fw_element_id */ + __le32 size; /* exclude header size */ + u8 ver[4]; + __le32 rsvd0; + __le32 rsvd1; + __le32 rsvd2; + union { + struct { + u8 priv[8]; + u8 contents[]; + } __packed common; + struct { + u8 idx; + u8 rsvd[7]; + struct { + __le32 addr; + __le32 data; + } __packed regs[]; + } __packed reg2; + } __packed u; +} __packed; + struct fwcmd_hdr { __le32 hdr0; __le32 hdr1; @@ -3581,6 +3611,7 @@ struct rtw89_fw_h2c_rf_get_mccch { int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev); int rtw89_fw_recognize(struct rtw89_dev *rtwdev); +int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev); const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, -- cgit From 894747206893c4a276e82999d1a1ed76c58bb36a Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:26 +0800 Subject: wifi: rtw89: add to parse firmware elements of BB and RF tables The tables of BB and RF parameters are pairs of {addr, value}. Load them and convert from little-endian to CPU order, and show the version to clear which version we are using. rtw89_8922ae 0000:03:00.0: Firmware element BB version: 00 04 00 00 rtw89_8922ae 0000:03:00.0: Firmware element radio A version: 00 13 00 00 rtw89_8922ae 0000:03:00.0: Firmware element NCTL version: 00 05 00 00 We use tables defined in firmware elements with higher priority than original static const tables defined in driver, because WiFi 7 chips will not define the tables in driver, and existing chips can possibly migrate to the new design one by one. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-8-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 8 +++ drivers/net/wireless/realtek/rtw89/fw.c | 95 +++++++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 7 +++ drivers/net/wireless/realtek/rtw89/phy.c | 15 +++-- 4 files changed, 121 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index aaee0733301a..bf6d8ef89097 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3613,6 +3613,13 @@ struct rtw89_fw_log { const char *(*fmts)[]; }; +struct rtw89_fw_elm_info { + struct rtw89_phy_table *bb_tbl; + struct rtw89_phy_table *bb_gain; + struct rtw89_phy_table *rf_radio[RF_PATH_MAX]; + struct rtw89_phy_table *rf_nctl; +}; + struct rtw89_fw_info { struct rtw89_fw_req_info req; int fw_format; @@ -3626,6 +3633,7 @@ struct rtw89_fw_info { struct rtw89_fw_suit bbmcu1; struct rtw89_fw_log log; u32 feature_map; + struct rtw89_fw_elm_info elm_info; }; #define RTW89_CHK_FW_FEATURE(_feat, _fw) \ diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d36fbbb6c549..1ca99dad2ac0 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -544,6 +544,68 @@ normal_done: return 0; } +static +int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const void *data) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + struct rtw89_phy_table *tbl; + struct rtw89_reg2_def *regs; + enum rtw89_rf_path rf_path; + u32 n_regs, i; + u8 idx; + + tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); + if (!tbl) + return -ENOMEM; + + switch (le32_to_cpu(elm->id)) { + case RTW89_FW_ELEMENT_ID_BB_REG: + elm_info->bb_tbl = tbl; + break; + case RTW89_FW_ELEMENT_ID_BB_GAIN: + elm_info->bb_gain = tbl; + break; + case RTW89_FW_ELEMENT_ID_RADIO_A: + case RTW89_FW_ELEMENT_ID_RADIO_B: + case RTW89_FW_ELEMENT_ID_RADIO_C: + case RTW89_FW_ELEMENT_ID_RADIO_D: + rf_path = (enum rtw89_rf_path)data; + idx = elm->u.reg2.idx; + + elm_info->rf_radio[idx] = tbl; + tbl->rf_path = rf_path; + tbl->config = rtw89_phy_config_rf_reg_v1; + break; + case RTW89_FW_ELEMENT_ID_RF_NCTL: + elm_info->rf_nctl = tbl; + break; + default: + kfree(tbl); + return -ENOENT; + } + + n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]); + regs = kcalloc(n_regs, sizeof(tbl->regs[0]), GFP_KERNEL); + if (!regs) + goto out; + + for (i = 0; i < n_regs; i++) { + regs[i].addr = le32_to_cpu(elm->u.reg2.regs[i].addr); + regs[i].data = le32_to_cpu(elm->u.reg2.regs[i].data); + } + + tbl->n_regs = n_regs; + tbl->regs = regs; + + return 0; + +out: + kfree(tbl); + return -ENOMEM; +} + struct rtw89_fw_element_handler { int (*fn)(struct rtw89_dev *rtwdev, const struct rtw89_fw_element_hdr *elm, const void *data); @@ -556,6 +618,17 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = { (const void *)RTW89_FW_BBMCU0, NULL}, [RTW89_FW_ELEMENT_ID_BBMCU1] = {__rtw89_fw_recognize_from_elm, (const void *)RTW89_FW_BBMCU1, NULL}, + [RTW89_FW_ELEMENT_ID_BB_REG] = {rtw89_build_phy_tbl_from_elm, NULL, "BB"}, + [RTW89_FW_ELEMENT_ID_BB_GAIN] = {rtw89_build_phy_tbl_from_elm, NULL, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_A] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_A, "radio A"}, + [RTW89_FW_ELEMENT_ID_RADIO_B] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_B, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_C] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_C, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_D] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_D, NULL}, + [RTW89_FW_ELEMENT_ID_RF_NCTL] = {rtw89_build_phy_tbl_from_elm, NULL, "NCTL"}, }; int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) @@ -903,6 +976,27 @@ void rtw89_load_firmware_work(struct work_struct *work) rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false); } +static void rtw89_free_phy_tbl_from_elm(struct rtw89_phy_table *tbl) +{ + if (!tbl) + return; + + kfree(tbl->regs); + kfree(tbl); +} + +static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + int i; + + rtw89_free_phy_tbl_from_elm(elm_info->bb_tbl); + rtw89_free_phy_tbl_from_elm(elm_info->bb_gain); + for (i = 0; i < ARRAY_SIZE(elm_info->rf_radio); i++) + rtw89_free_phy_tbl_from_elm(elm_info->rf_radio[i]); + rtw89_free_phy_tbl_from_elm(elm_info->rf_nctl); +} + void rtw89_unload_firmware(struct rtw89_dev *rtwdev) { struct rtw89_fw_info *fw = &rtwdev->fw; @@ -919,6 +1013,7 @@ void rtw89_unload_firmware(struct rtw89_dev *rtwdev) } kfree(fw->log.fmts); + rtw89_unload_firmware_elements(rtwdev); } static u32 rtw89_fw_log_get_fmt_idx(struct rtw89_dev *rtwdev, u32 fmt_id) diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index cb9eed8c2f1d..cbb130537e07 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3405,6 +3405,13 @@ struct rtw89_fw_logsuit_hdr { enum rtw89_fw_element_id { RTW89_FW_ELEMENT_ID_BBMCU0 = 0, RTW89_FW_ELEMENT_ID_BBMCU1 = 1, + RTW89_FW_ELEMENT_ID_BB_REG = 2, + RTW89_FW_ELEMENT_ID_BB_GAIN = 3, + RTW89_FW_ELEMENT_ID_RADIO_A = 4, + RTW89_FW_ELEMENT_ID_RADIO_B = 5, + RTW89_FW_ELEMENT_ID_RADIO_C = 6, + RTW89_FW_ELEMENT_ID_RADIO_D = 7, + RTW89_FW_ELEMENT_ID_RF_NCTL = 8, }; struct rtw89_fw_element_hdr { diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index abe0f5179a38..c40c4f8c1271 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -1355,12 +1355,16 @@ static void rtw89_phy_init_reg(struct rtw89_dev *rtwdev, void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev) { + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; - const struct rtw89_phy_table *bb_table = chip->bb_table; - const struct rtw89_phy_table *bb_gain_table = chip->bb_gain_table; + const struct rtw89_phy_table *bb_table; + const struct rtw89_phy_table *bb_gain_table; + bb_table = elm_info->bb_tbl ? elm_info->bb_tbl : chip->bb_table; rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg, NULL); rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + + bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table; if (bb_gain_table) rtw89_phy_init_reg(rtwdev, bb_gain_table, rtw89_phy_config_bb_gain, NULL); @@ -1378,6 +1382,7 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) { void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, void *data); + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_phy_table *rf_table; struct rtw89_fw_h2c_rf_reg_info *rf_reg_info; @@ -1388,7 +1393,8 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) return; for (path = RF_PATH_A; path < chip->rf_path_num; path++) { - rf_table = chip->rf_table[path]; + rf_table = elm_info->rf_radio[path] ? + elm_info->rf_radio[path] : chip->rf_table[path]; rf_reg_info->rf_path = rf_table->rf_path; if (noio) config = rtw89_phy_config_rf_reg_noio; @@ -1405,6 +1411,7 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) { + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_phy_table *nctl_table; u32 val; @@ -1427,7 +1434,7 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) if (ret) rtw89_err(rtwdev, "failed to poll nctl block\n"); - nctl_table = chip->nctl_table; + nctl_table = elm_info->rf_nctl ? elm_info->rf_nctl : chip->nctl_table; rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL); if (chip->nctl_post_table) -- cgit From dd59c6a32b7189f51947edc5b15939367729dd85 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 1 Aug 2023 10:11:27 +0800 Subject: wifi: rtw89: return failure if needed firmware elements are not recognized WiFi 7 chips doesn't have static const tables defined in driver. If tables aren't loaded properly from firmware file, driver can get NULL pointer access exception. One way is to add the checking statements when trying to access these tables, but I choose to check them right after loading firmware elements from firmware file, so I don't need to add error handlers everywhere. Currently, the needed firmware elements of WiFi 6 chips are all zero, and coming WiFi 7 chip will need at least BB MCU, parameters of BB and RF. We will add them after 8922AE is verified. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230801021127.15919-9-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 11 +++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 2 ++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + 7 files changed, 18 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index bf6d8ef89097..fa4bbc4095ab 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3382,6 +3382,7 @@ struct rtw89_chip_info { const char *fw_basename; u8 fw_format_max; bool try_ce_fw; + u32 needed_fw_elms; u32 fifo_size; bool small_fifo_size; u32 dle_scc_rsvd_size; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 1ca99dad2ac0..2811a94b5f69 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -635,6 +635,8 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) { struct rtw89_fw_info *fw_info = &rtwdev->fw; const struct firmware *firmware = fw_info->req.firmware; + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 unrecognized_elements = chip->needed_fw_elms; const struct rtw89_fw_element_handler *handler; const struct rtw89_fw_element_hdr *hdr; u32 elm_size; @@ -642,6 +644,8 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) u32 offset; int ret; + BUILD_BUG_ON(sizeof(chip->needed_fw_elms) * 8 < RTW89_FW_ELEMENT_ID_NUM); + offset = rtw89_mfw_get_size(rtwdev); offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); if (offset == 0) @@ -672,11 +676,18 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) rtw89_info(rtwdev, "Firmware element %s version: %4ph\n", handler->name, hdr->ver); + unrecognized_elements &= ~BIT(elem_id); next: offset += sizeof(*hdr) + elm_size; offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); } + if (unrecognized_elements) { + rtw89_err(rtwdev, "Firmware elements 0x%08x are unrecognized\n", + unrecognized_elements); + return -ENOENT; + } + return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index cbb130537e07..775f4e8fbda4 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3412,6 +3412,8 @@ enum rtw89_fw_element_id { RTW89_FW_ELEMENT_ID_RADIO_C = 6, RTW89_FW_ELEMENT_ID_RADIO_D = 7, RTW89_FW_ELEMENT_ID_RF_NCTL = 8, + + RTW89_FW_ELEMENT_ID_NUM, }; struct rtw89_fw_element_hdr { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 456b8369fb06..b5740639e267 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2339,6 +2339,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .fw_basename = RTW8851B_FW_BASENAME, .fw_format_max = RTW8851B_FW_FORMAT_MAX, .try_ce_fw = true, + .needed_fw_elms = 0, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 0fc5eb777a4a..41f05276406d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2076,6 +2076,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .fw_basename = RTW8852A_FW_BASENAME, .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, + .needed_fw_elms = 0, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index d76d74cc867a..eb2210cb7e09 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2508,6 +2508,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .fw_basename = RTW8852B_FW_BASENAME, .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, + .needed_fw_elms = 0, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index f269832b2bc6..b1af72fbf085 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2807,6 +2807,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .fw_basename = RTW8852C_FW_BASENAME, .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, + .needed_fw_elms = 0, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, -- cgit From c1e9e5e0b9cc25dbfb3a584951e6189b159f869f Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Wed, 2 Aug 2023 17:06:57 +0800 Subject: drivers: net: xgene: Do not check for 0 return after calling platform_get_irq() It is not possible for platform_get_irq() to return 0. Use the return value from platform_get_irq(). Signed-off-by: Ruan Jinjie Reviewed-by: Jesse Brandeburg Link: https://lore.kernel.org/r/20230802090657.969923-1-ruanjinjie@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 390671640388..41d96f4b23d8 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1632,7 +1632,7 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) for (i = 0; i < max_irqs; i++) { ret = platform_get_irq(pdev, i); - if (ret <= 0) { + if (ret < 0) { if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { max_irqs = i; pdata->rxq_cnt = max_irqs / 2; @@ -1640,7 +1640,7 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) pdata->cq_cnt = max_irqs / 2; break; } - return ret ? : -ENXIO; + return ret; } pdata->irqs[i] = ret; } -- cgit From 6abce66ba953a0f8ed97559709a2a567f95f560a Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Wed, 2 Aug 2023 16:52:16 +0800 Subject: net: gemini: Do not check for 0 return after calling platform_get_irq() It is not possible for platform_get_irq() to return 0. Use the return value from platform_get_irq(). Signed-off-by: Ruan Jinjie Reviewed-by: Jesse Brandeburg Link: https://lore.kernel.org/r/20230802085216.659238-1-ruanjinjie@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/cortina/gemini.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 5715b9ab2712..692cb2d04c1c 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2415,8 +2415,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) /* Interrupt */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq ? irq : -ENODEV; + if (irq < 0) + return irq; port->irq = irq; /* Clock the port */ -- cgit From 3986892646de95b916f6bf1c22b35dd2a3b3715a Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Wed, 2 Aug 2023 12:00:26 +0800 Subject: net/mlx4: Remove many unnecessary NULL values The NULL initialization of the pointers assigned by kzalloc() first is not necessary, because if the kzalloc() failed, the pointers will be assigned NULL, otherwise it works as usual. so remove it. Signed-off-by: Ruan Jinjie Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230802040026.2588675-1-ruanjinjie@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 10 +++++----- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/main.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 7d45f1d55f79..164a13272faa 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1467,8 +1467,8 @@ static int add_ip_rule(struct mlx4_en_priv *priv, struct list_head *list_h) { int err; - struct mlx4_spec_list *spec_l2 = NULL; - struct mlx4_spec_list *spec_l3 = NULL; + struct mlx4_spec_list *spec_l2; + struct mlx4_spec_list *spec_l3; struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL); @@ -1505,9 +1505,9 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv, struct list_head *list_h, int proto) { int err; - struct mlx4_spec_list *spec_l2 = NULL; - struct mlx4_spec_list *spec_l3 = NULL; - struct mlx4_spec_list *spec_l4 = NULL; + struct mlx4_spec_list *spec_l2; + struct mlx4_spec_list *spec_l3; + struct mlx4_spec_list *spec_l4; struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index e11bc0ac880e..403604ceebc8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -291,7 +291,7 @@ mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip, __be32 dst_ip, u8 ip_proto, __be16 src_port, __be16 dst_port, u32 flow_id) { - struct mlx4_en_filter *filter = NULL; + struct mlx4_en_filter *filter; filter = kzalloc(sizeof(struct mlx4_en_filter), GFP_ATOMIC); if (!filter) @@ -2935,7 +2935,7 @@ static void mlx4_en_bond_work(struct work_struct *work) static int mlx4_en_queue_bond_work(struct mlx4_en_priv *priv, int is_bonded, u8 v2p_p1, u8 v2p_p2) { - struct mlx4_en_bond *bond = NULL; + struct mlx4_en_bond *bond; bond = kzalloc(sizeof(*bond), GFP_ATOMIC); if (!bond) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 61286b0d9b0c..8a5409b00530 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -864,7 +864,7 @@ static void mlx4_slave_destroy_special_qp_cap(struct mlx4_dev *dev) static int mlx4_slave_special_qp_cap(struct mlx4_dev *dev) { - struct mlx4_func_cap *func_cap = NULL; + struct mlx4_func_cap *func_cap; struct mlx4_caps *caps = &dev->caps; int i, err = 0; @@ -908,9 +908,9 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) { int err; u32 page_size; - struct mlx4_dev_cap *dev_cap = NULL; - struct mlx4_func_cap *func_cap = NULL; - struct mlx4_init_hca_param *hca_param = NULL; + struct mlx4_dev_cap *dev_cap; + struct mlx4_func_cap *func_cap; + struct mlx4_init_hca_param *hca_param; hca_param = kzalloc(sizeof(*hca_param), GFP_KERNEL); func_cap = kzalloc(sizeof(*func_cap), GFP_KERNEL); -- cgit From 92272ec4107ef4f826b694a1338562c007e09821 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 2 Aug 2023 18:02:28 -0700 Subject: eth: add missing xdp.h includes in drivers Handful of drivers currently expect to get xdp.h by virtue of including netdevice.h. This will soon no longer be the case so add explicit includes. Reviewed-by: Wei Fang Reviewed-by: Gerhard Engleder Signed-off-by: Jakub Kicinski Acked-by: Jesper Dangaard Brouer Link: https://lore.kernel.org/r/20230803010230.1755386-2-kuba@kernel.org Signed-off-by: Martin KaFai Lau --- drivers/net/bonding/bond_main.c | 1 + drivers/net/ethernet/amazon/ena/ena_netdev.h | 1 + drivers/net/ethernet/engleder/tsnep.h | 1 + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 1 + drivers/net/ethernet/freescale/enetc/enetc.h | 1 + drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/fungible/funeth/funeth_txrx.h | 1 + drivers/net/ethernet/google/gve/gve.h | 1 + drivers/net/ethernet/intel/igc/igc.h | 1 + drivers/net/ethernet/microchip/lan966x/lan966x_main.h | 1 + drivers/net/ethernet/microsoft/mana/mana_en.c | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/ti/cpsw_priv.h | 1 + drivers/net/hyperv/hyperv_net.h | 1 + drivers/net/tap.c | 1 + 15 files changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7a0f25301f7e..2f21cca4fdaf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -90,6 +90,7 @@ #include #endif #include +#include #include "bonding_priv.h" diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 248b715b4d68..33c923e1261a 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "ena_com.h" diff --git a/drivers/net/ethernet/engleder/tsnep.h b/drivers/net/ethernet/engleder/tsnep.h index 11b29f56aaf9..6e14c918e3fb 100644 --- a/drivers/net/ethernet/engleder/tsnep.h +++ b/drivers/net/ethernet/engleder/tsnep.h @@ -14,6 +14,7 @@ #include #include #include +#include #define TSNEP "tsnep" diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index d56d7a13262e..bfb6c96c3b2f 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index 8577cf7699a0..7439739cd81a 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "enetc_hw.h" diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 8f1edcca96c4..5a0974e62f99 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ diff --git a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h index 53b7e95213a8..5eec552a1f24 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h +++ b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h @@ -5,6 +5,7 @@ #include #include +#include /* Tx descriptor size */ #define FUNETH_SQE_SIZE 64U diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 4b425bf71ede..a31256f70348 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "gve_desc.h" #include "gve_desc_dqo.h" diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 9db384f66a8e..4bffc3cb502f 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "igc_hw.h" diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 27f272831ea5..eb7d81b5e9f8 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index ac2acc9aca9d..21665f114fe9 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -11,6 +11,7 @@ #include #include +#include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 4ce5eaaae513..a6d034968654 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -22,6 +22,7 @@ #include #include #include +#include #include struct stmmac_resources { diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h index 34230145ca0b..0e27c433098d 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.h +++ b/drivers/net/ethernet/ti/cpsw_priv.h @@ -6,6 +6,7 @@ #ifndef DRIVERS_NET_ETHERNET_TI_CPSW_PRIV_H_ #define DRIVERS_NET_ETHERNET_TI_CPSW_PRIV_H_ +#include #include #include "davinci_cpdma.h" diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index c9dd69dbe1b8..810977952f95 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -16,6 +16,7 @@ #include #include #include +#include /* RSS related */ #define OID_GEN_RECEIVE_SCALE_CAPABILITIES 0x00010203 /* query only */ diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 9137fb8c1c42..b196a2a54355 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include -- cgit From 49e47a5b6145d86c30022fe0e949bbb24bae28ba Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 2 Aug 2023 18:02:29 -0700 Subject: net: move struct netdev_rx_queue out of netdevice.h struct netdev_rx_queue is touched in only a few places and having it defined in netdevice.h brings in the dependency on xdp.h, because struct xdp_rxq_info gets embedded in struct netdev_rx_queue. In prep for removal of xdp.h from netdevice.h move all the netdev_rx_queue stuff to a new header. We could technically break the new header up to avoid the sysfs.h include but it's so rarely included it doesn't seem to be worth it at this point. Reviewed-by: Amritha Nambiar Signed-off-by: Jakub Kicinski Acked-by: Jesper Dangaard Brouer Link: https://lore.kernel.org/r/20230803010230.1755386-3-kuba@kernel.org Signed-off-by: Martin KaFai Lau --- drivers/net/virtio_net.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0db14f6b87d3..5bcfd69333ea 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -22,6 +22,7 @@ #include #include #include +#include static int napi_weight = NAPI_POLL_WEIGHT; module_param(napi_weight, int, 0444); -- cgit From 6f9bad6b2d7d6b4e11032b944e379974e31c5c8f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 3 Aug 2023 16:00:07 -0700 Subject: eth: dpaa: add missing net/xdp.h include Add missing include for DPAA (fix aarch64 build). Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308040620.ty8oYNOP-lkp@intel.com/ Fixes: 680ee0456a57 ("net: invert the netdevice.h vs xdp.h dependency") Reviewed-by: Martin KaFai Lau Link: https://lore.kernel.org/r/20230803230008.362214-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index 35b8cea7f886..ac3c8ed57bbe 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -8,6 +8,7 @@ #include #include +#include #include #include -- cgit From 58e701264f15a8984136f4997faf99cb22b121f3 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Wed, 2 Aug 2023 17:31:56 +0800 Subject: net: microchip: vcap api: Use ERR_CAST() in vcap_decode_rule() There is a warning reported by coccinelle: ./drivers/net/ethernet/microchip/vcap/vcap_api.c:2399:9-16: WARNING: ERR_CAST can be used with ri Use ERR_CAST instead of ERR_PTR + PTR_ERR to simplify the conversion process. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/vcap/vcap_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index a418ad8e8770..a7b43f99bc80 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -2396,7 +2396,7 @@ struct vcap_rule *vcap_decode_rule(struct vcap_rule_internal *elem) ri = vcap_dup_rule(elem, elem->state == VCAP_RS_DISABLED); if (IS_ERR(ri)) - return ERR_PTR(PTR_ERR(ri)); + return ERR_CAST(ri); if (ri->state == VCAP_RS_DISABLED) goto out; -- cgit From 62c1bff593b7e30041d0273b835af9fd6f5ee737 Mon Sep 17 00:00:00 2001 From: Souradeep Chakrabarti Date: Wed, 2 Aug 2023 04:07:40 -0700 Subject: net: mana: Configure hwc timeout from hardware At present hwc timeout value is a fixed value. This patch sets the hwc timeout from the hardware. It now uses a new hardware capability GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG to query and set the value in hwc_timeout. Signed-off-by: Souradeep Chakrabarti Reviewed-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/ethernet/microsoft/mana/gdma_main.c | 30 +++++++++++++++++++++++- drivers/net/ethernet/microsoft/mana/hw_channel.c | 24 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index 3765d3389a9a..6367de0c2c2e 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -106,6 +106,25 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev) return 0; } +static int mana_gd_query_hwc_timeout(struct pci_dev *pdev, u32 *timeout_val) +{ + struct gdma_context *gc = pci_get_drvdata(pdev); + struct gdma_query_hwc_timeout_resp resp = {}; + struct gdma_query_hwc_timeout_req req = {}; + int err; + + mana_gd_init_req_hdr(&req.hdr, GDMA_QUERY_HWC_TIMEOUT, + sizeof(req), sizeof(resp)); + req.timeout_ms = *timeout_val; + err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp); + if (err || resp.hdr.status) + return err ? err : -EPROTO; + + *timeout_val = resp.timeout_ms; + + return 0; +} + static int mana_gd_detect_devices(struct pci_dev *pdev) { struct gdma_context *gc = pci_get_drvdata(pdev); @@ -882,8 +901,10 @@ int mana_gd_verify_vf_version(struct pci_dev *pdev) struct gdma_context *gc = pci_get_drvdata(pdev); struct gdma_verify_ver_resp resp = {}; struct gdma_verify_ver_req req = {}; + struct hw_channel_context *hwc; int err; + hwc = gc->hwc.driver_data; mana_gd_init_req_hdr(&req.hdr, GDMA_VERIFY_VF_DRIVER_VERSION, sizeof(req), sizeof(resp)); @@ -910,7 +931,14 @@ int mana_gd_verify_vf_version(struct pci_dev *pdev) err, resp.hdr.status); return err ? err : -EPROTO; } - + if (resp.pf_cap_flags1 & GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG) { + err = mana_gd_query_hwc_timeout(pdev, &hwc->hwc_timeout); + if (err) { + dev_err(gc->dev, "Failed to set the hwc timeout %d\n", err); + return err; + } + dev_dbg(gc->dev, "set the hwc timeout to %u\n", hwc->hwc_timeout); + } return 0; } diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c index 2bd1d74021f7..9d1cd3bfcf66 100644 --- a/drivers/net/ethernet/microsoft/mana/hw_channel.c +++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c @@ -174,7 +174,25 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self, complete(&hwc->hwc_init_eqe_comp); break; + case GDMA_EQE_HWC_SOC_RECONFIG_DATA: + type_data.as_uint32 = event->details[0]; + type = type_data.type; + val = type_data.value; + + switch (type) { + case HWC_DATA_CFG_HWC_TIMEOUT: + hwc->hwc_timeout = val; + break; + + default: + dev_warn(hwc->dev, "Received unknown reconfig type %u\n", type); + break; + } + + break; + default: + dev_warn(hwc->dev, "Received unknown gdma event %u\n", event->type); /* Ignore unknown events, which should never happen. */ break; } @@ -696,6 +714,7 @@ int mana_hwc_create_channel(struct gdma_context *gc) gd->driver_data = hwc; hwc->gdma_dev = gd; hwc->dev = gc->dev; + hwc->hwc_timeout = HW_CHANNEL_WAIT_RESOURCE_TIMEOUT_MS; /* HWC's instance number is always 0. */ gd->dev_id.as_uint32 = 0; @@ -770,6 +789,8 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) hwc->gdma_dev->doorbell = INVALID_DOORBELL; hwc->gdma_dev->pdid = INVALID_PDID; + hwc->hwc_timeout = 0; + kfree(hwc); gc->hwc.driver_data = NULL; gc->hwc.gdma_context = NULL; @@ -825,7 +846,8 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len, goto out; } - if (!wait_for_completion_timeout(&ctx->comp_event, 30 * HZ)) { + if (!wait_for_completion_timeout(&ctx->comp_event, + (msecs_to_jiffies(hwc->hwc_timeout) * HZ))) { dev_err(hwc->dev, "HWC: Request timed out!\n"); err = -ETIMEDOUT; goto out; -- cgit From 86b7e033d684a9d4ca20ad8e6f8b9300cf99668f Mon Sep 17 00:00:00 2001 From: Zhu Wang Date: Thu, 3 Aug 2023 16:29:00 +0800 Subject: net: lan966x: Do not check 0 for platform_get_irq_byname() Since platform_get_irq_byname() never returned zero, so it need not to check whether it returned zero, it returned -EINVAL or -ENXIO when failed, so we replace the return error code with the result it returned. Signed-off-by: Zhu Wang Reviewed-by: Simon Horman Reviewed-by: Horatiu Vultur Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 4a1acc7234f6..0d6e79af2410 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -1119,8 +1119,8 @@ static int lan966x_probe(struct platform_device *pdev) /* set irq */ lan966x->xtr_irq = platform_get_irq_byname(pdev, "xtr"); - if (lan966x->xtr_irq <= 0) - return -EINVAL; + if (lan966x->xtr_irq < 0) + return lan966x->xtr_irq; err = devm_request_threaded_irq(&pdev->dev, lan966x->xtr_irq, NULL, lan966x_xtr_irq_handler, IRQF_ONESHOT, -- cgit From faa9039161ef0271bc36c2bf4d01c7897f07524d Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Thu, 3 Aug 2023 21:51:38 +0800 Subject: net: hns3: Remove unused function declarations Commit 1e6e76101fd9 ("net: hns3: configure promisc mode for VF asynchronously") left behind hclge_inform_vf_promisc_info() declaration. And commit 68c0a5c70614 ("net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support") declared but never implemented hclge_cmd_mdio_write() and hclge_cmd_mdio_read(). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230803135138.37456-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 4 ---- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 - 2 files changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 91c173f40701..0bd858620f27 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -886,8 +886,4 @@ struct hclge_query_wol_supported_cmd { struct hclge_hw; int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num); -enum hclge_comm_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw, - struct hclge_desc *desc); -enum hclge_comm_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw, - struct hclge_desc *desc); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6a43d1515585..70b059e6d35f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1146,7 +1146,6 @@ int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc); void hclge_report_hw_error(struct hclge_dev *hdev, enum hnae3_hw_error_type type); -void hclge_inform_vf_promisc_info(struct hclge_vport *vport); int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); int hclge_push_vf_link_status(struct hclge_vport *vport); int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); -- cgit From f5f2d9bb52f901929c04ea2585160f1b7317071d Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Thu, 3 Aug 2023 22:19:04 +0800 Subject: ixgbevf: Remove unused function declarations ixgbe_napi_add_all()/ixgbe_napi_del_all() are declared but never implemented in commit 92915f71201b ("ixgbevf: Driver main and ethool interface module and main header") Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230803141904.15316-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 149c733fcc2b..130cb868774c 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -486,9 +486,6 @@ static inline int ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring, { return 0; } #endif /* CONFIG_IXGBEVF_IPSEC */ -void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter); -void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter); - #define ixgbevf_hw_to_netdev(hw) \ (((struct ixgbevf_adapter *)(hw)->back)->netdev) -- cgit From 852c18d5611e5632b8d4456181462896e87b1662 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Thu, 3 Aug 2023 22:20:47 +0800 Subject: mlxsw: spectrum: Remove unused function declarations Commit c3d2ed93b14d ("mlxsw: Remove old parsing depth infrastructure") left behind mlxsw_sp_nve_inc_parsing_depth_get()/mlxsw_sp_nve_inc_parsing_depth_put(). And commit 532b49e41e64 ("mlxsw: spectrum_span: Derive SBIB from maximum port speed & MTU") remove mlxsw_sp_span_port_mtu_update()/mlxsw_sp_span_speed_update_work() but leave the declarations. Signed-off-by: Yue Haibing Reviewed-by: Ido Schimmel Link: https://lore.kernel.org/r/20230803142047.42660-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 ---- drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h | 5 ----- 2 files changed, 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 62151f0531ae..8da7bb04fc3a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -1401,10 +1401,6 @@ void mlxsw_sp_port_nve_fini(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_nve_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp); -/* spectrum_nve_vxlan.c */ -int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp); - /* spectrum_trap.c */ int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h index 82e711afb02b..c59b5f11f357 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h @@ -93,13 +93,8 @@ void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp); struct mlxsw_sp_span_entry * mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, const struct net_device *to_dev); - void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_span_entry *span_entry); - -int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu); -void mlxsw_sp_span_speed_update_work(struct work_struct *work); - int mlxsw_sp_span_agent_get(struct mlxsw_sp *mlxsw_sp, int *p_span_id, const struct mlxsw_sp_span_agent_parms *parms); void mlxsw_sp_span_agent_put(struct mlxsw_sp *mlxsw_sp, int span_id); -- cgit From f4bf467883f210d0bfbe784fffca52887de147fb Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 3 Aug 2023 16:56:24 +0100 Subject: net: phy: move marking PHY on SFP module into SFP code Move marking the PHY as being on a SFP module into the SFP code between getting the PHY device (and thus initialising the phy_device structure) and registering the discovered device. This means that PHY drivers can use phy_on_sfp() in their match and get_features methods. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qRaga-001vKt-8X@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 2 -- drivers/net/phy/sfp.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e19c4fee8d22..3e9909b30938 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1489,8 +1489,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, if (phydev->sfp_bus_attached) dev->sfp_bus = phydev->sfp_bus; - else if (dev->sfp_bus) - phydev->is_on_sfp_module = true; } /* Some Ethernet drivers try to connect to a PHY device before diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index d855a18308d7..4ecfac227865 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -1763,6 +1763,9 @@ static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45) return PTR_ERR(phy); } + /* Mark this PHY as being on a SFP module */ + phy->is_on_sfp_module = true; + err = phy_device_register(phy); if (err) { phy_device_free(phy); -- cgit From 66ce8e6b49df401854f0c98bed50a65e4167825b Mon Sep 17 00:00:00 2001 From: Rushil Gupta Date: Fri, 4 Aug 2023 21:34:41 +0000 Subject: gve: Control path for DQO-QPL GVE supports QPL ("queue-page-list") mode where all data is communicated through a set of pre-registered pages. Adding this mode to DQO descriptor format. Add checks, abi-changes and device options to support QPL mode for DQO in addition to GQI. Also, use pages-per-qpl supplied by device-option to control the size of the "queue-page-list". Signed-off-by: Rushil Gupta Reviewed-by: Willem de Bruijn Signed-off-by: Praveen Kaligineedi Signed-off-by: Bailey Forrest Signed-off-by: David S. Miller --- drivers/net/ethernet/google/gve/gve.h | 29 ++++++++- drivers/net/ethernet/google/gve/gve_adminq.c | 89 ++++++++++++++++++++++++---- drivers/net/ethernet/google/gve/gve_adminq.h | 10 ++++ drivers/net/ethernet/google/gve/gve_main.c | 20 +++++-- 4 files changed, 128 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index a31256f70348..3bd6eed7280f 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -52,6 +52,12 @@ #define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182 +#define DQO_QPL_DEFAULT_TX_PAGES 512 +#define DQO_QPL_DEFAULT_RX_PAGES 2048 + +/* Maximum TSO size supported on DQO */ +#define GVE_DQO_TX_MAX 0x3FFFF + /* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */ struct gve_rx_desc_queue { struct gve_rx_desc *desc_ring; /* the descriptor ring */ @@ -218,6 +224,9 @@ struct gve_rx_ring { * which cannot be reused yet. */ struct gve_index_list used_buf_states; + + /* qpl assigned to this queue */ + struct gve_queue_page_list *qpl; } dqo; }; @@ -454,6 +463,12 @@ struct gve_tx_ring { s16 num_pending_packets; u32 complq_mask; /* complq size is complq_mask + 1 */ + + /* QPL fields */ + struct { + /* qpl assigned to this queue */ + struct gve_queue_page_list *qpl; + }; } dqo; } ____cacheline_aligned; struct netdev_queue *netdev_txq; @@ -532,6 +547,7 @@ enum gve_queue_format { GVE_GQI_RDA_FORMAT = 0x1, GVE_GQI_QPL_FORMAT = 0x2, GVE_DQO_RDA_FORMAT = 0x3, + GVE_DQO_QPL_FORMAT = 0x4, }; struct gve_priv { @@ -551,7 +567,8 @@ struct gve_priv { u16 num_event_counters; u16 tx_desc_cnt; /* num desc per ring */ u16 rx_desc_cnt; /* num desc per ring */ - u16 tx_pages_per_qpl; /* tx buffer length */ + u16 tx_pages_per_qpl; /* Suggested number of pages per qpl for TX queues by NIC */ + u16 rx_pages_per_qpl; /* Suggested number of pages per qpl for RX queues by NIC */ u16 rx_data_slot_cnt; /* rx buffer length */ u64 max_registered_pages; u64 num_registered_pages; /* num pages registered with NIC */ @@ -809,11 +826,17 @@ static inline u32 gve_rx_idx_to_ntfy(struct gve_priv *priv, u32 queue_idx) return (priv->num_ntfy_blks / 2) + queue_idx; } +static inline bool gve_is_qpl(struct gve_priv *priv) +{ + return priv->queue_format == GVE_GQI_QPL_FORMAT || + priv->queue_format == GVE_DQO_QPL_FORMAT; +} + /* Returns the number of tx queue page lists */ static inline u32 gve_num_tx_qpls(struct gve_priv *priv) { - if (priv->queue_format != GVE_GQI_QPL_FORMAT) + if (!gve_is_qpl(priv)) return 0; return priv->tx_cfg.num_queues + priv->num_xdp_queues; @@ -833,7 +856,7 @@ static inline u32 gve_num_xdp_qpls(struct gve_priv *priv) */ static inline u32 gve_num_rx_qpls(struct gve_priv *priv) { - if (priv->queue_format != GVE_GQI_QPL_FORMAT) + if (!gve_is_qpl(priv)) return 0; return priv->rx_cfg.num_queues; diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c index 252974202a3f..79db7a6d42bc 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -39,7 +39,8 @@ void gve_parse_device_option(struct gve_priv *priv, struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, struct gve_device_option_dqo_rda **dev_op_dqo_rda, - struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) + struct gve_device_option_jumbo_frames **dev_op_jumbo_frames, + struct gve_device_option_dqo_qpl **dev_op_dqo_qpl) { u32 req_feat_mask = be32_to_cpu(option->required_features_mask); u16 option_length = be16_to_cpu(option->option_length); @@ -112,6 +113,22 @@ void gve_parse_device_option(struct gve_priv *priv, } *dev_op_dqo_rda = (void *)(option + 1); break; + case GVE_DEV_OPT_ID_DQO_QPL: + if (option_length < sizeof(**dev_op_dqo_qpl) || + req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL) { + dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT, + "DQO QPL", (int)sizeof(**dev_op_dqo_qpl), + GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL, + option_length, req_feat_mask); + break; + } + + if (option_length > sizeof(**dev_op_dqo_qpl)) { + dev_warn(&priv->pdev->dev, + GVE_DEVICE_OPTION_TOO_BIG_FMT, "DQO QPL"); + } + *dev_op_dqo_qpl = (void *)(option + 1); + break; case GVE_DEV_OPT_ID_JUMBO_FRAMES: if (option_length < sizeof(**dev_op_jumbo_frames) || req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) { @@ -146,7 +163,8 @@ gve_process_device_options(struct gve_priv *priv, struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, struct gve_device_option_dqo_rda **dev_op_dqo_rda, - struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) + struct gve_device_option_jumbo_frames **dev_op_jumbo_frames, + struct gve_device_option_dqo_qpl **dev_op_dqo_qpl) { const int num_options = be16_to_cpu(descriptor->num_device_options); struct gve_device_option *dev_opt; @@ -166,7 +184,8 @@ gve_process_device_options(struct gve_priv *priv, gve_parse_device_option(priv, descriptor, dev_opt, dev_op_gqi_rda, dev_op_gqi_qpl, - dev_op_dqo_rda, dev_op_jumbo_frames); + dev_op_dqo_rda, dev_op_jumbo_frames, + dev_op_dqo_qpl); dev_opt = next_opt; } @@ -505,12 +524,24 @@ static int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_index) cmd.create_tx_queue.queue_page_list_id = cpu_to_be32(qpl_id); } else { + u16 comp_ring_size; + u32 qpl_id = 0; + + if (priv->queue_format == GVE_DQO_RDA_FORMAT) { + qpl_id = GVE_RAW_ADDRESSING_QPL_ID; + comp_ring_size = + priv->options_dqo_rda.tx_comp_ring_entries; + } else { + qpl_id = tx->dqo.qpl->id; + comp_ring_size = priv->tx_desc_cnt; + } + cmd.create_tx_queue.queue_page_list_id = cpu_to_be32(qpl_id); cmd.create_tx_queue.tx_ring_size = cpu_to_be16(priv->tx_desc_cnt); cmd.create_tx_queue.tx_comp_ring_addr = cpu_to_be64(tx->complq_bus_dqo); cmd.create_tx_queue.tx_comp_ring_size = - cpu_to_be16(priv->options_dqo_rda.tx_comp_ring_entries); + cpu_to_be16(comp_ring_size); } return gve_adminq_issue_cmd(priv, &cmd); @@ -555,6 +586,18 @@ static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index) cmd.create_rx_queue.queue_page_list_id = cpu_to_be32(qpl_id); cmd.create_rx_queue.packet_buffer_size = cpu_to_be16(rx->packet_buffer_size); } else { + u16 rx_buff_ring_entries; + u32 qpl_id = 0; + + if (priv->queue_format == GVE_DQO_RDA_FORMAT) { + qpl_id = GVE_RAW_ADDRESSING_QPL_ID; + rx_buff_ring_entries = + priv->options_dqo_rda.rx_buff_ring_entries; + } else { + qpl_id = rx->dqo.qpl->id; + rx_buff_ring_entries = priv->rx_desc_cnt; + } + cmd.create_rx_queue.queue_page_list_id = cpu_to_be32(qpl_id); cmd.create_rx_queue.rx_ring_size = cpu_to_be16(priv->rx_desc_cnt); cmd.create_rx_queue.rx_desc_ring_addr = @@ -564,7 +607,7 @@ static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index) cmd.create_rx_queue.packet_buffer_size = cpu_to_be16(priv->data_buffer_size_dqo); cmd.create_rx_queue.rx_buff_ring_size = - cpu_to_be16(priv->options_dqo_rda.rx_buff_ring_entries); + cpu_to_be16(rx_buff_ring_entries); cmd.create_rx_queue.enable_rsc = !!(priv->dev->features & NETIF_F_LRO); } @@ -675,9 +718,13 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv, const struct gve_device_option_dqo_rda *dev_op_dqo_rda) { priv->tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries); + priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries); + + if (priv->queue_format == GVE_DQO_QPL_FORMAT) + return 0; + priv->options_dqo_rda.tx_comp_ring_entries = be16_to_cpu(dev_op_dqo_rda->tx_comp_ring_entries); - priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries); priv->options_dqo_rda.rx_buff_ring_entries = be16_to_cpu(dev_op_dqo_rda->rx_buff_ring_entries); @@ -687,7 +734,9 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv, static void gve_enable_supported_features(struct gve_priv *priv, u32 supported_features_mask, const struct gve_device_option_jumbo_frames - *dev_op_jumbo_frames) + *dev_op_jumbo_frames, + const struct gve_device_option_dqo_qpl + *dev_op_dqo_qpl) { /* Before control reaches this point, the page-size-capped max MTU from * the gve_device_descriptor field has already been stored in @@ -699,6 +748,18 @@ static void gve_enable_supported_features(struct gve_priv *priv, "JUMBO FRAMES device option enabled.\n"); priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu); } + + /* Override pages for qpl for DQO-QPL */ + if (dev_op_dqo_qpl) { + priv->tx_pages_per_qpl = + be16_to_cpu(dev_op_dqo_qpl->tx_pages_per_qpl); + priv->rx_pages_per_qpl = + be16_to_cpu(dev_op_dqo_qpl->rx_pages_per_qpl); + if (priv->tx_pages_per_qpl == 0) + priv->tx_pages_per_qpl = DQO_QPL_DEFAULT_TX_PAGES; + if (priv->rx_pages_per_qpl == 0) + priv->rx_pages_per_qpl = DQO_QPL_DEFAULT_RX_PAGES; + } } int gve_adminq_describe_device(struct gve_priv *priv) @@ -707,6 +768,7 @@ int gve_adminq_describe_device(struct gve_priv *priv) struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL; struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL; struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL; + struct gve_device_option_dqo_qpl *dev_op_dqo_qpl = NULL; struct gve_device_descriptor *descriptor; u32 supported_features_mask = 0; union gve_adminq_command cmd; @@ -733,13 +795,14 @@ int gve_adminq_describe_device(struct gve_priv *priv) err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda, &dev_op_gqi_qpl, &dev_op_dqo_rda, - &dev_op_jumbo_frames); + &dev_op_jumbo_frames, + &dev_op_dqo_qpl); if (err) goto free_device_descriptor; /* If the GQI_RAW_ADDRESSING option is not enabled and the queue format * is not set to GqiRda, choose the queue format in a priority order: - * DqoRda, GqiRda, GqiQpl. Use GqiQpl as default. + * DqoRda, DqoQpl, GqiRda, GqiQpl. Use GqiQpl as default. */ if (dev_op_dqo_rda) { priv->queue_format = GVE_DQO_RDA_FORMAT; @@ -747,7 +810,11 @@ int gve_adminq_describe_device(struct gve_priv *priv) "Driver is running with DQO RDA queue format.\n"); supported_features_mask = be32_to_cpu(dev_op_dqo_rda->supported_features_mask); - } else if (dev_op_gqi_rda) { + } else if (dev_op_dqo_qpl) { + priv->queue_format = GVE_DQO_QPL_FORMAT; + supported_features_mask = + be32_to_cpu(dev_op_dqo_qpl->supported_features_mask); + } else if (dev_op_gqi_rda) { priv->queue_format = GVE_GQI_RDA_FORMAT; dev_info(&priv->pdev->dev, "Driver is running with GQI RDA queue format.\n"); @@ -798,7 +865,7 @@ int gve_adminq_describe_device(struct gve_priv *priv) priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues); gve_enable_supported_features(priv, supported_features_mask, - dev_op_jumbo_frames); + dev_op_jumbo_frames, dev_op_dqo_qpl); free_device_descriptor: dma_free_coherent(&priv->pdev->dev, PAGE_SIZE, descriptor, diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h index f894beb3deaf..38a22279e863 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.h +++ b/drivers/net/ethernet/google/gve/gve_adminq.h @@ -109,6 +109,14 @@ struct gve_device_option_dqo_rda { static_assert(sizeof(struct gve_device_option_dqo_rda) == 8); +struct gve_device_option_dqo_qpl { + __be32 supported_features_mask; + __be16 tx_pages_per_qpl; + __be16 rx_pages_per_qpl; +}; + +static_assert(sizeof(struct gve_device_option_dqo_qpl) == 8); + struct gve_device_option_jumbo_frames { __be32 supported_features_mask; __be16 max_mtu; @@ -130,6 +138,7 @@ enum gve_dev_opt_id { GVE_DEV_OPT_ID_GQI_RDA = 0x2, GVE_DEV_OPT_ID_GQI_QPL = 0x3, GVE_DEV_OPT_ID_DQO_RDA = 0x4, + GVE_DEV_OPT_ID_DQO_QPL = 0x7, GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8, }; @@ -139,6 +148,7 @@ enum gve_dev_opt_req_feat_mask { GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0, + GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL = 0x0, }; enum gve_sup_feature_mask { diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index e6f1711d9be0..5704b5f57cd0 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -31,7 +31,6 @@ // Minimum amount of time between queue kicks in msec (10 seconds) #define MIN_TX_TIMEOUT_GAP (1000 * 10) -#define DQO_TX_MAX 0x3FFFF char gve_driver_name[] = "gve"; const char gve_version_str[] = GVE_VERSION; @@ -494,7 +493,7 @@ static int gve_setup_device_resources(struct gve_priv *priv) goto abort_with_stats_report; } - if (priv->queue_format == GVE_DQO_RDA_FORMAT) { + if (!gve_is_gqi(priv)) { priv->ptype_lut_dqo = kvzalloc(sizeof(*priv->ptype_lut_dqo), GFP_KERNEL); if (!priv->ptype_lut_dqo) { @@ -1083,11 +1082,12 @@ free_qpls: static int gve_alloc_qpls(struct gve_priv *priv) { int max_queues = priv->tx_cfg.max_queues + priv->rx_cfg.max_queues; + int page_count; int start_id; int i, j; int err; - if (priv->queue_format != GVE_GQI_QPL_FORMAT) + if (!gve_is_qpl(priv)) return 0; priv->qpls = kvcalloc(max_queues, sizeof(*priv->qpls), GFP_KERNEL); @@ -1095,17 +1095,25 @@ static int gve_alloc_qpls(struct gve_priv *priv) return -ENOMEM; start_id = gve_tx_start_qpl_id(priv); + page_count = priv->tx_pages_per_qpl; for (i = start_id; i < start_id + gve_num_tx_qpls(priv); i++) { err = gve_alloc_queue_page_list(priv, i, - priv->tx_pages_per_qpl); + page_count); if (err) goto free_qpls; } start_id = gve_rx_start_qpl_id(priv); + + /* For GQI_QPL number of pages allocated have 1:1 relationship with + * number of descriptors. For DQO, number of pages required are + * more than descriptors (because of out of order completions). + */ + page_count = priv->queue_format == GVE_GQI_QPL_FORMAT ? + priv->rx_data_slot_cnt : priv->rx_pages_per_qpl; for (i = start_id; i < start_id + gve_num_rx_qpls(priv); i++) { err = gve_alloc_queue_page_list(priv, i, - priv->rx_data_slot_cnt); + page_count); if (err) goto free_qpls; } @@ -2051,7 +2059,7 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) /* Big TCP is only supported on DQ*/ if (!gve_is_gqi(priv)) - netif_set_tso_max_size(priv->dev, DQO_TX_MAX); + netif_set_tso_max_size(priv->dev, GVE_DQO_TX_MAX); priv->num_registered_pages = 0; priv->rx_copybreak = GVE_DEFAULT_RX_COPYBREAK; -- cgit From a6fb8d5a8b6925f1e635818d3dd2d89531d4a058 Mon Sep 17 00:00:00 2001 From: Rushil Gupta Date: Fri, 4 Aug 2023 21:34:42 +0000 Subject: gve: Tx path for DQO-QPL Each QPL page is divided into GVE_TX_BUFS_PER_PAGE_DQO buffers. When a packet needs to be transmitted, we break the packet into max GVE_TX_BUF_SIZE_DQO sized chunks and transmit each chunk using a TX descriptor. We allocate the TX buffers from the free list in dqo_tx. We store these TX buffer indices in an array in the pending_packet structure. The TX buffers are returned to the free list in dqo_compl after receiving packet completion or when removing packets from miss completions list. Signed-off-by: Rushil Gupta Reviewed-by: Willem de Bruijn Signed-off-by: Praveen Kaligineedi Signed-off-by: Bailey Forrest Signed-off-by: David S. Miller --- drivers/net/ethernet/google/gve/gve.h | 77 ++++- drivers/net/ethernet/google/gve/gve_tx_dqo.c | 404 +++++++++++++++++++++------ 2 files changed, 398 insertions(+), 83 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 3bd6eed7280f..2042f79cea1f 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -58,6 +58,20 @@ /* Maximum TSO size supported on DQO */ #define GVE_DQO_TX_MAX 0x3FFFF +#define GVE_TX_BUF_SHIFT_DQO 11 + +/* 2K buffers for DQO-QPL */ +#define GVE_TX_BUF_SIZE_DQO BIT(GVE_TX_BUF_SHIFT_DQO) +#define GVE_TX_BUFS_PER_PAGE_DQO (PAGE_SIZE >> GVE_TX_BUF_SHIFT_DQO) +#define GVE_MAX_TX_BUFS_PER_PKT (DIV_ROUND_UP(GVE_DQO_TX_MAX, GVE_TX_BUF_SIZE_DQO)) + +/* If number of free/recyclable buffers are less than this threshold; driver + * allocs and uses a non-qpl page on the receive path of DQO QPL to free + * up buffers. + * Value is set big enough to post at least 3 64K LRO packet via 2K buffer to NIC. + */ +#define GVE_DQO_QPL_ONDEMAND_ALLOC_THRESHOLD 96 + /* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */ struct gve_rx_desc_queue { struct gve_rx_desc *desc_ring; /* the descriptor ring */ @@ -338,8 +352,14 @@ struct gve_tx_pending_packet_dqo { * All others correspond to `skb`'s frags and should be unmapped with * `dma_unmap_page`. */ - DEFINE_DMA_UNMAP_ADDR(dma[MAX_SKB_FRAGS + 1]); - DEFINE_DMA_UNMAP_LEN(len[MAX_SKB_FRAGS + 1]); + union { + struct { + DEFINE_DMA_UNMAP_ADDR(dma[MAX_SKB_FRAGS + 1]); + DEFINE_DMA_UNMAP_LEN(len[MAX_SKB_FRAGS + 1]); + }; + s16 tx_qpl_buf_ids[GVE_MAX_TX_BUFS_PER_PKT]; + }; + u16 num_bufs; /* Linked list index to next element in the list, or -1 if none */ @@ -394,6 +414,32 @@ struct gve_tx_ring { * set. */ u32 last_re_idx; + + /* free running number of packet buf descriptors posted */ + u16 posted_packet_desc_cnt; + /* free running number of packet buf descriptors completed */ + u16 completed_packet_desc_cnt; + + /* QPL fields */ + struct { + /* Linked list of gve_tx_buf_dqo. Index into + * tx_qpl_buf_next, or -1 if empty. + * + * This is a consumer list owned by the TX path. When it + * runs out, the producer list is stolen from the + * completion handling path + * (dqo_compl.free_tx_qpl_buf_head). + */ + s16 free_tx_qpl_buf_head; + + /* Free running count of the number of QPL tx buffers + * allocated + */ + u32 alloc_tx_qpl_buf_cnt; + + /* Cached value of `dqo_compl.free_tx_qpl_buf_cnt` */ + u32 free_tx_qpl_buf_cnt; + }; } dqo_tx; }; @@ -437,6 +483,24 @@ struct gve_tx_ring { * reached a specified timeout. */ struct gve_index_list timed_out_completions; + + /* QPL fields */ + struct { + /* Linked list of gve_tx_buf_dqo. Index into + * tx_qpl_buf_next, or -1 if empty. + * + * This is the producer list, owned by the completion + * handling path. When the consumer list + * (dqo_tx.free_tx_qpl_buf_head) is runs out, this list + * will be stolen. + */ + atomic_t free_tx_qpl_buf_head; + + /* Free running count of the number of tx buffers + * freed + */ + atomic_t free_tx_qpl_buf_cnt; + }; } dqo_compl; } ____cacheline_aligned; u64 pkt_done; /* free-running - total packets completed */ @@ -468,6 +532,15 @@ struct gve_tx_ring { struct { /* qpl assigned to this queue */ struct gve_queue_page_list *qpl; + + /* Each QPL page is divided into TX bounce buffers + * of size GVE_TX_BUF_SIZE_DQO. tx_qpl_buf_next is + * an array to manage linked lists of TX buffers. + * An entry j at index i implies that j'th buffer + * is next on the list after i + */ + s16 *tx_qpl_buf_next; + u32 num_tx_qpl_bufs; }; } dqo; } ____cacheline_aligned; diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c index 3c09e66ba1ab..1e19b834a613 100644 --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c @@ -13,6 +13,89 @@ #include #include +/* Returns true if tx_bufs are available. */ +static bool gve_has_free_tx_qpl_bufs(struct gve_tx_ring *tx, int count) +{ + int num_avail; + + if (!tx->dqo.qpl) + return true; + + num_avail = tx->dqo.num_tx_qpl_bufs - + (tx->dqo_tx.alloc_tx_qpl_buf_cnt - + tx->dqo_tx.free_tx_qpl_buf_cnt); + + if (count <= num_avail) + return true; + + /* Update cached value from dqo_compl. */ + tx->dqo_tx.free_tx_qpl_buf_cnt = + atomic_read_acquire(&tx->dqo_compl.free_tx_qpl_buf_cnt); + + num_avail = tx->dqo.num_tx_qpl_bufs - + (tx->dqo_tx.alloc_tx_qpl_buf_cnt - + tx->dqo_tx.free_tx_qpl_buf_cnt); + + return count <= num_avail; +} + +static s16 +gve_alloc_tx_qpl_buf(struct gve_tx_ring *tx) +{ + s16 index; + + index = tx->dqo_tx.free_tx_qpl_buf_head; + + /* No TX buffers available, try to steal the list from the + * completion handler. + */ + if (unlikely(index == -1)) { + tx->dqo_tx.free_tx_qpl_buf_head = + atomic_xchg(&tx->dqo_compl.free_tx_qpl_buf_head, -1); + index = tx->dqo_tx.free_tx_qpl_buf_head; + + if (unlikely(index == -1)) + return index; + } + + /* Remove TX buf from free list */ + tx->dqo_tx.free_tx_qpl_buf_head = tx->dqo.tx_qpl_buf_next[index]; + + return index; +} + +static void +gve_free_tx_qpl_bufs(struct gve_tx_ring *tx, + struct gve_tx_pending_packet_dqo *pkt) +{ + s16 index; + int i; + + if (!pkt->num_bufs) + return; + + index = pkt->tx_qpl_buf_ids[0]; + /* Create a linked list of buffers to be added to the free list */ + for (i = 1; i < pkt->num_bufs; i++) { + tx->dqo.tx_qpl_buf_next[index] = pkt->tx_qpl_buf_ids[i]; + index = pkt->tx_qpl_buf_ids[i]; + } + + while (true) { + s16 old_head = atomic_read_acquire(&tx->dqo_compl.free_tx_qpl_buf_head); + + tx->dqo.tx_qpl_buf_next[index] = old_head; + if (atomic_cmpxchg(&tx->dqo_compl.free_tx_qpl_buf_head, + old_head, + pkt->tx_qpl_buf_ids[0]) == old_head) { + break; + } + } + + atomic_add(pkt->num_bufs, &tx->dqo_compl.free_tx_qpl_buf_cnt); + pkt->num_bufs = 0; +} + /* Returns true if a gve_tx_pending_packet_dqo object is available. */ static bool gve_has_pending_packet(struct gve_tx_ring *tx) { @@ -136,9 +219,40 @@ static void gve_tx_free_ring_dqo(struct gve_priv *priv, int idx) kvfree(tx->dqo.pending_packets); tx->dqo.pending_packets = NULL; + kvfree(tx->dqo.tx_qpl_buf_next); + tx->dqo.tx_qpl_buf_next = NULL; + + if (tx->dqo.qpl) { + gve_unassign_qpl(priv, tx->dqo.qpl->id); + tx->dqo.qpl = NULL; + } + netif_dbg(priv, drv, priv->dev, "freed tx queue %d\n", idx); } +static int gve_tx_qpl_buf_init(struct gve_tx_ring *tx) +{ + int num_tx_qpl_bufs = GVE_TX_BUFS_PER_PAGE_DQO * + tx->dqo.qpl->num_entries; + int i; + + tx->dqo.tx_qpl_buf_next = kvcalloc(num_tx_qpl_bufs, + sizeof(tx->dqo.tx_qpl_buf_next[0]), + GFP_KERNEL); + if (!tx->dqo.tx_qpl_buf_next) + return -ENOMEM; + + tx->dqo.num_tx_qpl_bufs = num_tx_qpl_bufs; + + /* Generate free TX buf list */ + for (i = 0; i < num_tx_qpl_bufs - 1; i++) + tx->dqo.tx_qpl_buf_next[i] = i + 1; + tx->dqo.tx_qpl_buf_next[num_tx_qpl_bufs - 1] = -1; + + atomic_set_release(&tx->dqo_compl.free_tx_qpl_buf_head, -1); + return 0; +} + static int gve_tx_alloc_ring_dqo(struct gve_priv *priv, int idx) { struct gve_tx_ring *tx = &priv->tx[idx]; @@ -155,7 +269,9 @@ static int gve_tx_alloc_ring_dqo(struct gve_priv *priv, int idx) /* Queue sizes must be a power of 2 */ tx->mask = priv->tx_desc_cnt - 1; - tx->dqo.complq_mask = priv->options_dqo_rda.tx_comp_ring_entries - 1; + tx->dqo.complq_mask = priv->queue_format == GVE_DQO_RDA_FORMAT ? + priv->options_dqo_rda.tx_comp_ring_entries - 1 : + tx->mask; /* The max number of pending packets determines the maximum number of * descriptors which maybe written to the completion queue. @@ -211,6 +327,15 @@ static int gve_tx_alloc_ring_dqo(struct gve_priv *priv, int idx) if (!tx->q_resources) goto err; + if (gve_is_qpl(priv)) { + tx->dqo.qpl = gve_assign_tx_qpl(priv, idx); + if (!tx->dqo.qpl) + goto err; + + if (gve_tx_qpl_buf_init(tx)) + goto err; + } + gve_tx_add_to_block(priv, idx); return 0; @@ -267,20 +392,27 @@ static u32 num_avail_tx_slots(const struct gve_tx_ring *tx) return tx->mask - num_used; } +static bool gve_has_avail_slots_tx_dqo(struct gve_tx_ring *tx, + int desc_count, int buf_count) +{ + return gve_has_pending_packet(tx) && + num_avail_tx_slots(tx) >= desc_count && + gve_has_free_tx_qpl_bufs(tx, buf_count); +} + /* Stops the queue if available descriptors is less than 'count'. * Return: 0 if stop is not required. */ -static int gve_maybe_stop_tx_dqo(struct gve_tx_ring *tx, int count) +static int gve_maybe_stop_tx_dqo(struct gve_tx_ring *tx, + int desc_count, int buf_count) { - if (likely(gve_has_pending_packet(tx) && - num_avail_tx_slots(tx) >= count)) + if (likely(gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count))) return 0; /* Update cached TX head pointer */ tx->dqo_tx.head = atomic_read_acquire(&tx->dqo_compl.hw_tx_head); - if (likely(gve_has_pending_packet(tx) && - num_avail_tx_slots(tx) >= count)) + if (likely(gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count))) return 0; /* No space, so stop the queue */ @@ -295,8 +427,7 @@ static int gve_maybe_stop_tx_dqo(struct gve_tx_ring *tx, int count) */ tx->dqo_tx.head = atomic_read_acquire(&tx->dqo_compl.hw_tx_head); - if (likely(!gve_has_pending_packet(tx) || - num_avail_tx_slots(tx) < count)) + if (likely(!gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count))) return -EBUSY; netif_tx_start_queue(tx->netdev_txq); @@ -444,44 +575,16 @@ gve_tx_fill_general_ctx_desc(struct gve_tx_general_context_desc_dqo *desc, }; } -/* Returns 0 on success, or < 0 on error. - * - * Before this function is called, the caller must ensure - * gve_has_pending_packet(tx) returns true. - */ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - struct sk_buff *skb) + struct sk_buff *skb, + struct gve_tx_pending_packet_dqo *pkt, + s16 completion_tag, + u32 *desc_idx, + bool is_gso) { const struct skb_shared_info *shinfo = skb_shinfo(skb); - const bool is_gso = skb_is_gso(skb); - u32 desc_idx = tx->dqo_tx.tail; - - struct gve_tx_pending_packet_dqo *pkt; - struct gve_tx_metadata_dqo metadata; - s16 completion_tag; int i; - pkt = gve_alloc_pending_packet(tx); - pkt->skb = skb; - pkt->num_bufs = 0; - completion_tag = pkt - tx->dqo.pending_packets; - - gve_extract_tx_metadata_dqo(skb, &metadata); - if (is_gso) { - int header_len = gve_prep_tso(skb); - - if (unlikely(header_len < 0)) - goto err; - - gve_tx_fill_tso_ctx_desc(&tx->dqo.tx_ring[desc_idx].tso_ctx, - skb, &metadata, header_len); - desc_idx = (desc_idx + 1) & tx->mask; - } - - gve_tx_fill_general_ctx_desc(&tx->dqo.tx_ring[desc_idx].general_ctx, - &metadata); - desc_idx = (desc_idx + 1) & tx->mask; - /* Note: HW requires that the size of a non-TSO packet be within the * range of [17, 9728]. * @@ -490,6 +593,7 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, * - Hypervisor won't allow MTU larger than 9216. */ + pkt->num_bufs = 0; /* Map the linear portion of skb */ { u32 len = skb_headlen(skb); @@ -503,7 +607,7 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); ++pkt->num_bufs; - gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, + gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb, len, addr, completion_tag, /*eop=*/shinfo->nr_frags == 0, is_gso); } @@ -522,10 +626,139 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); ++pkt->num_bufs; - gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, + gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb, len, addr, completion_tag, is_eop, is_gso); } + return 0; +err: + for (i = 0; i < pkt->num_bufs; i++) { + if (i == 0) { + dma_unmap_single(tx->dev, + dma_unmap_addr(pkt, dma[i]), + dma_unmap_len(pkt, len[i]), + DMA_TO_DEVICE); + } else { + dma_unmap_page(tx->dev, + dma_unmap_addr(pkt, dma[i]), + dma_unmap_len(pkt, len[i]), + DMA_TO_DEVICE); + } + } + pkt->num_bufs = 0; + return -1; +} + +/* Tx buffer i corresponds to + * qpl_page_id = i / GVE_TX_BUFS_PER_PAGE_DQO + * qpl_page_offset = (i % GVE_TX_BUFS_PER_PAGE_DQO) * GVE_TX_BUF_SIZE_DQO + */ +static void gve_tx_buf_get_addr(struct gve_tx_ring *tx, + s16 index, + void **va, dma_addr_t *dma_addr) +{ + int page_id = index >> (PAGE_SHIFT - GVE_TX_BUF_SHIFT_DQO); + int offset = (index & (GVE_TX_BUFS_PER_PAGE_DQO - 1)) << GVE_TX_BUF_SHIFT_DQO; + + *va = page_address(tx->dqo.qpl->pages[page_id]) + offset; + *dma_addr = tx->dqo.qpl->page_buses[page_id] + offset; +} + +static int gve_tx_add_skb_copy_dqo(struct gve_tx_ring *tx, + struct sk_buff *skb, + struct gve_tx_pending_packet_dqo *pkt, + s16 completion_tag, + u32 *desc_idx, + bool is_gso) +{ + u32 copy_offset = 0; + dma_addr_t dma_addr; + u32 copy_len; + s16 index; + void *va; + + /* Break the packet into buffer size chunks */ + pkt->num_bufs = 0; + while (copy_offset < skb->len) { + index = gve_alloc_tx_qpl_buf(tx); + if (unlikely(index == -1)) + goto err; + + gve_tx_buf_get_addr(tx, index, &va, &dma_addr); + copy_len = min_t(u32, GVE_TX_BUF_SIZE_DQO, + skb->len - copy_offset); + skb_copy_bits(skb, copy_offset, va, copy_len); + + copy_offset += copy_len; + dma_sync_single_for_device(tx->dev, dma_addr, + copy_len, DMA_TO_DEVICE); + gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb, + copy_len, + dma_addr, + completion_tag, + copy_offset == skb->len, + is_gso); + + pkt->tx_qpl_buf_ids[pkt->num_bufs] = index; + ++tx->dqo_tx.alloc_tx_qpl_buf_cnt; + ++pkt->num_bufs; + } + + return 0; +err: + /* Should not be here if gve_has_free_tx_qpl_bufs() check is correct */ + gve_free_tx_qpl_bufs(tx, pkt); + return -ENOMEM; +} + +/* Returns 0 on success, or < 0 on error. + * + * Before this function is called, the caller must ensure + * gve_has_pending_packet(tx) returns true. + */ +static int gve_tx_add_skb_dqo(struct gve_tx_ring *tx, + struct sk_buff *skb) +{ + const bool is_gso = skb_is_gso(skb); + u32 desc_idx = tx->dqo_tx.tail; + struct gve_tx_pending_packet_dqo *pkt; + struct gve_tx_metadata_dqo metadata; + s16 completion_tag; + + pkt = gve_alloc_pending_packet(tx); + pkt->skb = skb; + completion_tag = pkt - tx->dqo.pending_packets; + + gve_extract_tx_metadata_dqo(skb, &metadata); + if (is_gso) { + int header_len = gve_prep_tso(skb); + + if (unlikely(header_len < 0)) + goto err; + + gve_tx_fill_tso_ctx_desc(&tx->dqo.tx_ring[desc_idx].tso_ctx, + skb, &metadata, header_len); + desc_idx = (desc_idx + 1) & tx->mask; + } + + gve_tx_fill_general_ctx_desc(&tx->dqo.tx_ring[desc_idx].general_ctx, + &metadata); + desc_idx = (desc_idx + 1) & tx->mask; + + if (tx->dqo.qpl) { + if (gve_tx_add_skb_copy_dqo(tx, skb, pkt, + completion_tag, + &desc_idx, is_gso)) + goto err; + } else { + if (gve_tx_add_skb_no_copy_dqo(tx, skb, pkt, + completion_tag, + &desc_idx, is_gso)) + goto err; + } + + tx->dqo_tx.posted_packet_desc_cnt += pkt->num_bufs; + /* Commit the changes to our state */ tx->dqo_tx.tail = desc_idx; @@ -547,22 +780,7 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, return 0; err: - for (i = 0; i < pkt->num_bufs; i++) { - if (i == 0) { - dma_unmap_single(tx->dev, - dma_unmap_addr(pkt, dma[i]), - dma_unmap_len(pkt, len[i]), - DMA_TO_DEVICE); - } else { - dma_unmap_page(tx->dev, - dma_unmap_addr(pkt, dma[i]), - dma_unmap_len(pkt, len[i]), - DMA_TO_DEVICE); - } - } - pkt->skb = NULL; - pkt->num_bufs = 0; gve_free_pending_packet(tx, pkt); return -1; @@ -636,40 +854,56 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, int num_buffer_descs; int total_num_descs; - if (skb_is_gso(skb)) { - /* If TSO doesn't meet HW requirements, attempt to linearize the - * packet. - */ - if (unlikely(!gve_can_send_tso(skb) && - skb_linearize(skb) < 0)) { - net_err_ratelimited("%s: Failed to transmit TSO packet\n", - priv->dev->name); - goto drop; - } - - if (unlikely(ipv6_hopopt_jumbo_remove(skb))) - goto drop; + if (tx->dqo.qpl) { + if (skb_is_gso(skb)) + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) + goto drop; - num_buffer_descs = gve_num_buffer_descs_needed(skb); + /* We do not need to verify the number of buffers used per + * packet or per segment in case of TSO as with 2K size buffers + * none of the TX packet rules would be violated. + * + * gve_can_send_tso() checks that each TCP segment of gso_size is + * not distributed over more than 9 SKB frags.. + */ + num_buffer_descs = DIV_ROUND_UP(skb->len, GVE_TX_BUF_SIZE_DQO); } else { - num_buffer_descs = gve_num_buffer_descs_needed(skb); + if (skb_is_gso(skb)) { + /* If TSO doesn't meet HW requirements, attempt to linearize the + * packet. + */ + if (unlikely(!gve_can_send_tso(skb) && + skb_linearize(skb) < 0)) { + net_err_ratelimited("%s: Failed to transmit TSO packet\n", + priv->dev->name); + goto drop; + } - if (unlikely(num_buffer_descs > GVE_TX_MAX_DATA_DESCS)) { - if (unlikely(skb_linearize(skb) < 0)) + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) goto drop; - num_buffer_descs = 1; + num_buffer_descs = gve_num_buffer_descs_needed(skb); + } else { + num_buffer_descs = gve_num_buffer_descs_needed(skb); + + if (unlikely(num_buffer_descs > GVE_TX_MAX_DATA_DESCS)) { + if (unlikely(skb_linearize(skb) < 0)) + goto drop; + + num_buffer_descs = 1; + } } } /* Metadata + (optional TSO) + data descriptors. */ total_num_descs = 1 + skb_is_gso(skb) + num_buffer_descs; if (unlikely(gve_maybe_stop_tx_dqo(tx, total_num_descs + - GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP))) { + GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP, + num_buffer_descs))) { return -1; } - if (unlikely(gve_tx_add_skb_no_copy_dqo(tx, skb) < 0)) + if (unlikely(gve_tx_add_skb_dqo(tx, skb) < 0)) goto drop; netdev_tx_sent_queue(tx->netdev_txq, skb->len); @@ -817,7 +1051,11 @@ static void gve_handle_packet_completion(struct gve_priv *priv, return; } } - gve_unmap_packet(tx->dev, pending_packet); + tx->dqo_tx.completed_packet_desc_cnt += pending_packet->num_bufs; + if (tx->dqo.qpl) + gve_free_tx_qpl_bufs(tx, pending_packet); + else + gve_unmap_packet(tx->dev, pending_packet); *bytes += pending_packet->skb->len; (*pkts)++; @@ -875,12 +1113,16 @@ static void remove_miss_completions(struct gve_priv *priv, remove_from_list(tx, &tx->dqo_compl.miss_completions, pending_packet); - /* Unmap buffers and free skb but do not unallocate packet i.e. + /* Unmap/free TX buffers and free skb but do not unallocate packet i.e. * the completion tag is not freed to ensure that the driver * can take appropriate action if a corresponding valid * completion is received later. */ - gve_unmap_packet(tx->dev, pending_packet); + if (tx->dqo.qpl) + gve_free_tx_qpl_bufs(tx, pending_packet); + else + gve_unmap_packet(tx->dev, pending_packet); + /* This indicates the packet was dropped. */ dev_kfree_skb_any(pending_packet->skb); pending_packet->skb = NULL; -- cgit From e7075ab4fb6b39730dfbfbfa3a5505d678f01d2c Mon Sep 17 00:00:00 2001 From: Rushil Gupta Date: Fri, 4 Aug 2023 21:34:43 +0000 Subject: gve: RX path for DQO-QPL The RX path allocates the QPL page pool at queue creation, and tries to reuse these pages through page recycling. This patch ensures that on refill no non-QPL pages are posted to the device. When the driver is running low on free buffers, an ondemand allocation step kicks in that allocates a non-qpl page for SKB business to free up the QPL page in use. gve_try_recycle_buf was moved to gve_rx_append_frags so that driver does not attempt to mark buffer as used if a non-qpl page was allocated ondemand. Signed-off-by: Rushil Gupta Reviewed-by: Willem de Bruijn Signed-off-by: Praveen Kaligineedi Signed-off-by: Bailey Forrest Signed-off-by: David S. Miller --- drivers/net/ethernet/google/gve/gve.h | 6 ++ drivers/net/ethernet/google/gve/gve_rx_dqo.c | 126 +++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 2042f79cea1f..0d1e681be250 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -241,6 +241,12 @@ struct gve_rx_ring { /* qpl assigned to this queue */ struct gve_queue_page_list *qpl; + + /* index into queue page list */ + u32 next_qpl_page_idx; + + /* track number of used buffers */ + u16 used_buf_states_cnt; } dqo; }; diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c index e57b73eb70f6..ea0e38b4d9e9 100644 --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c @@ -22,11 +22,13 @@ static int gve_buf_ref_cnt(struct gve_rx_buf_state_dqo *bs) } static void gve_free_page_dqo(struct gve_priv *priv, - struct gve_rx_buf_state_dqo *bs) + struct gve_rx_buf_state_dqo *bs, + bool free_page) { page_ref_sub(bs->page_info.page, bs->page_info.pagecnt_bias - 1); - gve_free_page(&priv->pdev->dev, bs->page_info.page, bs->addr, - DMA_FROM_DEVICE); + if (free_page) + gve_free_page(&priv->pdev->dev, bs->page_info.page, bs->addr, + DMA_FROM_DEVICE); bs->page_info.page = NULL; } @@ -130,12 +132,20 @@ gve_get_recycled_buf_state(struct gve_rx_ring *rx) */ for (i = 0; i < 5; i++) { buf_state = gve_dequeue_buf_state(rx, &rx->dqo.used_buf_states); - if (gve_buf_ref_cnt(buf_state) == 0) + if (gve_buf_ref_cnt(buf_state) == 0) { + rx->dqo.used_buf_states_cnt--; return buf_state; + } gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state); } + /* For QPL, we cannot allocate any new buffers and must + * wait for the existing ones to be available. + */ + if (rx->dqo.qpl) + return NULL; + /* If there are no free buf states discard an entry from * `used_buf_states` so it can be used. */ @@ -144,23 +154,39 @@ gve_get_recycled_buf_state(struct gve_rx_ring *rx) if (gve_buf_ref_cnt(buf_state) == 0) return buf_state; - gve_free_page_dqo(rx->gve, buf_state); + gve_free_page_dqo(rx->gve, buf_state, true); gve_free_buf_state(rx, buf_state); } return NULL; } -static int gve_alloc_page_dqo(struct gve_priv *priv, +static int gve_alloc_page_dqo(struct gve_rx_ring *rx, struct gve_rx_buf_state_dqo *buf_state) { - int err; + struct gve_priv *priv = rx->gve; + u32 idx; - err = gve_alloc_page(priv, &priv->pdev->dev, &buf_state->page_info.page, - &buf_state->addr, DMA_FROM_DEVICE, GFP_ATOMIC); - if (err) - return err; + if (!rx->dqo.qpl) { + int err; + err = gve_alloc_page(priv, &priv->pdev->dev, + &buf_state->page_info.page, + &buf_state->addr, + DMA_FROM_DEVICE, GFP_ATOMIC); + if (err) + return err; + } else { + idx = rx->dqo.next_qpl_page_idx; + if (idx >= priv->rx_pages_per_qpl) { + net_err_ratelimited("%s: Out of QPL pages\n", + priv->dev->name); + return -ENOMEM; + } + buf_state->page_info.page = rx->dqo.qpl->pages[idx]; + buf_state->addr = rx->dqo.qpl->page_buses[idx]; + rx->dqo.next_qpl_page_idx++; + } buf_state->page_info.page_offset = 0; buf_state->page_info.page_address = page_address(buf_state->page_info.page); @@ -195,9 +221,13 @@ static void gve_rx_free_ring_dqo(struct gve_priv *priv, int idx) for (i = 0; i < rx->dqo.num_buf_states; i++) { struct gve_rx_buf_state_dqo *bs = &rx->dqo.buf_states[i]; - + /* Only free page for RDA. QPL pages are freed in gve_main. */ if (bs->page_info.page) - gve_free_page_dqo(priv, bs); + gve_free_page_dqo(priv, bs, !rx->dqo.qpl); + } + if (rx->dqo.qpl) { + gve_unassign_qpl(priv, rx->dqo.qpl->id); + rx->dqo.qpl = NULL; } if (rx->dqo.bufq.desc_ring) { @@ -229,7 +259,8 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx) int i; const u32 buffer_queue_slots = - priv->options_dqo_rda.rx_buff_ring_entries; + priv->queue_format == GVE_DQO_RDA_FORMAT ? + priv->options_dqo_rda.rx_buff_ring_entries : priv->rx_desc_cnt; const u32 completion_queue_slots = priv->rx_desc_cnt; netif_dbg(priv, drv, priv->dev, "allocating rx ring DQO\n"); @@ -243,7 +274,9 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx) rx->ctx.skb_head = NULL; rx->ctx.skb_tail = NULL; - rx->dqo.num_buf_states = min_t(s16, S16_MAX, buffer_queue_slots * 4); + rx->dqo.num_buf_states = priv->queue_format == GVE_DQO_RDA_FORMAT ? + min_t(s16, S16_MAX, buffer_queue_slots * 4) : + priv->rx_pages_per_qpl; rx->dqo.buf_states = kvcalloc(rx->dqo.num_buf_states, sizeof(rx->dqo.buf_states[0]), GFP_KERNEL); @@ -275,6 +308,13 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx) if (!rx->dqo.bufq.desc_ring) goto err; + if (priv->queue_format != GVE_DQO_RDA_FORMAT) { + rx->dqo.qpl = gve_assign_rx_qpl(priv, rx->q_num); + if (!rx->dqo.qpl) + goto err; + rx->dqo.next_qpl_page_idx = 0; + } + rx->q_resources = dma_alloc_coherent(hdev, sizeof(*rx->q_resources), &rx->q_resources_bus, GFP_KERNEL); if (!rx->q_resources) @@ -352,7 +392,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx) if (unlikely(!buf_state)) break; - if (unlikely(gve_alloc_page_dqo(priv, buf_state))) { + if (unlikely(gve_alloc_page_dqo(rx, buf_state))) { u64_stats_update_begin(&rx->statss); rx->rx_buf_alloc_fail++; u64_stats_update_end(&rx->statss); @@ -415,6 +455,7 @@ static void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx, mark_used: gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state); + rx->dqo.used_buf_states_cnt++; } static void gve_rx_skb_csum(struct sk_buff *skb, @@ -475,6 +516,43 @@ static void gve_rx_free_skb(struct gve_rx_ring *rx) rx->ctx.skb_tail = NULL; } +static bool gve_rx_should_trigger_copy_ondemand(struct gve_rx_ring *rx) +{ + if (!rx->dqo.qpl) + return false; + if (rx->dqo.used_buf_states_cnt < + (rx->dqo.num_buf_states - + GVE_DQO_QPL_ONDEMAND_ALLOC_THRESHOLD)) + return false; + return true; +} + +static int gve_rx_copy_ondemand(struct gve_rx_ring *rx, + struct gve_rx_buf_state_dqo *buf_state, + u16 buf_len) +{ + struct page *page = alloc_page(GFP_ATOMIC); + int num_frags; + + if (!page) + return -ENOMEM; + + memcpy(page_address(page), + buf_state->page_info.page_address + + buf_state->page_info.page_offset, + buf_len); + num_frags = skb_shinfo(rx->ctx.skb_tail)->nr_frags; + skb_add_rx_frag(rx->ctx.skb_tail, num_frags, page, + 0, buf_len, PAGE_SIZE); + + u64_stats_update_begin(&rx->statss); + rx->rx_frag_alloc_cnt++; + u64_stats_update_end(&rx->statss); + /* Return unused buffer. */ + gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states, buf_state); + return 0; +} + /* Chains multi skbs for single rx packet. * Returns 0 if buffer is appended, -1 otherwise. */ @@ -502,12 +580,20 @@ static int gve_rx_append_frags(struct napi_struct *napi, rx->ctx.skb_head->truesize += priv->data_buffer_size_dqo; } + /* Trigger ondemand page allocation if we are running low on buffers */ + if (gve_rx_should_trigger_copy_ondemand(rx)) + return gve_rx_copy_ondemand(rx, buf_state, buf_len); + skb_add_rx_frag(rx->ctx.skb_tail, num_frags, buf_state->page_info.page, buf_state->page_info.page_offset, buf_len, priv->data_buffer_size_dqo); gve_dec_pagecnt_bias(&buf_state->page_info); + /* Advances buffer page-offset if page is partially used. + * Marks buffer as used if page is full. + */ + gve_try_recycle_buf(priv, rx, buf_state); return 0; } @@ -561,8 +647,6 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, priv)) != 0) { goto error; } - - gve_try_recycle_buf(priv, rx, buf_state); return 0; } @@ -588,6 +672,12 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, goto error; rx->ctx.skb_tail = rx->ctx.skb_head; + if (gve_rx_should_trigger_copy_ondemand(rx)) { + if (gve_rx_copy_ondemand(rx, buf_state, buf_len) < 0) + goto error; + return 0; + } + skb_add_rx_frag(rx->ctx.skb_head, 0, buf_state->page_info.page, buf_state->page_info.page_offset, buf_len, priv->data_buffer_size_dqo); -- cgit From b1d13f7a3b5396503e6869ed627bb4eeab9b524f Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Fri, 4 Aug 2023 13:33:53 -0700 Subject: net: mana: Add page pool for RX buffers Add page pool for RX buffers for faster buffer cycle and reduce CPU usage. The standard page pool API is used. With iperf and 128 threads test, this patch improved the throughput by 12-15%, and decreased the IRQ associated CPU's usage from 99-100% to 10-50%. Signed-off-by: Haiyang Zhang Reviewed-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/ethernet/microsoft/mana/mana_en.c | 90 ++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 21665f114fe9..a08023c57e25 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1415,8 +1415,8 @@ static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va, return skb; } -static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe, - struct mana_rxq *rxq) +static void mana_rx_skb(void *buf_va, bool from_pool, + struct mana_rxcomp_oob *cqe, struct mana_rxq *rxq) { struct mana_stats_rx *rx_stats = &rxq->stats; struct net_device *ndev = rxq->ndev; @@ -1449,6 +1449,9 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe, if (!skb) goto drop; + if (from_pool) + skb_mark_for_recycle(skb); + skb->dev = napi->dev; skb->protocol = eth_type_trans(skb, ndev); @@ -1499,9 +1502,14 @@ drop_xdp: u64_stats_update_end(&rx_stats->syncp); drop: - WARN_ON_ONCE(rxq->xdp_save_va); - /* Save for reuse */ - rxq->xdp_save_va = buf_va; + if (from_pool) { + page_pool_recycle_direct(rxq->page_pool, + virt_to_head_page(buf_va)); + } else { + WARN_ON_ONCE(rxq->xdp_save_va); + /* Save for reuse */ + rxq->xdp_save_va = buf_va; + } ++ndev->stats.rx_dropped; @@ -1509,11 +1517,13 @@ drop: } static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev, - dma_addr_t *da, bool is_napi) + dma_addr_t *da, bool *from_pool, bool is_napi) { struct page *page; void *va; + *from_pool = false; + /* Reuse XDP dropped page if available */ if (rxq->xdp_save_va) { va = rxq->xdp_save_va; @@ -1534,17 +1544,22 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev, return NULL; } } else { - page = dev_alloc_page(); + page = page_pool_dev_alloc_pages(rxq->page_pool); if (!page) return NULL; + *from_pool = true; va = page_to_virt(page); } *da = dma_map_single(dev, va + rxq->headroom, rxq->datasize, DMA_FROM_DEVICE); if (dma_mapping_error(dev, *da)) { - put_page(virt_to_head_page(va)); + if (*from_pool) + page_pool_put_full_page(rxq->page_pool, page, false); + else + put_page(virt_to_head_page(va)); + return NULL; } @@ -1553,21 +1568,25 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev, /* Allocate frag for rx buffer, and save the old buf */ static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq, - struct mana_recv_buf_oob *rxoob, void **old_buf) + struct mana_recv_buf_oob *rxoob, void **old_buf, + bool *old_fp) { + bool from_pool; dma_addr_t da; void *va; - va = mana_get_rxfrag(rxq, dev, &da, true); + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, true); if (!va) return; dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize, DMA_FROM_DEVICE); *old_buf = rxoob->buf_va; + *old_fp = rxoob->from_pool; rxoob->buf_va = va; rxoob->sgl[0].address = da; + rxoob->from_pool = from_pool; } static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq, @@ -1581,6 +1600,7 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq, struct device *dev = gc->dev; void *old_buf = NULL; u32 curr, pktlen; + bool old_fp; apc = netdev_priv(ndev); @@ -1623,12 +1643,12 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq, rxbuf_oob = &rxq->rx_oobs[curr]; WARN_ON_ONCE(rxbuf_oob->wqe_inf.wqe_size_in_bu != 1); - mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf); + mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp); /* Unsuccessful refill will have old_buf == NULL. * In this case, mana_rx_skb() will drop the packet. */ - mana_rx_skb(old_buf, oob, rxq); + mana_rx_skb(old_buf, old_fp, oob, rxq); drop: mana_move_wq_tail(rxq->gdma_rq, rxbuf_oob->wqe_inf.wqe_size_in_bu); @@ -1888,6 +1908,7 @@ static void mana_destroy_rxq(struct mana_port_context *apc, struct mana_recv_buf_oob *rx_oob; struct device *dev = gc->dev; struct napi_struct *napi; + struct page *page; int i; if (!rxq) @@ -1920,10 +1941,18 @@ static void mana_destroy_rxq(struct mana_port_context *apc, dma_unmap_single(dev, rx_oob->sgl[0].address, rx_oob->sgl[0].size, DMA_FROM_DEVICE); - put_page(virt_to_head_page(rx_oob->buf_va)); + page = virt_to_head_page(rx_oob->buf_va); + + if (rx_oob->from_pool) + page_pool_put_full_page(rxq->page_pool, page, false); + else + put_page(page); + rx_oob->buf_va = NULL; } + page_pool_destroy(rxq->page_pool); + if (rxq->gdma_rq) mana_gd_destroy_queue(gc, rxq->gdma_rq); @@ -1934,18 +1963,20 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key, struct mana_rxq *rxq, struct device *dev) { struct mana_port_context *mpc = netdev_priv(rxq->ndev); + bool from_pool = false; dma_addr_t da; void *va; if (mpc->rxbufs_pre) va = mana_get_rxbuf_pre(rxq, &da); else - va = mana_get_rxfrag(rxq, dev, &da, false); + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, false); if (!va) return -ENOMEM; rx_oob->buf_va = va; + rx_oob->from_pool = from_pool; rx_oob->sgl[0].address = da; rx_oob->sgl[0].size = rxq->datasize; @@ -2015,6 +2046,26 @@ static int mana_push_wqe(struct mana_rxq *rxq) return 0; } +static int mana_create_page_pool(struct mana_rxq *rxq, struct gdma_context *gc) +{ + struct page_pool_params pprm = {}; + int ret; + + pprm.pool_size = RX_BUFFERS_PER_QUEUE; + pprm.nid = gc->numa_node; + pprm.napi = &rxq->rx_cq.napi; + + rxq->page_pool = page_pool_create(&pprm); + + if (IS_ERR(rxq->page_pool)) { + ret = PTR_ERR(rxq->page_pool); + rxq->page_pool = NULL; + return ret; + } + + return 0; +} + static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc, u32 rxq_idx, struct mana_eq *eq, struct net_device *ndev) @@ -2044,6 +2095,13 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc, mana_get_rxbuf_cfg(ndev->mtu, &rxq->datasize, &rxq->alloc_size, &rxq->headroom); + /* Create page pool for RX queue */ + err = mana_create_page_pool(rxq, gc); + if (err) { + netdev_err(ndev, "Create page pool err:%d\n", err); + goto out; + } + err = mana_alloc_rx_wqe(apc, rxq, &rq_size, &cq_size); if (err) goto out; @@ -2115,8 +2173,8 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc, WARN_ON(xdp_rxq_info_reg(&rxq->xdp_rxq, ndev, rxq_idx, cq->napi.napi_id)); - WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, - MEM_TYPE_PAGE_SHARED, NULL)); + WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL, + rxq->page_pool)); napi_enable(&cq->napi); -- cgit From 813f3662c2403f590a3307ea66f4eea699c8d8e4 Mon Sep 17 00:00:00 2001 From: Yu Liao Date: Fri, 4 Aug 2023 17:21:43 +0800 Subject: ibmvnic: remove unused rc variable gcc with W=1 reports drivers/net/ethernet/ibm/ibmvnic.c:194:13: warning: variable 'rc' set but not used [-Wunused-but-set-variable] ^ This variable is not used so remove it. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308040609.zQsSXWXI-lkp@intel.com/ Signed-off-by: Yu Liao Reviewed-by: Nick Child Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 763d613adbcc..01535b03eab6 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -191,9 +191,8 @@ static void ibmvnic_clean_affinity(struct ibmvnic_adapter *adapter) struct ibmvnic_sub_crq_queue **rxqs; struct ibmvnic_sub_crq_queue **txqs; int num_rxqs, num_txqs; - int rc, i; + int i; - rc = 0; rxqs = adapter->rx_scrq; txqs = adapter->tx_scrq; num_txqs = adapter->num_active_tx_scrqs; -- cgit From 54024dbec95585243391caeb9f04a2620e630765 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 4 Aug 2023 17:35:31 +0800 Subject: net: ethernet: adi: adin1110: use eth_broadcast_addr() to assign broadcast address Use eth_broadcast_addr() to assign broadcast address instead of memset(). Signed-off-by: Yang Yingliang Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/adi/adin1110.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c index f5c2d7a9abc1..1c009b485188 100644 --- a/drivers/net/ethernet/adi/adin1110.c +++ b/drivers/net/ethernet/adi/adin1110.c @@ -739,7 +739,7 @@ static int adin1110_broadcasts_filter(struct adin1110_port_priv *port_priv, u32 port_rules = 0; u8 mask[ETH_ALEN]; - memset(mask, 0xFF, ETH_ALEN); + eth_broadcast_addr(mask); if (accept_broadcast && port_priv->state == BR_STATE_FORWARDING) port_rules = adin1110_port_rules(port_priv, true, true); @@ -760,7 +760,7 @@ static int adin1110_set_mac_address(struct net_device *netdev, return -EADDRNOTAVAIL; eth_hw_addr_set(netdev, dev_addr); - memset(mask, 0xFF, ETH_ALEN); + eth_broadcast_addr(mask); mac_slot = (!port_priv->nr) ? ADIN_MAC_P1_ADDR_SLOT : ADIN_MAC_P2_ADDR_SLOT; port_rules = adin1110_port_rules(port_priv, true, false); @@ -1271,7 +1271,7 @@ static int adin1110_port_set_blocking_state(struct adin1110_port_priv *port_priv goto out; /* Allow only BPDUs to be passed to the CPU */ - memset(mask, 0xFF, ETH_ALEN); + eth_broadcast_addr(mask); port_rules = adin1110_port_rules(port_priv, true, false); ret = adin1110_write_mac_address(port_priv, mac_slot, mac, mask, port_rules); @@ -1386,7 +1386,7 @@ static int adin1110_fdb_add(struct adin1110_port_priv *port_priv, other_port = priv->ports[!port_priv->nr]; port_rules = adin1110_port_rules(port_priv, false, true); - memset(mask, 0xFF, ETH_ALEN); + eth_broadcast_addr(mask); return adin1110_write_mac_address(other_port, mac_nr, (u8 *)fdb->addr, mask, port_rules); -- cgit From a6ab5c29b8d2039db885e26058ed8f8853e383ab Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Sat, 5 Aug 2023 18:57:40 +0800 Subject: net: sfp: Remove unused function declaration sfp_link_configure() Commit ce0aa27ff3f6 ("sfp: add sfp-bus to bridge between network devices and sfp cages") declared but never implemented it. Signed-off-by: Yue Haibing Signed-off-by: David S. Miller --- drivers/net/phy/sfp.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h index c7cb50d10099..1fd097dccb9f 100644 --- a/drivers/net/phy/sfp.h +++ b/drivers/net/phy/sfp.h @@ -37,7 +37,6 @@ int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id, void sfp_module_remove(struct sfp_bus *bus); int sfp_module_start(struct sfp_bus *bus); void sfp_module_stop(struct sfp_bus *bus); -int sfp_link_configure(struct sfp_bus *bus, const struct sfp_eeprom_id *id); struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp, const struct sfp_socket_ops *ops); void sfp_unregister_socket(struct sfp_bus *bus); -- cgit From 18cf3d31f8292e3994ec972097419f1c23e0d2ff Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Fri, 9 Jun 2023 15:44:18 +0300 Subject: net/mlx5: Track the current number of completion EQs In preparation to allocate completion EQs, add a counter to track the number of completion EQs currently allocated. Store the maximum number of EQs in max_comp_eqs variable. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 3db4866d7880..66257f7879b7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -58,7 +58,8 @@ struct mlx5_eq_table { struct mlx5_nb cq_err_nb; struct mutex lock; /* sync async eqs creations */ - int num_comp_eqs; + int curr_comp_eqs; + int max_comp_eqs; struct mlx5_irq_table *irq_table; struct mlx5_irq **comp_irqs; struct mlx5_irq *ctrl_irq; @@ -452,6 +453,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) ATOMIC_INIT_NOTIFIER_HEAD(&eq_table->nh[i]); eq_table->irq_table = mlx5_irq_table_get(dev); + eq_table->curr_comp_eqs = 0; return 0; } @@ -807,7 +809,7 @@ static void comp_irqs_release_pci(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - mlx5_irqs_release_vectors(table->comp_irqs, table->num_comp_eqs); + mlx5_irqs_release_vectors(table->comp_irqs, table->max_comp_eqs); } static int comp_irqs_request_pci(struct mlx5_core_dev *dev) @@ -821,7 +823,7 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev) int cpu; int i; - ncomp_eqs = table->num_comp_eqs; + ncomp_eqs = table->max_comp_eqs; cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL); if (!cpus) return -ENOMEM; @@ -847,13 +849,13 @@ static void comp_irqs_release_sf(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - mlx5_irq_affinity_irqs_release(dev, table->comp_irqs, table->num_comp_eqs); + mlx5_irq_affinity_irqs_release(dev, table->comp_irqs, table->max_comp_eqs); } static int comp_irqs_request_sf(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - int ncomp_eqs = table->num_comp_eqs; + int ncomp_eqs = table->max_comp_eqs; return mlx5_irq_affinity_irqs_request_auto(dev, ncomp_eqs, table->comp_irqs); } @@ -874,7 +876,7 @@ static int comp_irqs_request(struct mlx5_core_dev *dev) int ncomp_eqs; int ret; - ncomp_eqs = table->num_comp_eqs; + ncomp_eqs = table->max_comp_eqs; table->comp_irqs = kcalloc(ncomp_eqs, sizeof(*table->comp_irqs), GFP_KERNEL); if (!table->comp_irqs) return -ENOMEM; @@ -901,7 +903,7 @@ static int alloc_rmap(struct mlx5_core_dev *mdev) if (mlx5_core_is_sf(mdev)) return 0; - eq_table->rmap = alloc_irq_cpu_rmap(eq_table->num_comp_eqs); + eq_table->rmap = alloc_irq_cpu_rmap(eq_table->max_comp_eqs); if (!eq_table->rmap) return -ENOMEM; return 0; @@ -934,6 +936,7 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev) eq->core.eqn); tasklet_disable(&eq->tasklet_ctx.task); kfree(eq); + table->curr_comp_eqs--; } comp_irqs_release(dev); free_rmap(dev); @@ -973,6 +976,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) goto err_irqs_req; } + table->max_comp_eqs = ncomp_eqs; INIT_LIST_HEAD(&table->comp_eqs_list); nent = comp_eq_depth_devlink_param_get(dev); @@ -1008,9 +1012,9 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->core.eqn); /* add tail, to keep the list ordered, for mlx5_vector2eqn to work */ list_add_tail(&eq->list, &table->comp_eqs_list); + table->curr_comp_eqs++; } - table->num_comp_eqs = ncomp_eqs; return 0; clean_eq: @@ -1057,7 +1061,7 @@ int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn) unsigned int mlx5_comp_vectors_count(struct mlx5_core_dev *dev) { - return dev->priv.eq_table->num_comp_eqs; + return dev->priv.eq_table->max_comp_eqs; } EXPORT_SYMBOL(mlx5_comp_vectors_count); @@ -1148,7 +1152,7 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) struct mlx5_eq_table *eq_table = dev->priv.eq_table; int err; - eq_table->num_comp_eqs = get_num_eqs(dev); + eq_table->max_comp_eqs = get_num_eqs(dev); err = create_async_eqs(dev); if (err) { mlx5_core_err(dev, "Failed to create async EQs\n"); -- cgit From a1772de78d7303e33517d1741e0fce1c7247bec4 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Sun, 11 Jun 2023 14:35:36 +0300 Subject: net/mlx5: Refactor completion IRQ request/release API Introduce a per-vector completion IRQ request API that requests a single IRQ for a given vector index instead of multiple IRQs request API. On driver load, loop over all completion vectors and request an IRQ for each one via the newly introduced API. Symmetrically, introduce an IRQ release API per vector. On driver unload, loop over all vectors and release each completion IRQ via the new per-vector API. As IRQ vectors will be requested dynamically later in the patchset, add a cpumask of the bounded CPUs to avoid the possible mapping of two IRQs of the same device to the same cpu. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 36 ++++++++-- .../net/ethernet/mellanox/mlx5/core/irq_affinity.c | 82 ++++++++++------------ drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h | 26 +++---- drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 60 ++++++---------- 4 files changed, 101 insertions(+), 103 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 66257f7879b7..268fd61ae8c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -64,6 +64,7 @@ struct mlx5_eq_table { struct mlx5_irq **comp_irqs; struct mlx5_irq *ctrl_irq; struct cpu_rmap *rmap; + struct cpumask used_cpus; }; #define MLX5_ASYNC_EVENT_MASK ((1ull << MLX5_EVENT_TYPE_PATH_MIG) | \ @@ -453,6 +454,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) ATOMIC_INIT_NOTIFIER_HEAD(&eq_table->nh[i]); eq_table->irq_table = mlx5_irq_table_get(dev); + cpumask_clear(&eq_table->used_cpus); eq_table->curr_comp_eqs = 0; return 0; } @@ -808,8 +810,10 @@ EXPORT_SYMBOL(mlx5_eq_update_ci); static void comp_irqs_release_pci(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; + int i; - mlx5_irqs_release_vectors(table->comp_irqs, table->max_comp_eqs); + for (i = 0; i < table->max_comp_eqs; i++) + mlx5_irq_release_vector(table->comp_irqs[i]); } static int comp_irqs_request_pci(struct mlx5_core_dev *dev) @@ -817,9 +821,9 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev) struct mlx5_eq_table *table = dev->priv.eq_table; const struct cpumask *prev = cpu_none_mask; const struct cpumask *mask; + struct mlx5_irq *irq; int ncomp_eqs; u16 *cpus; - int ret; int cpu; int i; @@ -840,24 +844,42 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev) } spread_done: rcu_read_unlock(); - ret = mlx5_irqs_request_vectors(dev, cpus, ncomp_eqs, table->comp_irqs, &table->rmap); + for (i = 0; i < ncomp_eqs; i++) { + irq = mlx5_irq_request_vector(dev, cpus[i], i, &table->rmap); + if (IS_ERR(irq)) + break; + + table->comp_irqs[i] = irq; + } + kfree(cpus); - return ret; + return i ? i : PTR_ERR(irq); } static void comp_irqs_release_sf(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; + int i; - mlx5_irq_affinity_irqs_release(dev, table->comp_irqs, table->max_comp_eqs); + for (i = 0; i < table->max_comp_eqs; i++) + mlx5_irq_affinity_irq_release(dev, table->comp_irqs[i]); } static int comp_irqs_request_sf(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - int ncomp_eqs = table->max_comp_eqs; + struct mlx5_irq *irq; + int i; + + for (i = 0; i < table->max_comp_eqs; i++) { + irq = mlx5_irq_affinity_irq_request_auto(dev, &table->used_cpus, i); + if (IS_ERR(irq)) + break; + + table->comp_irqs[i] = irq; + } - return mlx5_irq_affinity_irqs_request_auto(dev, ncomp_eqs, table->comp_irqs); + return i ? i : PTR_ERR(irq); } static void comp_irqs_release(struct mlx5_core_dev *dev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c index fa467335526e..ed51800f9f67 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c @@ -156,67 +156,61 @@ unlock: return least_loaded_irq; } -void mlx5_irq_affinity_irqs_release(struct mlx5_core_dev *dev, struct mlx5_irq **irqs, - int num_irqs) +void mlx5_irq_affinity_irq_release(struct mlx5_core_dev *dev, struct mlx5_irq *irq) { struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev); - int i; - - for (i = 0; i < num_irqs; i++) { - int cpu = cpumask_first(mlx5_irq_get_affinity_mask(irqs[i])); + int cpu; - synchronize_irq(pci_irq_vector(pool->dev->pdev, - mlx5_irq_get_index(irqs[i]))); - if (mlx5_irq_put(irqs[i])) - if (pool->irqs_per_cpu) - cpu_put(pool, cpu); - } + cpu = cpumask_first(mlx5_irq_get_affinity_mask(irq)); + synchronize_irq(pci_irq_vector(pool->dev->pdev, + mlx5_irq_get_index(irq))); + if (mlx5_irq_put(irq)) + if (pool->irqs_per_cpu) + cpu_put(pool, cpu); } /** - * mlx5_irq_affinity_irqs_request_auto - request one or more IRQs for mlx5 device. - * @dev: mlx5 device that is requesting the IRQs. - * @nirqs: number of IRQs to request. - * @irqs: an output array of IRQs pointers. + * mlx5_irq_affinity_irq_request_auto - request one IRQ for mlx5 device. + * @dev: mlx5 device that is requesting the IRQ. + * @used_cpus: cpumask of bounded cpus by the device + * @vecidx: vector index to request an IRQ for. * * Each IRQ is bounded to at most 1 CPU. - * This function is requesting IRQs according to the default assignment. + * This function is requesting an IRQ according to the default assignment. * The default assignment policy is: - * - in each iteration, request the least loaded IRQ which is not bound to any + * - request the least loaded IRQ which is not bound to any * CPU of the previous IRQs requested. * - * This function returns the number of IRQs requested, (which might be smaller than - * @nirqs), if successful, or a negative error code in case of an error. + * On success, this function updates used_cpus mask and returns an irq pointer. + * In case of an error, an appropriate error pointer is returned. */ -int mlx5_irq_affinity_irqs_request_auto(struct mlx5_core_dev *dev, int nirqs, - struct mlx5_irq **irqs) +struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev, + struct cpumask *used_cpus, u16 vecidx) { struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev); struct irq_affinity_desc af_desc = {}; struct mlx5_irq *irq; - int i = 0; af_desc.is_managed = 1; cpumask_copy(&af_desc.mask, cpu_online_mask); - for (i = 0; i < nirqs; i++) { - if (mlx5_irq_pool_is_sf_pool(pool)) - irq = mlx5_irq_affinity_request(pool, &af_desc); - else - /* In case SF pool doesn't exists, fallback to the PF IRQs. - * The PF IRQs are already allocated and binded to CPU - * at this point. Hence, only an index is needed. - */ - irq = mlx5_irq_request(dev, i, NULL, NULL); - if (IS_ERR(irq)) - break; - irqs[i] = irq; - cpumask_clear_cpu(cpumask_first(mlx5_irq_get_affinity_mask(irq)), &af_desc.mask); - mlx5_core_dbg(pool->dev, "IRQ %u mapped to cpu %*pbl, %u EQs on this irq\n", - pci_irq_vector(dev->pdev, mlx5_irq_get_index(irq)), - cpumask_pr_args(mlx5_irq_get_affinity_mask(irq)), - mlx5_irq_read_locked(irq) / MLX5_EQ_REFS_PER_IRQ); - } - if (!i) - return PTR_ERR(irq); - return i; + cpumask_andnot(&af_desc.mask, &af_desc.mask, used_cpus); + if (mlx5_irq_pool_is_sf_pool(pool)) + irq = mlx5_irq_affinity_request(pool, &af_desc); + else + /* In case SF pool doesn't exists, fallback to the PF IRQs. + * The PF IRQs are already allocated and binded to CPU + * at this point. Hence, only an index is needed. + */ + irq = mlx5_irq_request(dev, vecidx, NULL, NULL); + + if (IS_ERR(irq)) + return irq; + + cpumask_or(used_cpus, used_cpus, mlx5_irq_get_affinity_mask(irq)); + mlx5_core_dbg(pool->dev, "IRQ %u mapped to cpu %*pbl, %u EQs on this irq\n", + pci_irq_vector(dev->pdev, mlx5_irq_get_index(irq)), + cpumask_pr_args(mlx5_irq_get_affinity_mask(irq)), + mlx5_irq_read_locked(irq) / MLX5_EQ_REFS_PER_IRQ); + + return irq; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h index aa403a5ea34e..1088114e905d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h @@ -29,9 +29,9 @@ void mlx5_ctrl_irq_release(struct mlx5_irq *ctrl_irq); struct mlx5_irq *mlx5_irq_request(struct mlx5_core_dev *dev, u16 vecidx, struct irq_affinity_desc *af_desc, struct cpu_rmap **rmap); -int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs, - struct mlx5_irq **irqs, struct cpu_rmap **rmap); -void mlx5_irqs_release_vectors(struct mlx5_irq **irqs, int nirqs); +struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu, + u16 vecidx, struct cpu_rmap **rmap); +void mlx5_irq_release_vector(struct mlx5_irq *irq); int mlx5_irq_attach_nb(struct mlx5_irq *irq, struct notifier_block *nb); int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb); struct cpumask *mlx5_irq_get_affinity_mask(struct mlx5_irq *irq); @@ -39,17 +39,17 @@ int mlx5_irq_get_index(struct mlx5_irq *irq); struct mlx5_irq_pool; #ifdef CONFIG_MLX5_SF -int mlx5_irq_affinity_irqs_request_auto(struct mlx5_core_dev *dev, int nirqs, - struct mlx5_irq **irqs); +struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev, + struct cpumask *used_cpus, u16 vecidx); struct mlx5_irq *mlx5_irq_affinity_request(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_desc); -void mlx5_irq_affinity_irqs_release(struct mlx5_core_dev *dev, struct mlx5_irq **irqs, - int num_irqs); +void mlx5_irq_affinity_irq_release(struct mlx5_core_dev *dev, struct mlx5_irq *irq); #else -static inline int mlx5_irq_affinity_irqs_request_auto(struct mlx5_core_dev *dev, int nirqs, - struct mlx5_irq **irqs) +static inline +struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev, + struct cpumask *used_cpus, u16 vecidx) { - return -EOPNOTSUPP; + return ERR_PTR(-EOPNOTSUPP); } static inline struct mlx5_irq * @@ -58,7 +58,9 @@ mlx5_irq_affinity_request(struct mlx5_irq_pool *pool, struct irq_affinity_desc * return ERR_PTR(-EOPNOTSUPP); } -static inline void mlx5_irq_affinity_irqs_release(struct mlx5_core_dev *dev, - struct mlx5_irq **irqs, int num_irqs) {} +static inline +void mlx5_irq_affinity_irq_release(struct mlx5_core_dev *dev, struct mlx5_irq *irq) +{ +} #endif #endif /* __MLX5_IRQ_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index cba2a4afb5fd..33a133c9918c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -432,19 +432,10 @@ static struct mlx5_irq_pool *ctrl_irq_pool_get(struct mlx5_core_dev *dev) return pool ? pool : irq_table->pcif_pool; } -/** - * mlx5_irqs_release - release one or more IRQs back to the system. - * @irqs: IRQs to be released. - * @nirqs: number of IRQs to be released. - */ -static void mlx5_irqs_release(struct mlx5_irq **irqs, int nirqs) +static void _mlx5_irq_release(struct mlx5_irq *irq) { - int i; - - for (i = 0; i < nirqs; i++) { - synchronize_irq(irqs[i]->map.virq); - mlx5_irq_put(irqs[i]); - } + synchronize_irq(irq->map.virq); + mlx5_irq_put(irq); } /** @@ -453,7 +444,7 @@ static void mlx5_irqs_release(struct mlx5_irq **irqs, int nirqs) */ void mlx5_ctrl_irq_release(struct mlx5_irq *ctrl_irq) { - mlx5_irqs_release(&ctrl_irq, 1); + _mlx5_irq_release(ctrl_irq); } /** @@ -569,53 +560,42 @@ void mlx5_msix_free(struct mlx5_core_dev *dev, struct msi_map map) EXPORT_SYMBOL(mlx5_msix_free); /** - * mlx5_irqs_release_vectors - release one or more IRQs back to the system. - * @irqs: IRQs to be released. - * @nirqs: number of IRQs to be released. + * mlx5_irq_release_vector - release one IRQ back to the system. + * @irq: the irq to release. */ -void mlx5_irqs_release_vectors(struct mlx5_irq **irqs, int nirqs) +void mlx5_irq_release_vector(struct mlx5_irq *irq) { - mlx5_irqs_release(irqs, nirqs); + _mlx5_irq_release(irq); } /** - * mlx5_irqs_request_vectors - request one or more IRQs for mlx5 device. - * @dev: mlx5 device that is requesting the IRQs. - * @cpus: CPUs array for binding the IRQs - * @nirqs: number of IRQs to request. - * @irqs: an output array of IRQs pointers. + * mlx5_irq_request_vector - request one IRQ for mlx5 device. + * @dev: mlx5 device that is requesting the IRQ. + * @cpu: CPU to bind the IRQ to. + * @vecidx: vector index to request an IRQ for. * @rmap: pointer to reverse map pointer for completion interrupts * * Each IRQ is bound to at most 1 CPU. - * This function is requests nirqs IRQs, starting from @vecidx. + * This function is requests one IRQ, for the given @vecidx. * - * This function returns the number of IRQs requested, (which might be smaller than - * @nirqs), if successful, or a negative error code in case of an error. + * This function returns a pointer to the irq on success, or an error pointer + * in case of an error. */ -int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs, - struct mlx5_irq **irqs, struct cpu_rmap **rmap) +struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu, + u16 vecidx, struct cpu_rmap **rmap) { struct mlx5_irq_table *table = mlx5_irq_table_get(dev); struct mlx5_irq_pool *pool = table->pcif_pool; struct irq_affinity_desc af_desc; - struct mlx5_irq *irq; int offset = 1; - int i; if (!pool->xa_num_irqs.max) offset = 0; af_desc.is_managed = false; - for (i = 0; i < nirqs; i++) { - cpumask_clear(&af_desc.mask); - cpumask_set_cpu(cpus[i], &af_desc.mask); - irq = mlx5_irq_request(dev, i + offset, &af_desc, rmap); - if (IS_ERR(irq)) - break; - irqs[i] = irq; - } - - return i ? i : PTR_ERR(irq); + cpumask_clear(&af_desc.mask); + cpumask_set_cpu(cpu, &af_desc.mask); + return mlx5_irq_request(dev, vecidx + offset, &af_desc, rmap); } static struct mlx5_irq_pool * -- cgit From c8a0245c3937d302a52c9d6b54de44b302e78265 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Sun, 18 Jun 2023 19:23:24 +0300 Subject: net/mlx5: Use xarray to store and manage completion IRQs Use xarray to store the completion IRQs instead of a fixed-size allocated array as not all completion IRQs will be requested on driver load, but rather on demand when an EQ is created. The xarray offers more scalability, reduced memory overhead, and provides the ability to dynamically resize the array when needed. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 61 +++++++++++++--------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 268fd61ae8c0..ac22d4d6b94b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -61,7 +61,7 @@ struct mlx5_eq_table { int curr_comp_eqs; int max_comp_eqs; struct mlx5_irq_table *irq_table; - struct mlx5_irq **comp_irqs; + struct xarray comp_irqs; struct mlx5_irq *ctrl_irq; struct cpu_rmap *rmap; struct cpumask used_cpus; @@ -455,14 +455,18 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) eq_table->irq_table = mlx5_irq_table_get(dev); cpumask_clear(&eq_table->used_cpus); + xa_init(&eq_table->comp_irqs); eq_table->curr_comp_eqs = 0; return 0; } void mlx5_eq_table_cleanup(struct mlx5_core_dev *dev) { + struct mlx5_eq_table *table = dev->priv.eq_table; + mlx5_eq_debugfs_cleanup(dev); - kvfree(dev->priv.eq_table); + xa_destroy(&table->comp_irqs); + kvfree(table); } /* Async EQs */ @@ -810,10 +814,13 @@ EXPORT_SYMBOL(mlx5_eq_update_ci); static void comp_irqs_release_pci(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - int i; + struct mlx5_irq *irq; + unsigned long index; - for (i = 0; i < table->max_comp_eqs; i++) - mlx5_irq_release_vector(table->comp_irqs[i]); + xa_for_each(&table->comp_irqs, index, irq) { + xa_erase(&table->comp_irqs, index); + mlx5_irq_release_vector(irq); + } } static int comp_irqs_request_pci(struct mlx5_core_dev *dev) @@ -849,7 +856,8 @@ spread_done: if (IS_ERR(irq)) break; - table->comp_irqs[i] = irq; + if (xa_err(xa_store(&table->comp_irqs, i, irq, GFP_KERNEL))) + break; } kfree(cpus); @@ -859,10 +867,13 @@ spread_done: static void comp_irqs_release_sf(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - int i; + struct mlx5_irq *irq; + unsigned long index; - for (i = 0; i < table->max_comp_eqs; i++) - mlx5_irq_affinity_irq_release(dev, table->comp_irqs[i]); + xa_for_each(&table->comp_irqs, index, irq) { + xa_erase(&table->comp_irqs, index); + mlx5_irq_affinity_irq_release(dev, irq); + } } static int comp_irqs_request_sf(struct mlx5_core_dev *dev) @@ -876,7 +887,8 @@ static int comp_irqs_request_sf(struct mlx5_core_dev *dev) if (IS_ERR(irq)) break; - table->comp_irqs[i] = irq; + if (xa_err(xa_store(&table->comp_irqs, i, irq, GFP_KERNEL))) + break; } return i ? i : PTR_ERR(irq); @@ -884,31 +896,14 @@ static int comp_irqs_request_sf(struct mlx5_core_dev *dev) static void comp_irqs_release(struct mlx5_core_dev *dev) { - struct mlx5_eq_table *table = dev->priv.eq_table; - mlx5_core_is_sf(dev) ? comp_irqs_release_sf(dev) : comp_irqs_release_pci(dev); - - kfree(table->comp_irqs); } static int comp_irqs_request(struct mlx5_core_dev *dev) { - struct mlx5_eq_table *table = dev->priv.eq_table; - int ncomp_eqs; - int ret; - - ncomp_eqs = table->max_comp_eqs; - table->comp_irqs = kcalloc(ncomp_eqs, sizeof(*table->comp_irqs), GFP_KERNEL); - if (!table->comp_irqs) - return -ENOMEM; - - ret = mlx5_core_is_sf(dev) ? comp_irqs_request_sf(dev) : - comp_irqs_request_pci(dev); - if (ret < 0) - kfree(table->comp_irqs); - - return ret; + return mlx5_core_is_sf(dev) ? comp_irqs_request_sf(dev) : + comp_irqs_request_pci(dev); } #ifdef CONFIG_RFS_ACCEL @@ -983,10 +978,11 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq; + struct mlx5_irq *irq; + unsigned long index; int ncomp_eqs; int nent; int err; - int i; err = alloc_rmap(dev); if (err) @@ -1002,7 +998,8 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) INIT_LIST_HEAD(&table->comp_eqs_list); nent = comp_eq_depth_devlink_param_get(dev); - for (i = 0; i < ncomp_eqs; i++) { + xa_for_each(&table->comp_irqs, index, irq) + { struct mlx5_eq_param param = {}; eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, dev->priv.numa_node); @@ -1018,7 +1015,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) eq->irq_nb.notifier_call = mlx5_eq_comp_int; param = (struct mlx5_eq_param) { - .irq = table->comp_irqs[i], + .irq = irq, .nent = nent, }; -- cgit From 54b2cf41b853e04ea09a2a075e4a6dc30638c298 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 12 Jun 2023 15:34:27 +0300 Subject: net/mlx5: Refactor completion IRQ request/release handlers in EQ layer Break the completion IRQ request/release functions into per-vector handlers for both PCI devices and SFs in the EQ layer. On EQ table creation, loop over all vectors and request an IRQ for each one using the new per-vector functions. Perform the symmetrical change when releasing IRQs on EQ table cleanup. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 109 +++++++++++++-------------- 1 file changed, 51 insertions(+), 58 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ac22d4d6b94b..c01a5d8dbe9b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -811,99 +811,84 @@ void mlx5_eq_update_ci(struct mlx5_eq *eq, u32 cc, bool arm) } EXPORT_SYMBOL(mlx5_eq_update_ci); -static void comp_irqs_release_pci(struct mlx5_core_dev *dev) +static void comp_irq_release_pci(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_irq *irq; - unsigned long index; - xa_for_each(&table->comp_irqs, index, irq) { - xa_erase(&table->comp_irqs, index); - mlx5_irq_release_vector(irq); - } + irq = xa_load(&table->comp_irqs, vecidx); + if (!irq) + return; + + xa_erase(&table->comp_irqs, vecidx); + mlx5_irq_release_vector(irq); } -static int comp_irqs_request_pci(struct mlx5_core_dev *dev) +static int comp_irq_request_pci(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; const struct cpumask *prev = cpu_none_mask; const struct cpumask *mask; struct mlx5_irq *irq; - int ncomp_eqs; - u16 *cpus; + int found_cpu = 0; + int i = 0; int cpu; - int i; - - ncomp_eqs = table->max_comp_eqs; - cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL); - if (!cpus) - return -ENOMEM; - i = 0; rcu_read_lock(); for_each_numa_hop_mask(mask, dev->priv.numa_node) { for_each_cpu_andnot(cpu, mask, prev) { - cpus[i] = cpu; - if (++i == ncomp_eqs) + if (i++ == vecidx) { + found_cpu = cpu; goto spread_done; + } } prev = mask; } + spread_done: rcu_read_unlock(); - for (i = 0; i < ncomp_eqs; i++) { - irq = mlx5_irq_request_vector(dev, cpus[i], i, &table->rmap); - if (IS_ERR(irq)) - break; - - if (xa_err(xa_store(&table->comp_irqs, i, irq, GFP_KERNEL))) - break; - } + irq = mlx5_irq_request_vector(dev, found_cpu, vecidx, &table->rmap); + if (IS_ERR(irq)) + return PTR_ERR(irq); - kfree(cpus); - return i ? i : PTR_ERR(irq); + return xa_err(xa_store(&table->comp_irqs, vecidx, irq, GFP_KERNEL)); } -static void comp_irqs_release_sf(struct mlx5_core_dev *dev) +static void comp_irq_release_sf(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_irq *irq; - unsigned long index; - xa_for_each(&table->comp_irqs, index, irq) { - xa_erase(&table->comp_irqs, index); - mlx5_irq_affinity_irq_release(dev, irq); - } + irq = xa_load(&table->comp_irqs, vecidx); + if (!irq) + return; + + xa_erase(&table->comp_irqs, vecidx); + mlx5_irq_affinity_irq_release(dev, irq); } -static int comp_irqs_request_sf(struct mlx5_core_dev *dev) +static int comp_irq_request_sf(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_irq *irq; - int i; - - for (i = 0; i < table->max_comp_eqs; i++) { - irq = mlx5_irq_affinity_irq_request_auto(dev, &table->used_cpus, i); - if (IS_ERR(irq)) - break; - if (xa_err(xa_store(&table->comp_irqs, i, irq, GFP_KERNEL))) - break; - } + irq = mlx5_irq_affinity_irq_request_auto(dev, &table->used_cpus, vecidx); + if (IS_ERR(irq)) + return PTR_ERR(irq); - return i ? i : PTR_ERR(irq); + return xa_err(xa_store(&table->comp_irqs, vecidx, irq, GFP_KERNEL)); } -static void comp_irqs_release(struct mlx5_core_dev *dev) +static void comp_irq_release(struct mlx5_core_dev *dev, u16 vecidx) { - mlx5_core_is_sf(dev) ? comp_irqs_release_sf(dev) : - comp_irqs_release_pci(dev); + mlx5_core_is_sf(dev) ? comp_irq_release_sf(dev, vecidx) : + comp_irq_release_pci(dev, vecidx); } -static int comp_irqs_request(struct mlx5_core_dev *dev) +static int comp_irq_request(struct mlx5_core_dev *dev, u16 vecidx) { - return mlx5_core_is_sf(dev) ? comp_irqs_request_sf(dev) : - comp_irqs_request_pci(dev); + return mlx5_core_is_sf(dev) ? comp_irq_request_sf(dev, vecidx) : + comp_irq_request_pci(dev, vecidx); } #ifdef CONFIG_RFS_ACCEL @@ -944,6 +929,8 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq, *n; + struct mlx5_irq *irq; + unsigned long index; list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) { list_del(&eq->list); @@ -955,7 +942,10 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev) kfree(eq); table->curr_comp_eqs--; } - comp_irqs_release(dev); + + xa_for_each(&table->comp_irqs, index, irq) + comp_irq_release(dev, index); + free_rmap(dev); } @@ -980,7 +970,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) struct mlx5_eq_comp *eq; struct mlx5_irq *irq; unsigned long index; - int ncomp_eqs; + int vecidx; int nent; int err; @@ -988,13 +978,16 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) if (err) return err; - ncomp_eqs = comp_irqs_request(dev); - if (ncomp_eqs < 0) { - err = ncomp_eqs; - goto err_irqs_req; + for (vecidx = 0; vecidx < table->max_comp_eqs; vecidx++) { + err = comp_irq_request(dev, vecidx); + if (err < 0) + break; } - table->max_comp_eqs = ncomp_eqs; + if (!vecidx) + goto err_irqs_req; + + table->max_comp_eqs = vecidx; INIT_LIST_HEAD(&table->comp_eqs_list); nent = comp_eq_depth_devlink_param_get(dev); -- cgit From 273c697fdedc65f8b423a652fb248860a3dbf36d Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 19 Jun 2023 15:01:43 +0300 Subject: net/mlx5: Use xarray to store and manage completion EQs Use xarray to store the completion EQs instead of a linked list. The xarray offers more scalability, reduced memory overhead, and facilitates the lookup of a certain EQ given a vector index. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 50 +++++++++++++--------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index c01a5d8dbe9b..b343c0fd621e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -47,7 +47,7 @@ enum { static_assert(MLX5_EQ_POLLING_BUDGET <= MLX5_NUM_SPARE_EQE); struct mlx5_eq_table { - struct list_head comp_eqs_list; + struct xarray comp_eqs; struct mlx5_eq_async pages_eq; struct mlx5_eq_async cmd_eq; struct mlx5_eq_async async_eq; @@ -455,6 +455,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) eq_table->irq_table = mlx5_irq_table_get(dev); cpumask_clear(&eq_table->used_cpus); + xa_init(&eq_table->comp_eqs); xa_init(&eq_table->comp_irqs); eq_table->curr_comp_eqs = 0; return 0; @@ -466,6 +467,7 @@ void mlx5_eq_table_cleanup(struct mlx5_core_dev *dev) mlx5_eq_debugfs_cleanup(dev); xa_destroy(&table->comp_irqs); + xa_destroy(&table->comp_eqs); kvfree(table); } @@ -928,12 +930,12 @@ static void free_rmap(struct mlx5_core_dev *mdev) {} static void destroy_comp_eqs(struct mlx5_core_dev *dev) { struct mlx5_eq_table *table = dev->priv.eq_table; - struct mlx5_eq_comp *eq, *n; + struct mlx5_eq_comp *eq; struct mlx5_irq *irq; unsigned long index; - list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) { - list_del(&eq->list); + xa_for_each(&table->comp_eqs, index, eq) { + xa_erase(&table->comp_eqs, index); mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); if (destroy_unmap_eq(dev, &eq->core)) mlx5_core_warn(dev, "failed to destroy comp EQ 0x%x\n", @@ -988,7 +990,6 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) goto err_irqs_req; table->max_comp_eqs = vecidx; - INIT_LIST_HEAD(&table->comp_eqs_list); nent = comp_eq_depth_devlink_param_get(dev); xa_for_each(&table->comp_irqs, index, irq) @@ -1022,13 +1023,16 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) } mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->core.eqn); - /* add tail, to keep the list ordered, for mlx5_vector2eqn to work */ - list_add_tail(&eq->list, &table->comp_eqs_list); + err = xa_err(xa_store(&table->comp_eqs, index, eq, GFP_KERNEL)); + if (err) + goto disable_eq; table->curr_comp_eqs++; } return 0; +disable_eq: + mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); clean_eq: kfree(eq); clean: @@ -1043,21 +1047,16 @@ static int vector2eqnirqn(struct mlx5_core_dev *dev, int vector, int *eqn, { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq; - int err = -ENOENT; - int i = 0; - list_for_each_entry(eq, &table->comp_eqs_list, list) { - if (i++ == vector) { - if (irqn) - *irqn = eq->core.irqn; - if (eqn) - *eqn = eq->core.eqn; - err = 0; - break; - } - } + eq = xa_load(&table->comp_eqs, vector); + if (!eq) + return -ENOENT; - return err; + if (irqn) + *irqn = eq->core.irqn; + if (eqn) + *eqn = eq->core.eqn; + return 0; } int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn) @@ -1082,12 +1081,10 @@ mlx5_comp_irq_get_affinity_mask(struct mlx5_core_dev *dev, int vector) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq; - int i = 0; - list_for_each_entry(eq, &table->comp_eqs_list, list) { - if (i++ == vector) - return mlx5_irq_get_affinity_mask(eq->core.irq); - } + eq = xa_load(&table->comp_eqs, vector); + if (eq) + return mlx5_irq_get_affinity_mask(eq->core.irq); WARN_ON_ONCE(1); return NULL; @@ -1105,8 +1102,9 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq; + unsigned long index; - list_for_each_entry(eq, &table->comp_eqs_list, list) { + xa_for_each(&table->comp_eqs, index, eq) { if (eq->core.eqn == eqn) return eq; } -- cgit From e3e56775e91398df95c610bfc9bf4025db7dcf66 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Sun, 11 Jun 2023 19:55:02 +0300 Subject: net/mlx5: Implement single completion EQ create/destroy methods Currently, create_comp_eqs() function handles the creation of all completion EQs for all the vectors on driver load. While on driver unload, destroy_comp_eqs() performs the equivalent job. In preparation for dynamic EQ creation, replace create_comp_eqs() / destroy_comp_eqs() with create_comp_eq() / destroy_comp_eq() functions which will receive a vector index and allocate/destroy an EQ for that specific vector. Thus, allowing more flexibility in the management of completion EQs. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 137 +++++++++++++-------------- 1 file changed, 66 insertions(+), 71 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index b343c0fd621e..41fa15757101 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -927,28 +927,19 @@ static int alloc_rmap(struct mlx5_core_dev *mdev) { return 0; } static void free_rmap(struct mlx5_core_dev *mdev) {} #endif -static void destroy_comp_eqs(struct mlx5_core_dev *dev) +static void destroy_comp_eq(struct mlx5_core_dev *dev, struct mlx5_eq_comp *eq, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; - struct mlx5_eq_comp *eq; - struct mlx5_irq *irq; - unsigned long index; - - xa_for_each(&table->comp_eqs, index, eq) { - xa_erase(&table->comp_eqs, index); - mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); - if (destroy_unmap_eq(dev, &eq->core)) - mlx5_core_warn(dev, "failed to destroy comp EQ 0x%x\n", - eq->core.eqn); - tasklet_disable(&eq->tasklet_ctx.task); - kfree(eq); - table->curr_comp_eqs--; - } - xa_for_each(&table->comp_irqs, index, irq) - comp_irq_release(dev, index); - - free_rmap(dev); + xa_erase(&table->comp_eqs, vecidx); + mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); + if (destroy_unmap_eq(dev, &eq->core)) + mlx5_core_warn(dev, "failed to destroy comp EQ 0x%x\n", + eq->core.eqn); + tasklet_disable(&eq->tasklet_ctx.task); + kfree(eq); + comp_irq_release(dev, vecidx); + table->curr_comp_eqs--; } static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev) @@ -966,79 +957,62 @@ static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev) return MLX5_COMP_EQ_SIZE; } -static int create_comp_eqs(struct mlx5_core_dev *dev) +static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; + struct mlx5_eq_param param = {}; struct mlx5_eq_comp *eq; struct mlx5_irq *irq; - unsigned long index; - int vecidx; int nent; int err; - err = alloc_rmap(dev); + err = comp_irq_request(dev, vecidx); if (err) return err; - for (vecidx = 0; vecidx < table->max_comp_eqs; vecidx++) { - err = comp_irq_request(dev, vecidx); - if (err < 0) - break; - } - - if (!vecidx) - goto err_irqs_req; - - table->max_comp_eqs = vecidx; nent = comp_eq_depth_devlink_param_get(dev); - xa_for_each(&table->comp_irqs, index, irq) - { - struct mlx5_eq_param param = {}; + eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, dev->priv.numa_node); + if (!eq) { + err = -ENOMEM; + goto clean_irq; + } - eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, dev->priv.numa_node); - if (!eq) { - err = -ENOMEM; - goto clean; - } + INIT_LIST_HEAD(&eq->tasklet_ctx.list); + INIT_LIST_HEAD(&eq->tasklet_ctx.process_list); + spin_lock_init(&eq->tasklet_ctx.lock); + tasklet_setup(&eq->tasklet_ctx.task, mlx5_cq_tasklet_cb); - INIT_LIST_HEAD(&eq->tasklet_ctx.list); - INIT_LIST_HEAD(&eq->tasklet_ctx.process_list); - spin_lock_init(&eq->tasklet_ctx.lock); - tasklet_setup(&eq->tasklet_ctx.task, mlx5_cq_tasklet_cb); - - eq->irq_nb.notifier_call = mlx5_eq_comp_int; - param = (struct mlx5_eq_param) { - .irq = irq, - .nent = nent, - }; - - err = create_map_eq(dev, &eq->core, ¶m); - if (err) - goto clean_eq; - err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb); - if (err) { - destroy_unmap_eq(dev, &eq->core); - goto clean_eq; - } + irq = xa_load(&table->comp_irqs, vecidx); + eq->irq_nb.notifier_call = mlx5_eq_comp_int; + param = (struct mlx5_eq_param) { + .irq = irq, + .nent = nent, + }; - mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->core.eqn); - err = xa_err(xa_store(&table->comp_eqs, index, eq, GFP_KERNEL)); - if (err) - goto disable_eq; - table->curr_comp_eqs++; + err = create_map_eq(dev, &eq->core, ¶m); + if (err) + goto clean_eq; + err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb); + if (err) { + destroy_unmap_eq(dev, &eq->core); + goto clean_eq; } + mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->core.eqn); + err = xa_err(xa_store(&table->comp_eqs, vecidx, eq, GFP_KERNEL)); + if (err) + goto disable_eq; + + table->curr_comp_eqs++; return 0; disable_eq: mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); clean_eq: kfree(eq); -clean: - destroy_comp_eqs(dev); -err_irqs_req: - free_rmap(dev); +clean_irq: + comp_irq_release(dev, vecidx); return err; } @@ -1161,6 +1135,7 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) { struct mlx5_eq_table *eq_table = dev->priv.eq_table; int err; + int i; eq_table->max_comp_eqs = get_num_eqs(dev); err = create_async_eqs(dev); @@ -1169,8 +1144,19 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) goto err_async_eqs; } - err = create_comp_eqs(dev); + err = alloc_rmap(dev); if (err) { + mlx5_core_err(dev, "Failed to allocate rmap\n"); + goto err_rmap; + } + + for (i = 0; i < eq_table->max_comp_eqs; i++) { + err = create_comp_eq(dev, i); + if (err < 0) + break; + } + + if (!i) { mlx5_core_err(dev, "Failed to create completion EQs\n"); goto err_comp_eqs; } @@ -1178,6 +1164,8 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) return 0; err_comp_eqs: + free_rmap(dev); +err_rmap: destroy_async_eqs(dev); err_async_eqs: return err; @@ -1185,7 +1173,14 @@ err_async_eqs: void mlx5_eq_table_destroy(struct mlx5_core_dev *dev) { - destroy_comp_eqs(dev); + struct mlx5_eq_table *table = dev->priv.eq_table; + struct mlx5_eq_comp *eq; + unsigned long index; + + xa_for_each(&table->comp_eqs, index, eq) + destroy_comp_eq(dev, eq, index); + + free_rmap(dev); destroy_async_eqs(dev); } -- cgit From ddd2c79da02021153dc8674e5a7e9748e56c1240 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 12 Jun 2023 11:50:10 +0300 Subject: net/mlx5: Introduce mlx5_cpumask_default_spread For better code readability in the completion IRQ request code, define the cpu lookup per completion vector logic in a separate function. The new method mlx5_cpumask_default_spread() given a vector index 'n' will return the 'nth' cpu. This new method will be used also in the next patch. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 41fa15757101..ad654d460d0c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -826,20 +826,18 @@ static void comp_irq_release_pci(struct mlx5_core_dev *dev, u16 vecidx) mlx5_irq_release_vector(irq); } -static int comp_irq_request_pci(struct mlx5_core_dev *dev, u16 vecidx) +static int mlx5_cpumask_default_spread(int numa_node, int index) { - struct mlx5_eq_table *table = dev->priv.eq_table; const struct cpumask *prev = cpu_none_mask; const struct cpumask *mask; - struct mlx5_irq *irq; int found_cpu = 0; int i = 0; int cpu; rcu_read_lock(); - for_each_numa_hop_mask(mask, dev->priv.numa_node) { + for_each_numa_hop_mask(mask, numa_node) { for_each_cpu_andnot(cpu, mask, prev) { - if (i++ == vecidx) { + if (i++ == index) { found_cpu = cpu; goto spread_done; } @@ -849,7 +847,17 @@ static int comp_irq_request_pci(struct mlx5_core_dev *dev, u16 vecidx) spread_done: rcu_read_unlock(); - irq = mlx5_irq_request_vector(dev, found_cpu, vecidx, &table->rmap); + return found_cpu; +} + +static int comp_irq_request_pci(struct mlx5_core_dev *dev, u16 vecidx) +{ + struct mlx5_eq_table *table = dev->priv.eq_table; + struct mlx5_irq *irq; + int cpu; + + cpu = mlx5_cpumask_default_spread(dev->priv.numa_node, vecidx); + irq = mlx5_irq_request_vector(dev, cpu, vecidx, &table->rmap); if (IS_ERR(irq)) return PTR_ERR(irq); -- cgit From f3147015fa0769cf1dcbfdb9040ad380cc4daeb5 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 12 Jun 2023 11:58:14 +0300 Subject: net/mlx5: Add IRQ vector to CPU lookup function Currently, once driver load completes, IRQ requests were performed for all vectors. However, as we move to support dynamic creation of EQs, this will not be the case as some IRQs will not exist at this stage. Thus, in such case, use the default CPU to IRQ mapping which is the serial mapping based on IRQ vector index. Meaning, the n'th vector gets mapped to the n'th CPU. Introduce an API function mlx5_comp_vector_cpu() that takes an IRQ index and provides the corresponding CPU mapping. It utilizes the existing IRQ affinity if defined, or resorts to the default serialized CPU mapping otherwise. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/trap.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 19 ++++++++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c index 201ac7dd338f..bcf9807a5556 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c @@ -128,7 +128,7 @@ static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev, static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv) { - int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, 0)); + int cpu = mlx5_comp_vector_get_cpu(priv->mdev, 0); struct net_device *netdev = priv->netdev; struct mlx5e_trap *t; int err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 1c820119e438..9ec7b975c549 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2445,7 +2445,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, struct xsk_buff_pool *xsk_pool, struct mlx5e_channel **cp) { - int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, ix)); + int cpu = mlx5_comp_vector_get_cpu(priv->mdev, ix); struct net_device *netdev = priv->netdev; struct mlx5e_xsk_param xsk; struct mlx5e_channel *c; @@ -2862,7 +2862,7 @@ static void mlx5e_set_default_xps_cpumasks(struct mlx5e_priv *priv, cpumask_clear(priv->scratchpad.cpumask); for (irq = ix; irq < num_comp_vectors; irq += params->num_channels) { - int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(mdev, irq)); + int cpu = mlx5_comp_vector_get_cpu(mdev, irq); cpumask_set_cpu(cpu, priv->scratchpad.cpumask); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ad654d460d0c..2f5c0d00285f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -1058,7 +1058,7 @@ unsigned int mlx5_comp_vectors_count(struct mlx5_core_dev *dev) } EXPORT_SYMBOL(mlx5_comp_vectors_count); -struct cpumask * +static struct cpumask * mlx5_comp_irq_get_affinity_mask(struct mlx5_core_dev *dev, int vector) { struct mlx5_eq_table *table = dev->priv.eq_table; @@ -1068,10 +1068,23 @@ mlx5_comp_irq_get_affinity_mask(struct mlx5_core_dev *dev, int vector) if (eq) return mlx5_irq_get_affinity_mask(eq->core.irq); - WARN_ON_ONCE(1); return NULL; } -EXPORT_SYMBOL(mlx5_comp_irq_get_affinity_mask); + +int mlx5_comp_vector_get_cpu(struct mlx5_core_dev *dev, int vector) +{ + struct cpumask *mask; + int cpu; + + mask = mlx5_comp_irq_get_affinity_mask(dev, vector); + if (mask) + cpu = cpumask_first(mask); + else + cpu = mlx5_cpumask_default_spread(dev->priv.numa_node, vector); + + return cpu; +} +EXPORT_SYMBOL(mlx5_comp_vector_get_cpu); #ifdef CONFIG_RFS_ACCEL struct cpu_rmap *mlx5_eq_table_get_rmap(struct mlx5_core_dev *dev) -- cgit From 674dd4e2e04e7a62bfacf28129e0808f33395bdf Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Thu, 22 Jun 2023 18:52:44 +0300 Subject: net/mlx5: Rename mlx5_comp_vectors_count() to mlx5_comp_vectors_max() To accurately represent its purpose, rename the function that retrieves the value of maximum vectors from mlx5_comp_vectors_count() to mlx5_comp_vectors_max(). Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 0f8f70b91485..c1deb04ba7e8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -193,7 +193,7 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) { return is_kdump_kernel() ? MLX5E_MIN_NUM_CHANNELS : - min_t(int, mlx5_comp_vectors_count(mdev), MLX5E_MAX_NUM_CHANNELS); + min_t(int, mlx5_comp_vectors_max(mdev), MLX5E_MAX_NUM_CHANNELS); } /* The maximum WQE size can be retrieved by max_wqe_sz_sq in diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 9ec7b975c549..5710d755c2c4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2856,7 +2856,7 @@ static void mlx5e_set_default_xps_cpumasks(struct mlx5e_priv *priv, struct mlx5_core_dev *mdev = priv->mdev; int num_comp_vectors, ix, irq; - num_comp_vectors = mlx5_comp_vectors_count(mdev); + num_comp_vectors = mlx5_comp_vectors_max(mdev); for (ix = 0; ix < params->num_channels; ix++) { cpumask_clear(priv->scratchpad.cpumask); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 2f5c0d00285f..6272962ea077 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -1052,11 +1052,11 @@ int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn) return vector2eqnirqn(dev, vector, NULL, irqn); } -unsigned int mlx5_comp_vectors_count(struct mlx5_core_dev *dev) +unsigned int mlx5_comp_vectors_max(struct mlx5_core_dev *dev) { return dev->priv.eq_table->max_comp_eqs; } -EXPORT_SYMBOL(mlx5_comp_vectors_count); +EXPORT_SYMBOL(mlx5_comp_vectors_max); static struct cpumask * mlx5_comp_irq_get_affinity_mask(struct mlx5_core_dev *dev, int vector) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c index 4a5ae86e2b62..24bb30b5008c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c @@ -1096,7 +1096,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, if (!in) goto err_cqwq; - vector = raw_smp_processor_id() % mlx5_comp_vectors_count(mdev); + vector = raw_smp_processor_id() % mlx5_comp_vectors_max(mdev); err = mlx5_vector2eqn(mdev, vector, &eqn); if (err) { kvfree(in); -- cgit From 54c5297801f3b9140c751c7f5660770c52dea24e Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Thu, 22 Jun 2023 19:05:46 +0300 Subject: net/mlx5: Handle SF IRQ request in the absence of SF IRQ pool In case the SF IRQ pool is not available due to setup limitations, SF currently relies on the already allocated PF IRQs to fulfill its IRQ vector requests. However, with the dynamic EQ allocation introduced in the next patch, it is possible that not all IRQs of PF will be allocated after the driver is loaded. In such case, if a SF requests a completion IRQ without having its own independent IRQ pool, SF will lack a PF IRQ to utilize. To address this scenario, allocate an IRQ for the SF from the PF's IRQ pool on demand. The new IRQ will be shared between the SF and it's PF. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 24 ++++++++++++++++++++-- .../net/ethernet/mellanox/mlx5/core/irq_affinity.c | 12 ++++------- 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 6272962ea077..6e6e0a1c12b5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -850,14 +850,29 @@ spread_done: return found_cpu; } +static struct cpu_rmap *mlx5_eq_table_get_pci_rmap(struct mlx5_core_dev *dev) +{ +#ifdef CONFIG_RFS_ACCEL +#ifdef CONFIG_MLX5_SF + if (mlx5_core_is_sf(dev)) + return dev->priv.parent_mdev->priv.eq_table->rmap; +#endif + return dev->priv.eq_table->rmap; +#else + return NULL; +#endif +} + static int comp_irq_request_pci(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; + struct cpu_rmap *rmap; struct mlx5_irq *irq; int cpu; + rmap = mlx5_eq_table_get_pci_rmap(dev); cpu = mlx5_cpumask_default_spread(dev->priv.numa_node, vecidx); - irq = mlx5_irq_request_vector(dev, cpu, vecidx, &table->rmap); + irq = mlx5_irq_request_vector(dev, cpu, vecidx, &rmap); if (IS_ERR(irq)) return PTR_ERR(irq); @@ -883,8 +898,13 @@ static int comp_irq_request_sf(struct mlx5_core_dev *dev, u16 vecidx) struct mlx5_irq *irq; irq = mlx5_irq_affinity_irq_request_auto(dev, &table->used_cpus, vecidx); - if (IS_ERR(irq)) + if (IS_ERR(irq)) { + /* In case SF irq pool does not exist, fallback to the PF irqs*/ + if (PTR_ERR(irq) == -ENOENT) + return comp_irq_request_pci(dev, vecidx); + return PTR_ERR(irq); + } return xa_err(xa_store(&table->comp_irqs, vecidx, irq, GFP_KERNEL)); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c index ed51800f9f67..047d5fed5f89 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c @@ -191,17 +191,13 @@ struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev, struct irq_affinity_desc af_desc = {}; struct mlx5_irq *irq; + if (!mlx5_irq_pool_is_sf_pool(pool)) + return ERR_PTR(-ENOENT); + af_desc.is_managed = 1; cpumask_copy(&af_desc.mask, cpu_online_mask); cpumask_andnot(&af_desc.mask, &af_desc.mask, used_cpus); - if (mlx5_irq_pool_is_sf_pool(pool)) - irq = mlx5_irq_affinity_request(pool, &af_desc); - else - /* In case SF pool doesn't exists, fallback to the PF IRQs. - * The PF IRQs are already allocated and binded to CPU - * at this point. Hence, only an index is needed. - */ - irq = mlx5_irq_request(dev, vecidx, NULL, NULL); + irq = mlx5_irq_affinity_request(pool, &af_desc); if (IS_ERR(irq)) return irq; -- cgit From f14c1a14e63227a65faa68237687784a6dd2e922 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 12 Jun 2023 10:13:50 +0300 Subject: net/mlx5: Allocate completion EQs dynamically This commit enables the dynamic allocation of EQs at runtime, allowing for more flexibility in managing completion EQs and reducing the memory overhead of driver load. Whenever a CQ is created for a given vector index, the driver will lookup to see if there is an already mapped completion EQ for that vector, if so, utilize it. Otherwise, allocate a new EQ on demand and then utilize it for the CQ completion events. Add a protection lock to the EQ table to protect from concurrent EQ creation attempts. While at it, replace mlx5_vector2irqn()/mlx5_vector2eqn() with mlx5_comp_eqn_get() and mlx5_comp_irqn_get() which will allocate an EQ on demand if no EQ is found for the given vector. Signed-off-by: Maher Sanalla Reviewed-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 80 ++++++++++++---------- .../net/ethernet/mellanox/mlx5/core/fpga/conn.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h | 2 +- .../ethernet/mellanox/mlx5/core/steering/dr_send.c | 2 +- 6 files changed, 49 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 5710d755c2c4..5919b889479f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1989,7 +1989,7 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param) int eqn; int err; - err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn); + err = mlx5_comp_eqn_get(mdev, param->eq_ix, &eqn); if (err) return err; @@ -2452,7 +2452,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, unsigned int irq; int err; - err = mlx5_vector2irqn(priv->mdev, ix, &irq); + err = mlx5_comp_irqn_get(priv->mdev, ix, &irq); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 6e6e0a1c12b5..ea0405e0a43f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -58,6 +58,7 @@ struct mlx5_eq_table { struct mlx5_nb cq_err_nb; struct mutex lock; /* sync async eqs creations */ + struct mutex comp_lock; /* sync comp eqs creations */ int curr_comp_eqs; int max_comp_eqs; struct mlx5_irq_table *irq_table; @@ -457,6 +458,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev) cpumask_clear(&eq_table->used_cpus); xa_init(&eq_table->comp_eqs); xa_init(&eq_table->comp_irqs); + mutex_init(&eq_table->comp_lock); eq_table->curr_comp_eqs = 0; return 0; } @@ -985,6 +987,7 @@ static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev) return MLX5_COMP_EQ_SIZE; } +/* Must be called with EQ table comp_lock held */ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx) { struct mlx5_eq_table *table = dev->priv.eq_table; @@ -994,6 +997,13 @@ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx) int nent; int err; + lockdep_assert_held(&table->comp_lock); + if (table->curr_comp_eqs == table->max_comp_eqs) { + mlx5_core_err(dev, "maximum number of vectors is allocated, %d\n", + table->max_comp_eqs); + return -ENOMEM; + } + err = comp_irq_request(dev, vecidx); if (err) return err; @@ -1033,7 +1043,7 @@ static int create_comp_eq(struct mlx5_core_dev *dev, u16 vecidx) goto disable_eq; table->curr_comp_eqs++; - return 0; + return eq->core.eqn; disable_eq: mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); @@ -1044,32 +1054,47 @@ clean_irq: return err; } -static int vector2eqnirqn(struct mlx5_core_dev *dev, int vector, int *eqn, - unsigned int *irqn) +int mlx5_comp_eqn_get(struct mlx5_core_dev *dev, u16 vecidx, int *eqn) { struct mlx5_eq_table *table = dev->priv.eq_table; struct mlx5_eq_comp *eq; + int ret = 0; - eq = xa_load(&table->comp_eqs, vector); - if (!eq) - return -ENOENT; - - if (irqn) - *irqn = eq->core.irqn; - if (eqn) + mutex_lock(&table->comp_lock); + eq = xa_load(&table->comp_eqs, vecidx); + if (eq) { *eqn = eq->core.eqn; + goto out; + } + + ret = create_comp_eq(dev, vecidx); + if (ret < 0) { + mutex_unlock(&table->comp_lock); + return ret; + } + + *eqn = ret; +out: + mutex_unlock(&table->comp_lock); return 0; } +EXPORT_SYMBOL(mlx5_comp_eqn_get); -int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn) +int mlx5_comp_irqn_get(struct mlx5_core_dev *dev, int vector, unsigned int *irqn) { - return vector2eqnirqn(dev, vector, eqn, NULL); -} -EXPORT_SYMBOL(mlx5_vector2eqn); + struct mlx5_eq_table *table = dev->priv.eq_table; + struct mlx5_eq_comp *eq; + int eqn; + int err; -int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn) -{ - return vector2eqnirqn(dev, vector, NULL, irqn); + /* Allocate the EQ if not allocated yet */ + err = mlx5_comp_eqn_get(dev, vector, &eqn); + if (err) + return err; + + eq = xa_load(&table->comp_eqs, vector); + *irqn = eq->core.irqn; + return 0; } unsigned int mlx5_comp_vectors_max(struct mlx5_core_dev *dev) @@ -1119,10 +1144,9 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn) struct mlx5_eq_comp *eq; unsigned long index; - xa_for_each(&table->comp_eqs, index, eq) { + xa_for_each(&table->comp_eqs, index, eq) if (eq->core.eqn == eqn) return eq; - } return ERR_PTR(-ENOENT); } @@ -1130,11 +1154,7 @@ struct mlx5_eq_comp *mlx5_eqn2comp_eq(struct mlx5_core_dev *dev, int eqn) /* This function should only be called after mlx5_cmd_force_teardown_hca */ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev) { - struct mlx5_eq_table *table = dev->priv.eq_table; - - mutex_lock(&table->lock); /* sync with create/destroy_async_eq */ mlx5_irq_table_free_irqs(dev); - mutex_unlock(&table->lock); } #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING @@ -1176,7 +1196,6 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) { struct mlx5_eq_table *eq_table = dev->priv.eq_table; int err; - int i; eq_table->max_comp_eqs = get_num_eqs(dev); err = create_async_eqs(dev); @@ -1191,21 +1210,8 @@ int mlx5_eq_table_create(struct mlx5_core_dev *dev) goto err_rmap; } - for (i = 0; i < eq_table->max_comp_eqs; i++) { - err = create_comp_eq(dev, i); - if (err < 0) - break; - } - - if (!i) { - mlx5_core_err(dev, "Failed to create completion EQs\n"); - goto err_comp_eqs; - } - return 0; -err_comp_eqs: - free_rmap(dev); err_rmap: destroy_async_eqs(dev); err_async_eqs: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c index 12abe991583a..c4de6bf8d1b6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c @@ -445,7 +445,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) goto err_cqwq; } - err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn); + err = mlx5_comp_eqn_get(mdev, smp_processor_id(), &eqn); if (err) { kvfree(in); goto err_cqwq; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c index 5a80fb7dbbca..40c7be124041 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c @@ -81,7 +81,7 @@ static int create_aso_cq(struct mlx5_aso_cq *cq, void *cqc_data) int inlen, eqn; int err; - err = mlx5_vector2eqn(mdev, 0, &eqn); + err = mlx5_comp_eqn_get(mdev, 0, &eqn); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h index d3d628b862f3..69a75459775d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h @@ -104,6 +104,6 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev); struct cpu_rmap *mlx5_eq_table_get_rmap(struct mlx5_core_dev *dev); #endif -int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn); +int mlx5_comp_irqn_get(struct mlx5_core_dev *dev, int vector, unsigned int *irqn); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c index 24bb30b5008c..6fa06ba2d346 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c @@ -1097,7 +1097,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, goto err_cqwq; vector = raw_smp_processor_id() % mlx5_comp_vectors_max(mdev); - err = mlx5_vector2eqn(mdev, vector, &eqn); + err = mlx5_comp_eqn_get(mdev, vector, &eqn); if (err) { kvfree(in); goto err_cqwq; -- cgit From a0ae00e71e3e652c3bde8dcb61b4c1718618192e Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 4 Aug 2023 09:43:44 +0800 Subject: net/mlx5: remove many unnecessary NULL values There are many pointers assigned first, which need not to be initialized, so remove the NULL assignments. Signed-off-by: Ruan Jinjie Reviewed-by: Jesse Brandeburg Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c index 39c03dcbd196..e5c1012921d2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c @@ -57,7 +57,7 @@ static const char * const mlx5_fpga_qp_error_strings[] = { }; static struct mlx5_fpga_device *mlx5_fpga_device_alloc(void) { - struct mlx5_fpga_device *fdev = NULL; + struct mlx5_fpga_device *fdev; fdev = kzalloc(sizeof(*fdev), GFP_KERNEL); if (!fdev) @@ -252,7 +252,7 @@ out: int mlx5_fpga_init(struct mlx5_core_dev *mdev) { - struct mlx5_fpga_device *fdev = NULL; + struct mlx5_fpga_device *fdev; if (!MLX5_CAP_GEN(mdev, fpga)) { mlx5_core_dbg(mdev, "FPGA capability not present\n"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c index 4047629a876b..30564d9b00e9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c @@ -40,7 +40,7 @@ struct mlx5_hv_vhca_agent { struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev) { - struct mlx5_hv_vhca *hv_vhca = NULL; + struct mlx5_hv_vhca *hv_vhca; hv_vhca = kzalloc(sizeof(*hv_vhca), GFP_KERNEL); if (!hv_vhca) -- cgit From 58f6d9d04489788d4115bd4bec4193df9e23f45f Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Sun, 6 Aug 2023 13:34:59 +0300 Subject: net/mlx5: Fix typo reminder -> remainder Fix a typo in esw_qos_devlink_rate_to_mbps(): reminder -> remainder. Signed-off-by: Gal Pressman Reviewed-by: Rahul Rameshbabu Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c index 7c79476cc5f9..1887a24ee414 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c @@ -740,7 +740,7 @@ int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *name, u64 *rate, struct netlink_ext_ack *extack) { - u32 link_speed_max, reminder; + u32 link_speed_max, remainder; u64 value; int err; @@ -750,8 +750,8 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char * return err; } - value = div_u64_rem(*rate, MLX5_LINKSPEED_UNIT, &reminder); - if (reminder) { + value = div_u64_rem(*rate, MLX5_LINKSPEED_UNIT, &remainder); + if (remainder) { pr_err("%s rate value %lluBps not in link speed units of 1Mbps.\n", name, *rate); NL_SET_ERR_MSG_MOD(extack, "TX rate value not in link speed units of 1Mbps"); -- cgit From d602be220cf97aa581a9b34a7780a889bc3dd25c Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 11 Jul 2023 09:42:01 +0300 Subject: net/mlx5: E-Switch, Remove redundant arg ignore_flow_lvl The arg is always passed as true and thus redundant. Signed-off-by: Roi Dayan Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 723dff87e6d5..e391535e1ab1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -375,7 +375,6 @@ esw_setup_indir_table(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr, - bool ignore_flow_lvl, int *i) { struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; @@ -385,8 +384,7 @@ esw_setup_indir_table(struct mlx5_flow_destination *dest, return -EOPNOTSUPP; for (j = esw_attr->split_count; j < esw_attr->out_count; j++, (*i)++) { - if (ignore_flow_lvl) - flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; + flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; dest[*i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest[*i].ft = mlx5_esw_indir_table_get(esw, attr, @@ -569,7 +567,7 @@ esw_setup_dests(struct mlx5_flow_destination *dest, err = esw_setup_mtu_dest(dest, &attr->meter_attr, *i); (*i)++; } else if (esw_is_indir_table(esw, attr)) { - err = esw_setup_indir_table(dest, flow_act, esw, attr, true, i); + err = esw_setup_indir_table(dest, flow_act, esw, attr, i); } else if (esw_is_chain_src_port_rewrite(esw, esw_attr)) { err = esw_setup_chain_src_port_rewrite(dest, flow_act, esw, chains, attr, i); } else { -- cgit From b56fb19c337951fc4daba646fab2c50bb4c41c58 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 11 Jul 2023 13:23:27 +0300 Subject: net/mlx5: Bridge, Only handle registered netdev bridge events Don't handle bridge events for a netdev that doesn't belong to an eswitch that registered for bridge events. Signed-off-by: Roi Dayan Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index 560800246573..0fef853eab62 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -77,6 +77,10 @@ mlx5_esw_bridge_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_es return NULL; priv = netdev_priv(dev); + + if (!priv->mdev->priv.eswitch->br_offloads) + return NULL; + rpriv = priv->ppriv; *vport_num = rpriv->rep->vport; *esw_owner_vhca_id = MLX5_CAP_GEN(priv->mdev, vhca_id); -- cgit From 26cfb838aa002a5c03319f7fce87e9313e794351 Mon Sep 17 00:00:00 2001 From: Johannes Zink Date: Tue, 1 Aug 2023 17:44:29 +0200 Subject: net: stmmac: correct MAC propagation delay The IEEE1588 Standard specifies that the timestamps of Packets must be captured when the PTP message timestamp point (leading edge of first octet after the start of frame delimiter) crosses the boundary between the node and the network. As the MAC latches the timestamp at an internal point, the captured timestamp must be corrected for the additional data transmission latency, as described in the publicly available datasheet [1]. This patch only corrects for the MAC-Internal delay, which can be read out from the MAC_Ingress_Timestamp_Latency register on DWMAC version 5, since the Phy framework currently does not support querying the Phy ingress and egress latency. The Closs Domain Crossing Circuits errors as indicated in [1] are already being accounted in the stmmac_get_tx_hwtstamp() function and are not corrected here. As the Latency varies for different link speeds and MII modes of operation, the correction value needs to be updated on each link state change. As the delay also causes a phase shift in the timestamp counter compared to the rest of the network, this correction will also reduce phase error when generating PPS outputs from the timestamp counter. Since the correction registers may be unavailable on some hardware and no feature bits are documented for dynamically detection of the MAC propagation delay readout, introduce a feature bit to explicitely enable MAC delay Correction in the gluecode driver. [1] i.MX8MP Reference Manual, rev.1 Section 11.7.2.5.3 "Timestamp correction" Signed-off-by: Johannes Zink Link: https://lore.kernel.org/r/20230719-stmmac_correct_mac_delay-v2-1-3366f38ee9a6@pengutronix.de Link: https://lore.kernel.org/r/20230719-stmmac_correct_mac_delay-v3-1-61e63427735e@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 ++ .../net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 43 ++++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++ drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 6 +++ 4 files changed, 58 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 652af8f6e75f..238f17c50a1e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -532,6 +532,7 @@ struct stmmac_hwtimestamp { void (*get_systime) (void __iomem *ioaddr, u64 *systime); void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time); void (*timestamp_interrupt)(struct stmmac_priv *priv); + void (*hwtstamp_correct_latency)(struct stmmac_priv *priv); }; #define stmmac_config_hw_tstamping(__priv, __args...) \ @@ -550,6 +551,8 @@ struct stmmac_hwtimestamp { stmmac_do_void_callback(__priv, ptp, get_ptptime, __args) #define stmmac_timestamp_interrupt(__priv, __args...) \ stmmac_do_void_callback(__priv, ptp, timestamp_interrupt, __args) +#define stmmac_hwtstamp_correct_latency(__priv, __args...) \ + stmmac_do_void_callback(__priv, ptp, hwtstamp_correct_latency, __args) struct stmmac_tx_queue; struct stmmac_rx_queue; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index fa2c3ba7e9fe..540f6a4ec0b8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -60,6 +60,48 @@ static void config_sub_second_increment(void __iomem *ioaddr, *ssinc = data; } +static void hwtstamp_correct_latency(struct stmmac_priv *priv) +{ + void __iomem *ioaddr = priv->ptpaddr; + u32 reg_tsic, reg_tsicsns; + u32 reg_tsec, reg_tsecsns; + u64 scaled_ns; + u32 val; + + /* MAC-internal ingress latency */ + scaled_ns = readl(ioaddr + PTP_TS_INGR_LAT); + + /* See section 11.7.2.5.3.1 "Ingress Correction" on page 4001 of + * i.MX8MP Applications Processor Reference Manual Rev. 1, 06/2021 + */ + val = readl(ioaddr + PTP_TCR); + if (val & PTP_TCR_TSCTRLSSR) + /* nanoseconds field is in decimal format with granularity of 1ns/bit */ + scaled_ns = ((u64)NSEC_PER_SEC << 16) - scaled_ns; + else + /* nanoseconds field is in binary format with granularity of ~0.466ns/bit */ + scaled_ns = ((1ULL << 31) << 16) - + DIV_U64_ROUND_CLOSEST(scaled_ns * PSEC_PER_NSEC, 466U); + + reg_tsic = scaled_ns >> 16; + reg_tsicsns = scaled_ns & 0xff00; + + /* set bit 31 for 2's compliment */ + reg_tsic |= BIT(31); + + writel(reg_tsic, ioaddr + PTP_TS_INGR_CORR_NS); + writel(reg_tsicsns, ioaddr + PTP_TS_INGR_CORR_SNS); + + /* MAC-internal egress latency */ + scaled_ns = readl(ioaddr + PTP_TS_EGR_LAT); + + reg_tsec = scaled_ns >> 16; + reg_tsecsns = scaled_ns & 0xff00; + + writel(reg_tsec, ioaddr + PTP_TS_EGR_CORR_NS); + writel(reg_tsecsns, ioaddr + PTP_TS_EGR_CORR_SNS); +} + static int init_systime(void __iomem *ioaddr, u32 sec, u32 nsec) { u32 value; @@ -221,4 +263,5 @@ const struct stmmac_hwtimestamp stmmac_ptp = { .get_systime = get_systime, .get_ptptime = get_ptptime, .timestamp_interrupt = timestamp_interrupt, + .hwtstamp_correct_latency = hwtstamp_correct_latency, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e1f1c034d325..99aa5360b3ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -909,6 +909,9 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) priv->hwts_tx_en = 0; priv->hwts_rx_en = 0; + if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) + stmmac_hwtstamp_correct_latency(priv, priv); + return 0; } @@ -1094,6 +1097,9 @@ static void stmmac_mac_link_up(struct phylink_config *config, if (priv->dma_cap.fpesel) stmmac_fpe_link_state_handle(priv, true); + + if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) + stmmac_hwtstamp_correct_latency(priv, priv); } static const struct phylink_mac_ops stmmac_phylink_mac_ops = { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index bf619295d079..d1fe4b46f162 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -26,6 +26,12 @@ #define PTP_ACR 0x40 /* Auxiliary Control Reg */ #define PTP_ATNR 0x48 /* Auxiliary Timestamp - Nanoseconds Reg */ #define PTP_ATSR 0x4c /* Auxiliary Timestamp - Seconds Reg */ +#define PTP_TS_INGR_CORR_NS 0x58 /* Ingress timestamp correction nanoseconds */ +#define PTP_TS_EGR_CORR_NS 0x5C /* Egress timestamp correction nanoseconds*/ +#define PTP_TS_INGR_CORR_SNS 0x60 /* Ingress timestamp correction subnanoseconds */ +#define PTP_TS_EGR_CORR_SNS 0x64 /* Egress timestamp correction subnanoseconds */ +#define PTP_TS_INGR_LAT 0x68 /* MAC internal Ingress Latency */ +#define PTP_TS_EGR_LAT 0x6c /* MAC internal Egress Latency */ #define PTP_STNSUR_ADDSUB_SHIFT 31 #define PTP_DIGITAL_ROLLOVER_MODE 0x3B9ACA00 /* 10e9-1 ns */ -- cgit From 6cb2e613c79653e40814152def7abec32efe0f29 Mon Sep 17 00:00:00 2001 From: Johannes Zink Date: Tue, 1 Aug 2023 17:44:30 +0200 Subject: net: stmmac: dwmac-imx: enable MAC propagation delay correction for i.MX8MP As the i.MX8MP supports reading MAC propagation delay and correcting the Hardware timestamp counter for additional delays [1], enable the feature for this SoC. This reduces phase error of the PPS output from the PTP Hardware Clock from approx 150ns to 100ns. [1] i.MX8MP Reference Manual, rev.1 Section 11.7.2.5.3 "Timestamp correction" Signed-off-by: Johannes Zink Link: https://lore.kernel.org/r/20230719-stmmac_correct_mac_delay-v3-2-61e63427735e@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 92e06a96757a..645a9454a490 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -42,6 +42,7 @@ struct imx_dwmac_ops { u32 addr_width; + u32 flags; bool mac_rgmii_txclk_auto_adj; int (*fix_soc_reset)(void *priv, void __iomem *ioaddr); @@ -311,6 +312,9 @@ static int imx_dwmac_probe(struct platform_device *pdev) goto err_parse_dt; } + if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) + plat_dat->flags |= STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY; + plat_dat->host_dma_width = dwmac->ops->addr_width; plat_dat->init = imx_dwmac_init; plat_dat->exit = imx_dwmac_exit; @@ -350,6 +354,7 @@ static struct imx_dwmac_ops imx8mp_dwmac_data = { .addr_width = 34, .mac_rgmii_txclk_auto_adj = false, .set_intf_mode = imx8mp_set_intf_mode, + .flags = STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY, }; static struct imx_dwmac_ops imx8dxl_dwmac_data = { -- cgit From 505a1fdadac1f10b436e8bbf9a63e4e0f7b63077 Mon Sep 17 00:00:00 2001 From: Wojciech Drewek Date: Thu, 27 Jul 2023 10:35:39 +0200 Subject: ice: Accept LAG netdevs in bridge offloads Allow LAG interfaces to be used in bridge offload using netif_is_lag_master. In this case, search for ice netdev in the list of LAG's lower devices. Reviewed-by: Jedrzej Jagielski Signed-off-by: Wojciech Drewek Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch_br.c | 47 ++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index cc7357ed6e5f..67bfd1f61cdd 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -20,8 +20,23 @@ static const struct rhashtable_params ice_fdb_ht_params = { static bool ice_eswitch_br_is_dev_valid(const struct net_device *dev) { - /* Accept only PF netdev and PRs */ - return ice_is_port_repr_netdev(dev) || netif_is_ice(dev); + /* Accept only PF netdev, PRs and LAG */ + return ice_is_port_repr_netdev(dev) || netif_is_ice(dev) || + netif_is_lag_master(dev); +} + +static struct net_device * +ice_eswitch_br_get_uplink_from_lag(struct net_device *lag_dev) +{ + struct net_device *lower; + struct list_head *iter; + + netdev_for_each_lower_dev(lag_dev, lower, iter) { + if (netif_is_ice(lower)) + return lower; + } + + return NULL; } static struct ice_esw_br_port * @@ -31,8 +46,19 @@ ice_eswitch_br_netdev_to_port(struct net_device *dev) struct ice_repr *repr = ice_netdev_to_repr(dev); return repr->br_port; - } else if (netif_is_ice(dev)) { - struct ice_pf *pf = ice_netdev_to_pf(dev); + } else if (netif_is_ice(dev) || netif_is_lag_master(dev)) { + struct net_device *ice_dev; + struct ice_pf *pf; + + if (netif_is_lag_master(dev)) + ice_dev = ice_eswitch_br_get_uplink_from_lag(dev); + else + ice_dev = dev; + + if (!ice_dev) + return NULL; + + pf = ice_netdev_to_pf(ice_dev); return pf->br_port; } @@ -1085,7 +1111,18 @@ ice_eswitch_br_port_link(struct ice_esw_br_offloads *br_offloads, err = ice_eswitch_br_vf_repr_port_init(bridge, repr); trace_ice_eswitch_br_port_link(repr->br_port); } else { - struct ice_pf *pf = ice_netdev_to_pf(dev); + struct net_device *ice_dev; + struct ice_pf *pf; + + if (netif_is_lag_master(dev)) + ice_dev = ice_eswitch_br_get_uplink_from_lag(dev); + else + ice_dev = dev; + + if (!ice_dev) + return 0; + + pf = ice_netdev_to_pf(ice_dev); err = ice_eswitch_br_uplink_port_init(bridge, pf); trace_ice_eswitch_br_port_link(pf->br_port); -- cgit From 0960a27bd479fdff21c14ff449dac85f86d7eb4d Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Thu, 22 Jun 2023 15:35:12 +0200 Subject: ice: Add direction metadata Currently it is possible to create a filter which breaks TX traffic, e.g.: tc filter add dev $PF1 ingress protocol ip prio 1 flower ip_proto udp dst_port $PORT action mirred egress redirect dev $VF1_PR This adds a rule which might match both TX and RX traffic, and in TX path the PF will actually receive the traffic, which breaks communication. To fix this, add a match on direction metadata flag when adding a tc rule. Because of the way metadata is currently handled, a duplicate lookup word would appear if VLAN metadata is also added. The lookup would still work correctly, but one word would be wasted. To prevent it, lookup 0 now always contains all metadata. When any metadata needs to be added, it is added to lookup 0 and lookup count is not incremented. This way, two flags residing in the same word will take up one word, instead of two. Note: the drop action is also affected, i.e. it will now only work in one direction. Signed-off-by: Marcin Szycik Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_protocol_type.h | 1 + drivers/net/ethernet/intel/ice/ice_switch.c | 11 +++++-- drivers/net/ethernet/intel/ice/ice_switch.h | 1 + drivers/net/ethernet/intel/ice/ice_tc_lib.c | 34 +++++++++++----------- 4 files changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h index 6a9364761165..9812b98d107f 100644 --- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h +++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h @@ -287,6 +287,7 @@ struct ice_nvgre_hdr { * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100) * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100) */ +#define ICE_PKT_FROM_NETWORK BIT(3) #define ICE_PKT_VLAN_STAG BIT(12) #define ICE_PKT_VLAN_ITAG BIT(13) #define ICE_PKT_VLAN_EVLAN (BIT(14) | BIT(15)) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 91bc92f5059b..dcbb69bc9f5a 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -6058,14 +6058,21 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw, void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup) { lkup->type = ICE_HW_METADATA; - lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] = + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] |= cpu_to_be16(ICE_PKT_TUNNEL_MASK); } +void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |= + cpu_to_be16(ICE_PKT_FROM_NETWORK); +} + void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup) { lkup->type = ICE_HW_METADATA; - lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] = + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |= cpu_to_be16(ICE_PKT_VLAN_MASK); } diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 250823ac173a..0bd4320e39df 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -359,6 +359,7 @@ int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id); /* Switch/bridge related commands */ void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup); +void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup); void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup); void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup); int diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index 38547db1ec4e..37b54db91df2 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -7,6 +7,8 @@ #include "ice_lib.h" #include "ice_protocol_type.h" +#define ICE_TC_METADATA_LKUP_IDX 0 + /** * ice_tc_count_lkups - determine lookup count for switch filter * @flags: TC-flower flags @@ -19,7 +21,13 @@ static int ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, struct ice_tc_flower_fltr *fltr) { - int lkups_cnt = 0; + int lkups_cnt = 1; /* 0th lookup is metadata */ + + /* Always add metadata as the 0th lookup. Included elements: + * - Direction flag (always present) + * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified) + * - Tunnel flag (present if tunnel) + */ if (flags & ICE_TC_FLWR_FIELD_TENANT_ID) lkups_cnt++; @@ -54,10 +62,6 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) lkups_cnt++; - /* is VLAN TPID specified */ - if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) - lkups_cnt++; - /* is CVLAN specified? */ if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) lkups_cnt++; @@ -84,10 +88,6 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ICE_TC_FLWR_FIELD_SRC_L4_PORT)) lkups_cnt++; - /* matching for tunneled packets in metadata */ - if (fltr->tunnel_type != TNL_LAST) - lkups_cnt++; - return lkups_cnt; } @@ -176,10 +176,9 @@ static u16 ice_check_supported_vlan_tpid(u16 vlan_tpid) static int ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, - struct ice_adv_lkup_elem *list) + struct ice_adv_lkup_elem *list, int i) { struct ice_tc_flower_lyr_2_4_hdrs *hdr = &fltr->outer_headers; - int i = 0; if (flags & ICE_TC_FLWR_FIELD_TENANT_ID) { u32 tenant_id; @@ -329,8 +328,7 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, } /* always fill matching on tunneled packets in metadata */ - ice_rule_add_tunnel_metadata(&list[i]); - i++; + ice_rule_add_tunnel_metadata(&list[ICE_TC_METADATA_LKUP_IDX]); return i; } @@ -358,13 +356,16 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers = &tc_fltr->outer_headers; bool inner = false; u16 vlan_tpid = 0; - int i = 0; + int i = 1; /* 0th lookup is metadata */ rule_info->vlan_type = vlan_tpid; + /* Always add direction metadata */ + ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]); + rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type); if (tc_fltr->tunnel_type != TNL_LAST) { - i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list); + i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i); headers = &tc_fltr->inner_headers; inner = true; @@ -431,8 +432,7 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, rule_info->vlan_type = ice_check_supported_vlan_tpid(vlan_tpid); - ice_rule_add_vlan_metadata(&list[i]); - i++; + ice_rule_add_vlan_metadata(&list[ICE_TC_METADATA_LKUP_IDX]); } if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) { -- cgit From 41ad9f8ee6b8ec292f46b0a0bfaeace51e82a4eb Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Thu, 22 Jun 2023 15:35:13 +0200 Subject: ice: Rename enum ice_pkt_flags values enum ice_pkt_flags contains values such as ICE_PKT_FLAGS_VLAN and ICE_PKT_FLAGS_TUNNEL, but actually the flags words which they refer to contain a range of unrelated values - e.g. word 0 (ICE_PKT_FLAGS_VLAN) contains fields such as from_network and ucast, which have nothing to do with VLAN. Rename each enum value to ICE_PKT_FLAGS_MDID, so it's clear in which flags word does some value reside. Signed-off-by: Marcin Szycik Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_protocol_type.h | 8 ++++---- drivers/net/ethernet/intel/ice/ice_switch.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h index 9812b98d107f..f6f27361c3cf 100644 --- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h +++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h @@ -393,10 +393,10 @@ enum ice_hw_metadata_offset { }; enum ice_pkt_flags { - ICE_PKT_FLAGS_VLAN = 0, - ICE_PKT_FLAGS_TUNNEL = 1, - ICE_PKT_FLAGS_TCP = 2, - ICE_PKT_FLAGS_ERROR = 3, + ICE_PKT_FLAGS_MDID20 = 0, + ICE_PKT_FLAGS_MDID21 = 1, + ICE_PKT_FLAGS_MDID22 = 2, + ICE_PKT_FLAGS_MDID23 = 3, }; struct ice_hw_metadata { diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index dcbb69bc9f5a..a7afb612fe32 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -6058,21 +6058,21 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw, void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup) { lkup->type = ICE_HW_METADATA; - lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] |= + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID21] |= cpu_to_be16(ICE_PKT_TUNNEL_MASK); } void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup) { lkup->type = ICE_HW_METADATA; - lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |= + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |= cpu_to_be16(ICE_PKT_FROM_NETWORK); } void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup) { lkup->type = ICE_HW_METADATA; - lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |= + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |= cpu_to_be16(ICE_PKT_VLAN_MASK); } -- cgit From 272ad7944a7bb17ee1060ff887402ce759823640 Mon Sep 17 00:00:00 2001 From: Karol Kolacinski Date: Thu, 13 Jul 2023 15:21:23 +0200 Subject: ice: Add get C827 PHY index function Add a function to find the C827 PHY node handle and return C827 PHY index for the E810 products. In order to bring this function to full functionality, some helpers for this were written by Michal Michalik. Co-developed-by: Michal Michalik Signed-off-by: Michal Michalik Signed-off-by: Karol Kolacinski Signed-off-by: Jan Sokolowski Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 1 + drivers/net/ethernet/intel/ice/ice_common.c | 62 +++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_common.h | 1 + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 3 ++ 4 files changed, 67 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index c0ad34b42531..1ad92f95d6bd 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1404,6 +1404,7 @@ struct ice_aqc_get_link_topo { struct ice_aqc_link_topo_addr addr; u8 node_part_num; #define ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575 0x21 +#define ICE_AQC_GET_LINK_TOPO_NODE_NR_C827 0x31 u8 rsvd[9]; }; diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index dade0a50299c..ce3f0f2b0e35 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -5,6 +5,7 @@ #include "ice_sched.h" #include "ice_adminq_cmd.h" #include "ice_flow.h" +#include "ice_ptp_hw.h" #define ICE_PF_RESET_WAIT_COUNT 300 @@ -2661,6 +2662,67 @@ ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p, ice_recalc_port_limited_caps(hw, &dev_p->common_cap); } +/** + * ice_aq_get_netlist_node + * @hw: pointer to the hw struct + * @cmd: get_link_topo AQ structure + * @node_part_number: output node part number if node found + * @node_handle: output node handle parameter if node found + */ +static int +ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd, + u8 *node_part_number, u16 *node_handle) +{ + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); + desc.params.get_link_topo = *cmd; + + if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL)) + return -EIO; + + if (node_handle) + *node_handle = le16_to_cpu(desc.params.get_link_topo.addr.handle); + if (node_part_number) + *node_part_number = desc.params.get_link_topo.node_part_num; + + return 0; +} + +/** + * ice_is_pf_c827 - check if pf contains c827 phy + * @hw: pointer to the hw struct + */ +bool ice_is_pf_c827(struct ice_hw *hw) +{ + struct ice_aqc_get_link_topo cmd = {}; + u8 node_part_number; + u16 node_handle; + int status; + + if (hw->mac_type != ICE_MAC_E810) + return false; + + if (hw->device_id != ICE_DEV_ID_E810C_QSFP) + return true; + + cmd.addr.topo_params.node_type_ctx = + FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY) | + FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ICE_AQC_LINK_TOPO_NODE_CTX_PORT); + cmd.addr.topo_params.index = 0; + + status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number, + &node_handle); + + if (status || node_part_number != ICE_AQC_GET_LINK_TOPO_NODE_NR_C827) + return false; + + if (node_handle == E810C_QSFP_C827_0_HANDLE || node_handle == E810C_QSFP_C827_1_HANDLE) + return true; + + return false; +} + /** * ice_aq_list_caps - query function/device capabilities * @hw: pointer to the HW struct diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index df12a9d8d28c..71b82cdf4a6d 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -93,6 +93,7 @@ int ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, struct ice_aqc_get_phy_caps_data *caps, struct ice_sq_cd *cd); +bool ice_is_pf_c827(struct ice_hw *hw); int ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, enum ice_adminq_opc opc, struct ice_sq_cd *cd); diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 3b68cb91bd81..1969425f0084 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -112,6 +112,9 @@ struct ice_cgu_pll_params_e822 { extern const struct ice_cgu_pll_params_e822 e822_cgu_params[NUM_ICE_TIME_REF_FREQ]; +#define E810C_QSFP_C827_0_HANDLE 2 +#define E810C_QSFP_C827_1_HANDLE 3 + /* Table of constants related to possible TIME_REF sources */ extern const struct ice_time_ref_info_e822 e822_time_ref[NUM_ICE_TIME_REF_FREQ]; -- cgit From 5708155d902dc881dff7cb3b48098b45ea0847da Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Thu, 13 Jul 2023 15:21:24 +0200 Subject: ice: add FW load wait As some cards load FW from external sources, we have to wait to be sure that FW is ready before setting link up. Add check and wait for FW readiness Signed-off-by: Jan Sokolowski Reviewed-by: Przemek Kitszel Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 2 ++ drivers/net/ethernet/intel/ice/ice_main.c | 37 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index a92dc9a16035..fb590b4c1053 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -335,6 +335,8 @@ #define VP_MDET_TX_TCLAN_VALID_M BIT(0) #define VP_MDET_TX_TDPU(_VF) (0x00040000 + ((_VF) * 4)) #define VP_MDET_TX_TDPU_VALID_M BIT(0) +#define GL_MNG_FWSM 0x000B6134 +#define GL_MNG_FWSM_FW_LOADING_M BIT(30) #define GLNVM_FLA 0x000B6108 #define GLNVM_FLA_LOCKED_M BIT(6) #define GLNVM_GENS 0x000B6100 diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 2e80d5cd9f56..0f04347eda39 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4520,6 +4520,31 @@ static void ice_deinit_eth(struct ice_pf *pf) ice_decfg_netdev(vsi); } +/** + * ice_wait_for_fw - wait for full FW readiness + * @hw: pointer to the hardware structure + * @timeout: milliseconds that can elapse before timing out + */ +static int ice_wait_for_fw(struct ice_hw *hw, u32 timeout) +{ + int fw_loading; + u32 elapsed = 0; + + while (elapsed <= timeout) { + fw_loading = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_LOADING_M; + + /* firmware was not yet loaded, we have to wait more */ + if (fw_loading) { + elapsed += 100; + msleep(100); + continue; + } + return 0; + } + + return -ETIMEDOUT; +} + static int ice_init_dev(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); @@ -4532,6 +4557,18 @@ static int ice_init_dev(struct ice_pf *pf) return err; } + /* Some cards require longer initialization times + * due to necessity of loading FW from an external source. + * This can take even half a minute. + */ + if (ice_is_pf_c827(hw)) { + err = ice_wait_for_fw(hw, 30000); + if (err) { + dev_err(dev, "ice_wait_for_fw timed out"); + return err; + } + } + ice_init_feature_support(pf); ice_request_fw(pf); -- cgit From b6143c9b073fb321d948b6647065748337918dd8 Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Wed, 7 Jun 2023 09:09:57 -0400 Subject: ice: clean up __ice_aq_get_set_rss_lut() Refactor __ice_aq_get_set_rss_lut() to improve reader experience and limit misuse scenarios (undesired LUT size for given LUT type). Allow only 3 RSS LUT type+size variants: PF LUT sized 2048, GLOBAL LUT sized 512, and VSI LUT sized 64, which were used on default flows prior to this commit. Prior to the change, code was mixing the meaning of @params->lut_size and @params->lut_type, flag assigning logic was cryptic, while long defines made everything harder to follow. Fix that by extracting some code out to separate helpers. Drop some of "shift by 0" statements that originated from Intel's internal HW documentation. Drop some redundant VSI masks (since ice_is_vsi_valid() gives "valid" for up to 0x300 VSIs). After sweeping all the defines out of struct ice_aqc_get_set_rss_lut, it fits into 7 lines. Finally apply some cleanup to the callsite (use of the new enums, tmp var for lengthy bit extraction). Note that flags for 128 and 64 sized VSI LUT are the same, and 64 is used everywhere in the code (updated to new enum here), it just happened that there was 128 in flag name. __ice_aq_get_set_rss_key() uses the same VSI valid bit, make constant common for it and __ice_aq_get_set_rss_lut(). Signed-off-by: Przemek Kitszel Reviewed-by: Simon Horman Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 53 +++++---- drivers/net/ethernet/intel/ice/ice_common.c | 143 ++++++++++-------------- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 1 - drivers/net/ethernet/intel/ice/ice_lib.c | 20 ++-- drivers/net/ethernet/intel/ice/ice_type.h | 9 +- drivers/net/ethernet/intel/ice/ice_virtchnl.c | 6 +- 6 files changed, 99 insertions(+), 133 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 1ad92f95d6bd..29f7a9852aec 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1794,11 +1794,10 @@ struct ice_aqc_lldp_filter_ctrl { u8 reserved2[12]; }; +#define ICE_AQC_RSS_VSI_VALID BIT(15) + /* Get/Set RSS key (indirect 0x0B04/0x0B02) */ struct ice_aqc_get_set_rss_key { -#define ICE_AQC_GSET_RSS_KEY_VSI_VALID BIT(15) -#define ICE_AQC_GSET_RSS_KEY_VSI_ID_S 0 -#define ICE_AQC_GSET_RSS_KEY_VSI_ID_M (0x3FF << ICE_AQC_GSET_RSS_KEY_VSI_ID_S) __le16 vsi_id; u8 reserved[6]; __le32 addr_high; @@ -1816,35 +1815,33 @@ struct ice_aqc_get_set_rss_keys { u8 extended_hash_key[ICE_AQC_GET_SET_RSS_KEY_DATA_HASH_KEY_SIZE]; }; -/* Get/Set RSS LUT (indirect 0x0B05/0x0B03) */ -struct ice_aqc_get_set_rss_lut { -#define ICE_AQC_GSET_RSS_LUT_VSI_VALID BIT(15) -#define ICE_AQC_GSET_RSS_LUT_VSI_ID_S 0 -#define ICE_AQC_GSET_RSS_LUT_VSI_ID_M (0x3FF << ICE_AQC_GSET_RSS_LUT_VSI_ID_S) - __le16 vsi_id; -#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S 0 -#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M \ - (0x3 << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) - -#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI 0 -#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF 1 -#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL 2 +enum ice_lut_type { + ICE_LUT_VSI = 0, + ICE_LUT_PF = 1, + ICE_LUT_GLOBAL = 2, +}; -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S 2 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M \ - (0x3 << ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) +enum ice_lut_size { + ICE_LUT_VSI_SIZE = 64, + ICE_LUT_GLOBAL_SIZE = 512, + ICE_LUT_PF_SIZE = 2048, +}; -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128 128 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG 0 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512 512 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG 1 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K 2048 -#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG 2 +/* enum ice_aqc_lut_flags combines constants used to fill + * &ice_aqc_get_set_rss_lut ::flags, which is an amalgamation of global LUT ID, + * LUT size and LUT type, last of which does not need neither shift nor mask. + */ +enum ice_aqc_lut_flags { + ICE_AQC_LUT_SIZE_SMALL = 0, /* size = 64 or 128 */ + ICE_AQC_LUT_SIZE_512 = BIT(2), + ICE_AQC_LUT_SIZE_2K = BIT(3), -#define ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S 4 -#define ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M \ - (0xF << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) + ICE_AQC_LUT_GLOBAL_IDX = GENMASK(7, 4), +}; +/* Get/Set RSS LUT (indirect 0x0B05/0x0B03) */ +struct ice_aqc_get_set_rss_lut { + __le16 vsi_id; __le16 flags; __le32 reserved; __le32 addr_high; diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index ce3f0f2b0e35..a86255b529a0 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -3939,6 +3939,34 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, return status; } +static enum ice_lut_size ice_lut_type_to_size(enum ice_lut_type type) +{ + switch (type) { + case ICE_LUT_VSI: + return ICE_LUT_VSI_SIZE; + case ICE_LUT_GLOBAL: + return ICE_LUT_GLOBAL_SIZE; + case ICE_LUT_PF: + return ICE_LUT_PF_SIZE; + } + WARN_ONCE(1, "incorrect type passed"); + return ICE_LUT_VSI_SIZE; +} + +static enum ice_aqc_lut_flags ice_lut_size_to_flag(enum ice_lut_size size) +{ + switch (size) { + case ICE_LUT_VSI_SIZE: + return ICE_AQC_LUT_SIZE_SMALL; + case ICE_LUT_GLOBAL_SIZE: + return ICE_AQC_LUT_SIZE_512; + case ICE_LUT_PF_SIZE: + return ICE_AQC_LUT_SIZE_2K; + } + WARN_ONCE(1, "incorrect size passed"); + return 0; +} + /** * __ice_aq_get_set_rss_lut * @hw: pointer to the hardware structure @@ -3948,95 +3976,44 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr, * Internal function to get (0x0B05) or set (0x0B03) RSS look up table */ static int -__ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set) -{ - u16 flags = 0, vsi_id, lut_type, lut_size, glob_lut_idx, vsi_handle; - struct ice_aqc_get_set_rss_lut *cmd_resp; +__ice_aq_get_set_rss_lut(struct ice_hw *hw, + struct ice_aq_get_set_rss_lut_params *params, bool set) +{ + u16 opcode, vsi_id, vsi_handle = params->vsi_handle, glob_lut_idx = 0; + enum ice_lut_type lut_type = params->lut_type; + struct ice_aqc_get_set_rss_lut *desc_params; + enum ice_aqc_lut_flags flags; + enum ice_lut_size lut_size; struct ice_aq_desc desc; - int status; - u8 *lut; + u8 *lut = params->lut; - if (!params) - return -EINVAL; - - vsi_handle = params->vsi_handle; - lut = params->lut; - if (!ice_is_vsi_valid(hw, vsi_handle) || !lut) + if (!lut || !ice_is_vsi_valid(hw, vsi_handle)) return -EINVAL; - lut_size = params->lut_size; - lut_type = params->lut_type; - glob_lut_idx = params->global_lut_id; - vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); - - cmd_resp = &desc.params.get_set_rss_lut; + lut_size = ice_lut_type_to_size(lut_type); + if (lut_size > params->lut_size) + return -EINVAL; + else if (set && lut_size != params->lut_size) + return -EINVAL; - if (set) { - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut); + opcode = set ? ice_aqc_opc_set_rss_lut : ice_aqc_opc_get_rss_lut; + ice_fill_dflt_direct_cmd_desc(&desc, opcode); + if (set) desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - } else { - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut); - } - cmd_resp->vsi_id = cpu_to_le16(((vsi_id << - ICE_AQC_GSET_RSS_LUT_VSI_ID_S) & - ICE_AQC_GSET_RSS_LUT_VSI_ID_M) | - ICE_AQC_GSET_RSS_LUT_VSI_VALID); - - switch (lut_type) { - case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI: - case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF: - case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL: - flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) & - ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M); - break; - default: - status = -EINVAL; - goto ice_aq_get_set_rss_lut_exit; - } + desc_params = &desc.params.get_set_rss_lut; + vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); + desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID); - if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) { - flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) & - ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M); + if (lut_type == ICE_LUT_GLOBAL) + glob_lut_idx = FIELD_PREP(ICE_AQC_LUT_GLOBAL_IDX, + params->global_lut_id); - if (!set) - goto ice_aq_get_set_rss_lut_send; - } else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { - if (!set) - goto ice_aq_get_set_rss_lut_send; - } else { - goto ice_aq_get_set_rss_lut_send; - } + flags = lut_type | glob_lut_idx | ice_lut_size_to_flag(lut_size); + desc_params->flags = cpu_to_le16(flags); - /* LUT size is only valid for Global and PF table types */ - switch (lut_size) { - case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128: - break; - case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512: - flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG << - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; - break; - case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K: - if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { - flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG << - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; - break; - } - fallthrough; - default: - status = -EINVAL; - goto ice_aq_get_set_rss_lut_exit; - } - -ice_aq_get_set_rss_lut_send: - cmd_resp->flags = cpu_to_le16(flags); - status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL); - -ice_aq_get_set_rss_lut_exit: - return status; + return ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL); } /** @@ -4078,12 +4055,10 @@ static int __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id, struct ice_aqc_get_set_rss_keys *key, bool set) { - struct ice_aqc_get_set_rss_key *cmd_resp; + struct ice_aqc_get_set_rss_key *desc_params; u16 key_size = sizeof(*key); struct ice_aq_desc desc; - cmd_resp = &desc.params.get_set_rss_key; - if (set) { ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key); desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); @@ -4091,10 +4066,8 @@ __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id, ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key); } - cmd_resp->vsi_id = cpu_to_le16(((vsi_id << - ICE_AQC_GSET_RSS_KEY_VSI_ID_S) & - ICE_AQC_GSET_RSS_KEY_VSI_ID_M) | - ICE_AQC_GSET_RSS_KEY_VSI_VALID); + desc_params = &desc.params.get_set_rss_key; + desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID); return ice_aq_send_cmd(hw, &desc, key, key_size, NULL); } diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index fb590b4c1053..531cc2194741 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -491,7 +491,6 @@ #define VSIQF_FD_CNT_FD_BCNT_M ICE_M(0x3FFF, 16) #define VSIQF_FD_SIZE(_VSI) (0x00462000 + ((_VSI) * 4)) #define VSIQF_HKEY_MAX_INDEX 12 -#define VSIQF_HLUT_MAX_INDEX 15 #define PFPM_APM 0x000B8080 #define PFPM_APM_APME_M BIT(0) #define PFPM_WUFC 0x0009DC00 diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 077f2e91ae1a..927518fcad51 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -907,6 +907,7 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi) { struct ice_hw_common_caps *cap; struct ice_pf *pf = vsi->back; + u16 max_rss_size; if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { vsi->rss_size = 1; @@ -914,32 +915,31 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi) } cap = &pf->hw.func_caps.common_cap; + max_rss_size = BIT(cap->rss_table_entry_width); switch (vsi->type) { case ICE_VSI_CHNL: case ICE_VSI_PF: /* PF VSI will inherit RSS instance of PF */ vsi->rss_table_size = (u16)cap->rss_table_size; if (vsi->type == ICE_VSI_CHNL) - vsi->rss_size = min_t(u16, vsi->num_rxq, - BIT(cap->rss_table_entry_width)); + vsi->rss_size = min_t(u16, vsi->num_rxq, max_rss_size); else vsi->rss_size = min_t(u16, num_online_cpus(), - BIT(cap->rss_table_entry_width)); - vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; + max_rss_size); + vsi->rss_lut_type = ICE_LUT_PF; break; case ICE_VSI_SWITCHDEV_CTRL: - vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; - vsi->rss_size = min_t(u16, num_online_cpus(), - BIT(cap->rss_table_entry_width)); - vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; + vsi->rss_table_size = ICE_LUT_VSI_SIZE; + vsi->rss_size = min_t(u16, num_online_cpus(), max_rss_size); + vsi->rss_lut_type = ICE_LUT_VSI; break; case ICE_VSI_VF: /* VF VSI will get a small RSS table. * For VSI_LUT, LUT size should be set to 64 bytes. */ - vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; + vsi->rss_table_size = ICE_LUT_VSI_SIZE; vsi->rss_size = ICE_MAX_RSS_QS_PER_VF; - vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; + vsi->rss_lut_type = ICE_LUT_VSI; break; case ICE_VSI_LB: break; diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index e82f38c2a940..5e353b0cbe6f 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -1040,10 +1040,10 @@ enum ice_sw_fwd_act_type { }; struct ice_aq_get_set_rss_lut_params { - u16 vsi_handle; /* software VSI handle */ - u16 lut_size; /* size of the LUT buffer */ - u8 lut_type; /* type of the LUT (i.e. VSI, PF, Global) */ u8 *lut; /* input RSS LUT for set and output RSS LUT for get */ + enum ice_lut_size lut_size; /* size of the LUT buffer */ + enum ice_lut_type lut_type; /* type of the LUT (i.e. VSI, PF, Global) */ + u16 vsi_handle; /* software VSI handle */ u8 global_lut_id; /* only valid when lut_type is global */ }; @@ -1145,9 +1145,6 @@ struct ice_aq_get_set_rss_lut_params { #define ICE_SR_WORDS_IN_1KB 512 -/* Hash redirection LUT for VSI - maximum array size */ -#define ICE_VSIQF_HLUT_ARRAY_SIZE ((VSIQF_HLUT_MAX_INDEX + 1) * 4) - /* AQ API version for LLDP_FILTER_CONTROL */ #define ICE_FW_API_LLDP_FLTR_MAJ 1 #define ICE_FW_API_LLDP_FLTR_MIN 7 diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 625da88e7965..85d996531502 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -500,7 +500,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg) vfres->num_queue_pairs = vsi->num_txq; vfres->max_vectors = vf->pf->vfs.num_msix_per; vfres->rss_key_size = ICE_VSIQF_HKEY_ARRAY_SIZE; - vfres->rss_lut_size = ICE_VSIQF_HLUT_ARRAY_SIZE; + vfres->rss_lut_size = ICE_LUT_VSI_SIZE; vfres->max_mtu = ice_vc_get_max_frame_size(vf); vfres->vsi_res[0].vsi_id = vf->lan_vsi_num; @@ -962,7 +962,7 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg) goto error_param; } - if (vrl->lut_entries != ICE_VSIQF_HLUT_ARRAY_SIZE) { + if (vrl->lut_entries != ICE_LUT_VSI_SIZE) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; } @@ -978,7 +978,7 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg) goto error_param; } - if (ice_set_rss_lut(vsi, vrl->lut, ICE_VSIQF_HLUT_ARRAY_SIZE)) + if (ice_set_rss_lut(vsi, vrl->lut, ICE_LUT_VSI_SIZE)) v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; error_param: return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT, v_ret, -- cgit From a9ca9f9ceff382b58b488248f0c0da9e157f5d06 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Fri, 4 Aug 2023 20:05:24 +0200 Subject: page_pool: split types and declarations from page_pool.h Split types and pure function declarations from page_pool.h and add them in page_page/types.h, so that C sources can include page_pool.h and headers should generally only include page_pool/types.h as suggested by jakub. Rename page_pool.h to page_pool/helpers.h to have both in one place. Signed-off-by: Yunsheng Lin Suggested-by: Jakub Kicinski Signed-off-by: Alexander Lobakin Reviewed-by: Alexander Duyck Link: https://lore.kernel.org/r/20230804180529.2483231-2-aleksander.lobakin@intel.com [Jakub: change microsoft/mana, fix kdoc paths in Documentation] Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 2 +- drivers/net/ethernet/engleder/tsnep_main.c | 1 + drivers/net/ethernet/freescale/fec_main.c | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +- drivers/net/ethernet/marvell/mvneta.c | 2 +- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 + drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 1 + drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 1 + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en/params.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/en/trap.c | 1 - drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | 2 +- drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c | 1 + drivers/net/ethernet/microchip/lan966x/lan966x_main.h | 2 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 1 + drivers/net/ethernet/socionext/netsec.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 + drivers/net/ethernet/ti/cpsw.c | 2 +- drivers/net/ethernet/ti/cpsw_new.c | 2 +- drivers/net/ethernet/ti/cpsw_priv.c | 2 +- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 2 +- drivers/net/veth.c | 2 +- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 - drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/xen-netfront.c | 2 +- 33 files changed, 31 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6a643aae7802..eb168ca983b7 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index 2ce46d7affe4..96f5ca778c67 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "bnxt_hsi.h" #include "bnxt.h" #include "bnxt_xdp.h" diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c index 079f9f6ae21a..f61bd89734c5 100644 --- a/drivers/net/ethernet/engleder/tsnep_main.c +++ b/drivers/net/ethernet/engleder/tsnep_main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define TSNEP_RX_OFFSET (max(NET_SKB_PAD, XDP_PACKET_HEADROOM) + NET_IP_ALIGN) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 43f14cec91e9..3bd0bf03aedb 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9f6890059666..e5e37a33fd81 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 88af34bbee34..acd756b0c7c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include "hnae3.h" diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index acf4f6ba73a6..d483b8c00ec0 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 11e603686a27..e809f91c08fb 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 9e1b596c8f08..eb74ccddb440 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 8cdd92dd9762..8336cea16aff 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -7,6 +7,7 @@ #include #include +#include #include #include diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 61f62a6ec662..70b9065f7d10 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "otx2_reg.h" #include "otx2_common.h" diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 1b89f800f6df..fe05c9020269 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "mtk_eth_soc.h" #include "mtk_wed.h" diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 80d17729e557..4a2470fbad2c 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include "mtk_ppe.h" diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 5ce28ff7685f..e097f336e1c4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -6,6 +6,7 @@ #include "en/port.h" #include "en_accel/en_accel.h" #include "en_accel/ipsec.h" +#include #include static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c index 201ac7dd338f..698647cc8c0f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2020 Mellanox Technologies */ -#include #include "en/txrx.h" #include "en/params.h" #include "en/trap.h" diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 40589cebb773..12f56d0db0af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -35,6 +35,7 @@ #include "en/xdp.h" #include "en/params.h" #include +#include int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 1c820119e438..c8ec6467d4d1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include "eswitch.h" diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index f7bb5f4aaaca..3fd11b0761e0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 4d77055abd4b..07b84d668fcc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -38,7 +38,7 @@ #include "en/port.h" #ifdef CONFIG_PAGE_POOL_STATS -#include +#include #endif static unsigned int stats_grps_num(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c index bd72fbc2220f..3960534ac2ad 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -2,6 +2,7 @@ #include #include +#include #include "lan966x_main.h" diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index aebc9154693a..caa9e0533c96 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index a08023c57e25..31e2f2c74e15 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -11,6 +11,7 @@ #include #include +#include #include #include diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 0dcd6a568b06..f358ea003193 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #define NETSEC_REG_SOFT_RST 0x104 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index a6d034968654..3401e888a9f6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 99aa5360b3ff..fcab363d8dfa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include "stmmac_ptp.h" diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index f9cd566d1c9b..ca4d4548f85e 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c index c61e4e44a78f..0e4f526b1753 100644 --- a/drivers/net/ethernet/ti/cpsw_new.c +++ b/drivers/net/ethernet/ti/cpsw_new.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c index ae52cdbcf8cc..0ec85635dfd6 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.c +++ b/drivers/net/ethernet/ti/cpsw_priv.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 2c3f08be8c37..e04d4a5eed7b 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 614f3e3efab0..953f6d8f8db0 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #define DRV_NAME "veth" #define DRV_VERSION "1.0" diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index c0ff36a98bed..d158320bc15d 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -4,7 +4,6 @@ */ #include #include -#include #include "mt76.h" #define CHAN2G(_idx, _freq) { \ diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 878087257ea7..e8757865a3d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "util.h" #include "testmode.h" diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 47d54d8ea59d..ad29f370034e 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include -- cgit From aa07a0f421b599c492d2848ab150b0293b487c2b Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Fri, 4 Aug 2023 10:29:34 +0530 Subject: octeontx2-af: Code restructure to handle TC outer VLAN offload Moved the TC outer VLAN offload support to a separate function. This change is done to handle all VLAN related changes cleanly from a dedicated function. Signed-off-by: Suman Ghosh Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804045935.3010554-2-sumang@marvell.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 93 ++++++++++++---------- 1 file changed, 53 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 4bb511e3cbe5..c535e8170efc 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -439,6 +439,55 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, return 0; } +static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec, + struct flow_msg *flow_mask, struct flow_rule *rule, + struct npc_install_flow_req *req, bool is_inner) +{ + struct flow_match_vlan match; + u16 vlan_tci, vlan_tci_mask; + + if (is_inner) + return -EOPNOTSUPP; + + flow_rule_match_vlan(rule, &match); + if (ntohs(match.key->vlan_tpid) != ETH_P_8021Q) { + netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n", + ntohs(match.key->vlan_tpid)); + return -EOPNOTSUPP; + } + + if (!match.mask->vlan_id) { + struct flow_action_entry *act; + int i; + + flow_action_for_each(i, act, &rule->action) { + if (act->id == FLOW_ACTION_DROP) { + netdev_err(nic->netdev, + "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n", + ntohs(match.key->vlan_tpid), match.key->vlan_id); + return -EOPNOTSUPP; + } + } + } + + if (match.mask->vlan_id || + match.mask->vlan_dei || + match.mask->vlan_priority) { + vlan_tci = match.key->vlan_id | + match.key->vlan_dei << 12 | + match.key->vlan_priority << 13; + + vlan_tci_mask = match.mask->vlan_id | + match.mask->vlan_dei << 12 | + match.mask->vlan_priority << 13; + flow_spec->vlan_tci = htons(vlan_tci); + flow_mask->vlan_tci = htons(vlan_tci_mask); + req->features |= BIT_ULL(NPC_OUTER_VID); + } + + return 0; +} + static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, struct flow_cls_offload *f, struct npc_install_flow_req *req) @@ -591,47 +640,11 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_match_vlan match; - u16 vlan_tci, vlan_tci_mask; - - flow_rule_match_vlan(rule, &match); - - if (ntohs(match.key->vlan_tpid) != ETH_P_8021Q) { - netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n", - ntohs(match.key->vlan_tpid)); - return -EOPNOTSUPP; - } - - if (!match.mask->vlan_id) { - struct flow_action_entry *act; - int i; - - flow_action_for_each(i, act, &rule->action) { - if (act->id == FLOW_ACTION_DROP) { - netdev_err(nic->netdev, - "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n", - ntohs(match.key->vlan_tpid), - match.key->vlan_id); - return -EOPNOTSUPP; - } - } - } + int ret; - if (match.mask->vlan_id || - match.mask->vlan_dei || - match.mask->vlan_priority) { - vlan_tci = match.key->vlan_id | - match.key->vlan_dei << 12 | - match.key->vlan_priority << 13; - - vlan_tci_mask = match.mask->vlan_id | - match.mask->vlan_dei << 12 | - match.mask->vlan_priority << 13; - - flow_spec->vlan_tci = htons(vlan_tci); - flow_mask->vlan_tci = htons(vlan_tci_mask); - req->features |= BIT_ULL(NPC_OUTER_VID); - } + ret = otx2_tc_process_vlan(nic, flow_spec, flow_mask, rule, req, false); + if (ret) + return ret; } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { -- cgit From 21e748354ec246c9a1a83193cb3f82c05a233b8d Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Fri, 4 Aug 2023 10:29:35 +0530 Subject: octeontx2-af: TC flower offload support for inner VLAN Extend the current TC flower offload support to enable filters matching inner VLAN, and support offload of those filters to hardware. Signed-off-by: Suman Ghosh Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804045935.3010554-3-sumang@marvell.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 1 + drivers/net/ethernet/marvell/octeontx2/af/npc.h | 3 +++ .../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 5 ++++ .../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 13 ++++++++++ .../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 28 +++++++++++++++++----- 5 files changed, 44 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index a8f3c8faf8af..e2f2b2179eef 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1465,6 +1465,7 @@ struct flow_msg { u8 ip_flag; u8 next_header; }; + __be16 vlan_itci; }; struct npc_install_flow_req { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h index 534f20c0c5df..de9fbd98dfb7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h @@ -184,6 +184,7 @@ enum key_fields { NPC_VLAN_ETYPE_CTAG, /* 0x8100 */ NPC_VLAN_ETYPE_STAG, /* 0x88A8 */ NPC_OUTER_VID, + NPC_INNER_VID, NPC_TOS, NPC_IPFRAG_IPV4, NPC_SIP_IPV4, @@ -230,6 +231,8 @@ enum key_fields { NPC_VLAN_TAG1, /* outer vlan tci for double tagged frame */ NPC_VLAN_TAG2, + /* inner vlan tci for double tagged frame */ + NPC_VLAN_TAG3, /* other header fields programmed to extract but not of our interest */ NPC_UNKNOWN, NPC_KEY_FIELDS_MAX, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 7cd33edca365..d30e84803481 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -2787,6 +2787,11 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s, seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.vlan_tci)); break; + case NPC_INNER_VID: + seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_itci)); + seq_printf(s, "mask 0x%x\n", + ntohs(rule->mask.vlan_itci)); + break; case NPC_TOS: seq_printf(s, "%d ", rule->packet.tos); seq_printf(s, "mask 0x%x\n", rule->mask.tos); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index bb715e616fad..5c8f9fc15ff8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -20,6 +20,7 @@ static const char * const npc_flow_names[] = { [NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag", [NPC_VLAN_ETYPE_STAG] = "vlan ether type stag", [NPC_OUTER_VID] = "outer vlan id", + [NPC_INNER_VID] = "inner vlan id", [NPC_TOS] = "tos", [NPC_IPFRAG_IPV4] = "fragmented IPv4 header ", [NPC_SIP_IPV4] = "ipv4 source ip", @@ -328,6 +329,8 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) */ struct npc_key_field *vlan_tag1; struct npc_key_field *vlan_tag2; + /* Inner VLAN TCI for double tagged frames */ + struct npc_key_field *vlan_tag3; u64 *features; u8 start_lid; int i; @@ -350,6 +353,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) etype_tag2 = &key_fields[NPC_ETYPE_TAG2]; vlan_tag1 = &key_fields[NPC_VLAN_TAG1]; vlan_tag2 = &key_fields[NPC_VLAN_TAG2]; + vlan_tag3 = &key_fields[NPC_VLAN_TAG3]; /* if key profile programmed does not extract Ethertype at all */ if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) { @@ -431,6 +435,12 @@ vlan_tci: goto done; } *features |= BIT_ULL(NPC_OUTER_VID); + + /* If key profile extracts inner vlan tci */ + if (vlan_tag3->nr_kws) { + key_fields[NPC_INNER_VID] = *vlan_tag3; + *features |= BIT_ULL(NPC_INNER_VID); + } done: return; } @@ -513,6 +523,7 @@ do { \ NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2); NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2); NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2); + NPC_SCAN_HDR(NPC_VLAN_TAG3, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6, 2); NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6); NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4); @@ -943,6 +954,8 @@ do { \ NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0, ntohs(mask->vlan_tci), 0); + NPC_WRITE_FLOW(NPC_INNER_VID, vlan_itci, ntohs(pkt->vlan_itci), 0, + ntohs(mask->vlan_itci), 0); NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0, mask->next_header, 0); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index c535e8170efc..fab9d85bfb37 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -447,10 +447,11 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec u16 vlan_tci, vlan_tci_mask; if (is_inner) - return -EOPNOTSUPP; + flow_rule_match_cvlan(rule, &match); + else + flow_rule_match_vlan(rule, &match); - flow_rule_match_vlan(rule, &match); - if (ntohs(match.key->vlan_tpid) != ETH_P_8021Q) { + if (!eth_type_vlan(match.key->vlan_tpid)) { netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n", ntohs(match.key->vlan_tpid)); return -EOPNOTSUPP; @@ -480,9 +481,15 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec vlan_tci_mask = match.mask->vlan_id | match.mask->vlan_dei << 12 | match.mask->vlan_priority << 13; - flow_spec->vlan_tci = htons(vlan_tci); - flow_mask->vlan_tci = htons(vlan_tci_mask); - req->features |= BIT_ULL(NPC_OUTER_VID); + if (is_inner) { + flow_spec->vlan_itci = htons(vlan_tci); + flow_mask->vlan_itci = htons(vlan_tci_mask); + req->features |= BIT_ULL(NPC_INNER_VID); + } else { + flow_spec->vlan_tci = htons(vlan_tci); + flow_mask->vlan_tci = htons(vlan_tci_mask); + req->features |= BIT_ULL(NPC_OUTER_VID); + } } return 0; @@ -507,6 +514,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT(FLOW_DISSECTOR_KEY_CVLAN) | BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | @@ -647,6 +655,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, return ret; } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { + int ret; + + ret = otx2_tc_process_vlan(nic, flow_spec, flow_mask, rule, req, true); + if (ret) + return ret; + } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { struct flow_match_ipv4_addrs match; -- cgit From 43265d3fceebf1c32db07b9515eccdf3d10935d5 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Fri, 4 Aug 2023 17:59:45 +0800 Subject: net: dpaa2-eth: Remove redundant initialization owner in dpaa2_eth_driver The fsl_mc_driver_register() will set "THIS_MODULE" to driver.owner when register a fsl_mc_driver driver, so it is redundant initialization to set driver.owner in dpaa2_eth_driver statement. Remove it for clean code. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804095946.99956-2-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index a9676d0dece8..15bab41cee48 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -5087,7 +5087,6 @@ MODULE_DEVICE_TABLE(fslmc, dpaa2_eth_match_id_table); static struct fsl_mc_driver dpaa2_eth_driver = { .driver = { .name = KBUILD_MODNAME, - .owner = THIS_MODULE, }, .probe = dpaa2_eth_probe, .remove = dpaa2_eth_remove, -- cgit From ca46d207c97210c1fce54b2d81e9f7467ce0db5c Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Fri, 4 Aug 2023 17:59:46 +0800 Subject: net: dpaa2-switch: Remove redundant initialization owner in dpaa2_switch_drv The fsl_mc_driver_register() will set "THIS_MODULE" to driver.owner when register a fsl_mc_driver driver, so it is redundant initialization to set driver.owner in dpaa2_switch_drv statement. Remove it for clean code. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804095946.99956-3-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index 21cc4e52425a..97d3151076d5 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -3457,7 +3457,6 @@ MODULE_DEVICE_TABLE(fslmc, dpaa2_switch_match_id_table); static struct fsl_mc_driver dpaa2_switch_drv = { .driver = { .name = KBUILD_MODNAME, - .owner = THIS_MODULE, }, .probe = dpaa2_switch_probe, .remove = dpaa2_switch_remove, -- cgit From ac0955f0ccb0c2e710fd6a8c114a6fe8f3cf4dfd Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 4 Aug 2023 20:52:03 +0800 Subject: ixgbe: Remove unused function declarations Commit dc166e22ede5 ("ixgbe: DCB remove ixgbe_fcoe_getapp routine") leave ixgbe_fcoe_getapp() unused. Commit ffed21bcee7a ("ixgbe: Don't bother clearing buffer memory for descriptor rings") leave ixgbe_unmap_and_free_tx_resource() declaration unused. And commit 3b3bf3b92b31 ("ixgbe: remove unused fcoe.tc field and fcoe_setapp()") removed the ixgbe_fcoe_setapp() implementation. Commit c44ade9ef8ff ("ixgbe: update to latest common code module") declared but never implemented ixgbe_init_ops_generic(). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804125203.30924-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 6 ------ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 63d4e32df029..b6f0376e42f4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -945,8 +945,6 @@ void ixgbe_update_pf_promisc_vlvf(struct ixgbe_adapter *adapter, u32 vid); void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, struct ixgbe_adapter *, struct ixgbe_ring *); -void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *, - struct ixgbe_tx_buffer *); void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16); void ixgbe_write_eitr(struct ixgbe_q_vector *); int ixgbe_poll(struct napi_struct *napi, int budget); @@ -997,10 +995,6 @@ int ixgbe_setup_fcoe_ddp_resources(struct ixgbe_adapter *adapter); void ixgbe_free_fcoe_ddp_resources(struct ixgbe_adapter *adapter); int ixgbe_fcoe_enable(struct net_device *netdev); int ixgbe_fcoe_disable(struct net_device *netdev); -#ifdef CONFIG_IXGBE_DCB -u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter); -u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up); -#endif /* CONFIG_IXGBE_DCB */ int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type); int ixgbe_fcoe_get_hbainfo(struct net_device *netdev, struct netdev_fcoe_hbainfo *info); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 4b531e8ae38a..34761e691d52 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -8,7 +8,6 @@ #include "ixgbe.h" u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); -s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw); -- cgit From 2359fd0b8b1f2441ac2c732fba6bb0228189acbc Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 4 Aug 2023 20:55:25 +0800 Subject: i40e: Remove unused function declarations Commit f62b5060d670 ("i40e: fix mac address checking") left behind i40e_validate_mac_addr() declaration. Also the other declarations are declared but never implemented in commit 56a62fc86895 ("i40e: init code and hardware support"). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230804125525.20244-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index fe845987d99a..3eeee224f1fb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -18,7 +18,6 @@ /* adminq functions */ int i40e_init_adminq(struct i40e_hw *hw); void i40e_shutdown_adminq(struct i40e_hw *hw); -void i40e_adminq_init_ring_data(struct i40e_hw *hw); int i40e_clean_arq_element(struct i40e_hw *hw, struct i40e_arq_event_info *e, u16 *events_pending); @@ -51,7 +50,6 @@ i40e_asq_send_command_atomic_v2(struct i40e_hw *hw, void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, void *buffer, u16 buf_len); -void i40e_idle_aq(struct i40e_hw *hw); bool i40e_check_asq_alive(struct i40e_hw *hw); int i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading); const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err); @@ -117,9 +115,6 @@ int i40e_aq_set_link_restart_an(struct i40e_hw *hw, int i40e_aq_get_link_info(struct i40e_hw *hw, bool enable_lse, struct i40e_link_status *link, struct i40e_asq_cmd_details *cmd_details); -int i40e_aq_set_local_advt_reg(struct i40e_hw *hw, - u64 advt_reg, - struct i40e_asq_cmd_details *cmd_details); int i40e_aq_send_driver_version(struct i40e_hw *hw, struct i40e_driver_version *dv, struct i40e_asq_cmd_details *cmd_details); @@ -269,9 +264,6 @@ int i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); int i40e_aq_dcb_updated(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); -int i40e_aq_config_switch_comp_bw_limit(struct i40e_hw *hw, - u16 seid, u16 credit, u8 max_bw, - struct i40e_asq_cmd_details *cmd_details); int i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_vsi_tc_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details); @@ -350,7 +342,6 @@ i40e_aq_configure_partition_bw(struct i40e_hw *hw, int i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr); int i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num, u32 pba_num_size); -int i40e_validate_mac_addr(u8 *mac_addr); void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable); /* prototype for functions used for NVM access */ int i40e_init_nvm(struct i40e_hw *hw); @@ -425,14 +416,6 @@ i40e_virtchnl_link_speed(enum i40e_aq_link_speed link_speed) /* prototype for functions used for SW locks */ /* i40e_common for VF drivers*/ -void i40e_vf_parse_hw_config(struct i40e_hw *hw, - struct virtchnl_vf_resource *msg); -int i40e_vf_reset(struct i40e_hw *hw); -int i40e_aq_send_msg_to_pf(struct i40e_hw *hw, - enum virtchnl_ops v_opcode, - int v_retval, - u8 *msg, u16 msglen, - struct i40e_asq_cmd_details *cmd_details); int i40e_set_filter_control(struct i40e_hw *hw, struct i40e_filter_control_settings *settings); int i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, -- cgit From 6ff0490cd8100c07d0329d475afccaa9656595b9 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 4 Aug 2023 21:00:48 +0800 Subject: net: hns: Remove unused function declaration mac_adjust_link() Commit 511e6bc071db ("net: add Hisilicon Network Subsystem DSAF support") declared but never implemented this, remove it. Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Reviewed-by: Hao Lan Link: https://lore.kernel.org/r/20230804130048.39808-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index e3bb05959ba9..edf0bcf76ac9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -422,7 +422,6 @@ void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param); int hns_mac_init(struct dsaf_device *dsaf_dev); -void mac_adjust_link(struct net_device *net_dev); bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex); void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status); int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, -- cgit From 78d3902795f0d6a688407e032dfad89bc7933886 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 4 Aug 2023 15:30:11 +0200 Subject: net: fs_enet: Remove set but not used variable CC drivers/net/ethernet/freescale/fs_enet/fs_enet-main.o drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c: In function 'fs_enet_interrupt': drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c:321:40: warning: variable 'fpi' set but not used [-Wunused-but-set-variable] Remove that variable. Signed-off-by: Christophe Leroy Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/90b72c1708bb8ba2b7a1a688e8259e428968364d.1691155346.git.christophe.leroy@csgroup.eu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index f9f5b28cc72e..a6dfc8807d3d 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -318,14 +318,12 @@ fs_enet_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct fs_enet_private *fep; - const struct fs_platform_info *fpi; u32 int_events; u32 int_clr_events; int nr, napi_ok; int handled; fep = netdev_priv(dev); - fpi = fep->fpi; nr = 0; while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) { -- cgit From ae9e78a9dc88be8014c3c5116423ce6e58fdbcb8 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 4 Aug 2023 15:30:12 +0200 Subject: net: fs_enet: Fix address space and base types mismatches CHECK drivers/net/ethernet/freescale/fs_enet/mac-fcc.c drivers/net/ethernet/freescale/fs_enet/mac-fcc.c:550:9: warning: cast removes address space '__iomem' of expression drivers/net/ethernet/freescale/fs_enet/mac-fcc.c:550:9: error: subtraction of different types can't work (different address spaces) CC drivers/net/ethernet/freescale/fs_enet/mii-bitbang.o CHECK drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:95:31: warning: incorrect type in argument 1 (different base types) drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:95:31: expected unsigned int [noderef] [usertype] __iomem *p drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:95:31: got restricted __be32 [noderef] [usertype] __iomem *dat ... drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:63:31: warning: incorrect type in argument 1 (different base types) drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:63:31: expected unsigned int [noderef] [usertype] __iomem *p drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c:63:31: got restricted __be32 [noderef] [usertype] __iomem *dir ... Fix those address space and base type mismatches reported by sparse. Signed-off-by: Christophe Leroy Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/25c7965e6aeeb6bbe1b6be5a3c2c7125182fcb02.1691155346.git.christophe.leroy@csgroup.eu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 2 +- drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c index 925428f1b0c8..ce63fd56df89 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c @@ -547,7 +547,7 @@ static void tx_restart(struct net_device *dev) } /* Now update the TBPTR and dirty flag to the current buffer */ W32(ep, fen_genfcc.fcc_tbptr, - (uint) (((void *)recheck_bd - fep->ring_base) + + (uint)(((void __iomem *)recheck_bd - fep->ring_base) + fep->ring_mem_addr)); fep->dirty_tx = recheck_bd; diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 91a69fc2f7c2..f965a2329055 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -29,8 +29,8 @@ struct bb_info { struct mdiobb_ctrl ctrl; - __be32 __iomem *dir; - __be32 __iomem *dat; + u32 __iomem *dir; + u32 __iomem *dat; u32 mdio_msk; u32 mdc_msk; }; -- cgit From 9359a48c65a3c2723d469ba11889c56387e4395a Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 4 Aug 2023 15:30:15 +0200 Subject: net: fs_enet: Remove has_phy field in fs_platform_info struct Since commit 3dd82a1ea724 ("[POWERPC] CPM: Always use new binding.") has_phy field is never set. Remove dead code and remove the field. Signed-off-by: Christophe Leroy Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/bb5264e09e18f0ce8a0dbee399926a59f33cb248.1691155346.git.christophe.leroy@csgroup.eu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c index f609dc112458..cdc89d83cf07 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c @@ -339,11 +339,7 @@ static void restart(struct net_device *dev) static void stop(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; struct fec __iomem *fecp = fep->fec.fecp; - - struct fec_info *feci = dev->phydev->mdio.bus->priv; - int i; if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) @@ -363,16 +359,6 @@ static void stop(struct net_device *dev) FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN); fs_cleanup_bds(dev); - - /* shut down FEC1? that's where the mii bus is */ - if (fpi->has_phy) { - FS(fecp, r_cntrl, fpi->use_rmii ? - FEC_RCNTRL_RMII_MODE : - FEC_RCNTRL_MII_MODE); /* MII/RMII enable */ - FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); - FW(fecp, ievent, FEC_ENET_MII); - FW(fecp, mii_speed, feci->mii_speed); - } } static void napi_clear_event_fs(struct net_device *dev) -- cgit From 7a76918371fe04667528142554a3f26a8879e8ab Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 4 Aug 2023 15:30:17 +0200 Subject: net: fs_enet: Move struct fs_platform_info into fs_enet.h struct fs_platform_info is only used in fs_enet ethernet driver since commit 3dd82a1ea724 ("[POWERPC] CPM: Always use new binding."). Stale prototypes using fs_platform_info were left over in arch/powerpc/sysdev/fsl_soc.c but they are now removed by previous patch. Move struct fs_platform_info into fs_enet.h Signed-off-by: Christophe Leroy Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/f882d6b0b7075d0d8435310634ceaa2cc8e9938f.1691155347.git.christophe.leroy@csgroup.eu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 19 ++++++++++++++++++- drivers/net/ethernet/freescale/fs_enet/mii-fec.c | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h index cb419aef8d1b..d371072fff60 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h @@ -2,6 +2,7 @@ #ifndef FS_ENET_H #define FS_ENET_H +#include #include #include #include @@ -9,7 +10,6 @@ #include #include -#include #include #ifdef CONFIG_CPM1 @@ -118,6 +118,23 @@ struct phy_info { #define ENET_RX_ALIGN 16 #define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1) +struct fs_platform_info { + /* device specific information */ + u32 cp_command; /* CPM page/sblock/mcn */ + + u32 dpram_offset; + + struct device_node *phy_node; + + int rx_ring, tx_ring; /* number of buffers on rx */ + int rx_copybreak; /* limit we copy small frames */ + int napi_weight; /* NAPI weight */ + + int use_rmii; /* use RMII mode */ + + struct clk *clk_per; /* 'per' clock for register access */ +}; + struct fs_enet_private { struct napi_struct napi; struct device *dev; /* pointer back to the device (must be initialized first) */ diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 1910df250c33..a1e777a4b75f 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include -- cgit From 5e6cb39a256dd5a30e657d57e93f2e009f34ec4e Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 4 Aug 2023 15:30:20 +0200 Subject: net: fs_enet: Use cpm_muram_xxx() functions instead of cpm_dpxxx() macros cpm_dpxxx() macros are now always referring to cpm_muram_xxx() functions directly since commit 3dd82a1ea724 ("[POWERPC] CPM: Always use new binding.") Use cpm_muram_xxx() functions directly so that the cpm_dpxxx() macros can be removed in the near future. Signed-off-by: Christophe Leroy Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/2400b3156891adb653dc387fff6393de10cf2b24.1691155347.git.christophe.leroy@csgroup.eu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 2 +- drivers/net/ethernet/freescale/fs_enet/mac-scc.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c index ce63fd56df89..d903a9012db0 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c @@ -105,7 +105,7 @@ static int do_pd_setup(struct fs_enet_private *fep) goto out_ep; fep->fcc.mem = (void __iomem *)cpm2_immr; - fpi->dpram_offset = cpm_dpalloc(128, 32); + fpi->dpram_offset = cpm_muram_alloc(128, 32); if (IS_ERR_VALUE(fpi->dpram_offset)) { ret = fpi->dpram_offset; goto out_fcccp; diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c index 66d40da5cde0..a64cb6270515 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c @@ -133,13 +133,13 @@ static int allocate_bd(struct net_device *dev) struct fs_enet_private *fep = netdev_priv(dev); const struct fs_platform_info *fpi = fep->fpi; - fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) * - sizeof(cbd_t), 8); + fep->ring_mem_addr = cpm_muram_alloc((fpi->tx_ring + fpi->rx_ring) * + sizeof(cbd_t), 8); if (IS_ERR_VALUE(fep->ring_mem_addr)) return -ENOMEM; fep->ring_base = (void __iomem __force*) - cpm_dpram_addr(fep->ring_mem_addr); + cpm_muram_addr(fep->ring_mem_addr); return 0; } @@ -149,7 +149,7 @@ static void free_bd(struct net_device *dev) struct fs_enet_private *fep = netdev_priv(dev); if (fep->ring_base) - cpm_dpfree(fep->ring_mem_addr); + cpm_muram_free(fep->ring_mem_addr); } static void cleanup_data(struct net_device *dev) -- cgit From 8958ef511a01d395234638c68a77a226cf3f541f Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Aug 2023 09:25:52 +0800 Subject: team: add __exit modifier to team_nl_fini() team_nl_fini is only called when the module exits, so add the __exit modifier to it. Signed-off-by: Zhengchao Shao Reviewed-by: Simon Horman Reviewed-by: Hangbin Liu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230807012556.3146071-2-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/team/team.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index bc50fc3f6913..e4fe70a71b40 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2892,7 +2892,7 @@ static int __init team_nl_init(void) return genl_register_family(&team_nl_family); } -static void team_nl_fini(void) +static void __exit team_nl_fini(void) { genl_unregister_family(&team_nl_family); } -- cgit From adac119421c30666623c4849bd93731992a0f123 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Aug 2023 09:25:53 +0800 Subject: team: remove unreferenced header in broadcast and roundrobin files Because linux/errno.h is unreferenced in broadcast and roundrobin files, so remove it. Signed-off-by: Zhengchao Shao Reviewed-by: Hangbin Liu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230807012556.3146071-3-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/team/team_mode_broadcast.c | 1 - drivers/net/team/team_mode_roundrobin.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c index 313a3e2d68bf..61d7d79f0c36 100644 --- a/drivers/net/team/team_mode_broadcast.c +++ b/drivers/net/team/team_mode_broadcast.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c index 3ec63de97ae3..dd405d82c6ac 100644 --- a/drivers/net/team/team_mode_roundrobin.c +++ b/drivers/net/team/team_mode_roundrobin.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include -- cgit From de3ecc4fd8bf201c5cd02dc49687fb1506cebb45 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Aug 2023 09:25:54 +0800 Subject: team: change the init function in the team_option structure to void Because the init function in the team_option structure always returns 0, so change the init function to void and remove redundant code. Signed-off-by: Zhengchao Shao Reviewed-by: Hangbin Liu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230807012556.3146071-4-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/team/team.c | 8 ++------ drivers/net/team/team_mode_activebackup.c | 5 ++--- drivers/net/team/team_mode_loadbalance.c | 15 ++++++--------- 3 files changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index e4fe70a71b40..b88e1c451e07 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -149,7 +149,6 @@ static int __team_option_inst_add(struct team *team, struct team_option *option, struct team_option_inst *opt_inst; unsigned int array_size; unsigned int i; - int err; array_size = option->array_size; if (!array_size) @@ -165,11 +164,8 @@ static int __team_option_inst_add(struct team *team, struct team_option *option, opt_inst->changed = true; opt_inst->removed = false; list_add_tail(&opt_inst->list, &team->option_inst_list); - if (option->init) { - err = option->init(team, &opt_inst->info); - if (err) - return err; - } + if (option->init) + option->init(team, &opt_inst->info); } return 0; diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c index 3147a4fdf8d9..44d604f1c512 100644 --- a/drivers/net/team/team_mode_activebackup.c +++ b/drivers/net/team/team_mode_activebackup.c @@ -57,11 +57,10 @@ static void ab_port_leave(struct team *team, struct team_port *port) } } -static int ab_active_port_init(struct team *team, - struct team_option_inst_info *info) +static void ab_active_port_init(struct team *team, + struct team_option_inst_info *info) { ab_priv(team)->ap_opt_inst_info = info; - return 0; } static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index 18d99fda997c..50c015cd0682 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -361,14 +361,13 @@ static int lb_tx_method_set(struct team *team, struct team_gsetter_ctx *ctx) return 0; } -static int lb_tx_hash_to_port_mapping_init(struct team *team, - struct team_option_inst_info *info) +static void lb_tx_hash_to_port_mapping_init(struct team *team, + struct team_option_inst_info *info) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = info->array_index; LB_HTPM_OPT_INST_INFO_BY_HASH(lb_priv, hash) = info; - return 0; } static int lb_tx_hash_to_port_mapping_get(struct team *team, @@ -401,14 +400,13 @@ static int lb_tx_hash_to_port_mapping_set(struct team *team, return -ENODEV; } -static int lb_hash_stats_init(struct team *team, - struct team_option_inst_info *info) +static void lb_hash_stats_init(struct team *team, + struct team_option_inst_info *info) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = info->array_index; lb_priv->ex->stats.info[hash].opt_inst_info = info; - return 0; } static int lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) @@ -421,14 +419,13 @@ static int lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) return 0; } -static int lb_port_stats_init(struct team *team, - struct team_option_inst_info *info) +static void lb_port_stats_init(struct team *team, + struct team_option_inst_info *info) { struct team_port *port = info->port; struct lb_port_priv *lb_port_priv = get_lb_port_priv(port); lb_port_priv->stats_info.opt_inst_info = info; - return 0; } static int lb_port_stats_get(struct team *team, struct team_gsetter_ctx *ctx) -- cgit From c3b41f4c7b7ce573f379c0053e3c86e722562659 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Aug 2023 09:25:55 +0800 Subject: team: change the getter function in the team_option structure to void Because the getter function in the team_option structure always returns 0, so change the getter function to void and remove redundant code. Signed-off-by: Zhengchao Shao Reviewed-by: Hangbin Liu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230807012556.3146071-5-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/team/team.c | 52 +++++++++++++------------------ drivers/net/team/team_mode_activebackup.c | 3 +- drivers/net/team/team_mode_loadbalance.c | 24 ++++++-------- 3 files changed, 32 insertions(+), 47 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index b88e1c451e07..8243563a40f0 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -358,7 +358,9 @@ static int team_option_get(struct team *team, { if (!opt_inst->option->getter) return -EOPNOTSUPP; - return opt_inst->option->getter(team, ctx); + + opt_inst->option->getter(team, ctx); + return 0; } static int team_option_set(struct team *team, @@ -1373,10 +1375,9 @@ static int team_port_del(struct team *team, struct net_device *port_dev) * Net device ops *****************/ -static int team_mode_option_get(struct team *team, struct team_gsetter_ctx *ctx) +static void team_mode_option_get(struct team *team, struct team_gsetter_ctx *ctx) { ctx->data.str_val = team->mode->kind; - return 0; } static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) @@ -1384,11 +1385,10 @@ static int team_mode_option_set(struct team *team, struct team_gsetter_ctx *ctx) return team_change_mode(team, ctx->data.str_val); } -static int team_notify_peers_count_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_notify_peers_count_get(struct team *team, + struct team_gsetter_ctx *ctx) { ctx->data.u32_val = team->notify_peers.count; - return 0; } static int team_notify_peers_count_set(struct team *team, @@ -1398,11 +1398,10 @@ static int team_notify_peers_count_set(struct team *team, return 0; } -static int team_notify_peers_interval_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_notify_peers_interval_get(struct team *team, + struct team_gsetter_ctx *ctx) { ctx->data.u32_val = team->notify_peers.interval; - return 0; } static int team_notify_peers_interval_set(struct team *team, @@ -1412,11 +1411,10 @@ static int team_notify_peers_interval_set(struct team *team, return 0; } -static int team_mcast_rejoin_count_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_mcast_rejoin_count_get(struct team *team, + struct team_gsetter_ctx *ctx) { ctx->data.u32_val = team->mcast_rejoin.count; - return 0; } static int team_mcast_rejoin_count_set(struct team *team, @@ -1426,11 +1424,10 @@ static int team_mcast_rejoin_count_set(struct team *team, return 0; } -static int team_mcast_rejoin_interval_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_mcast_rejoin_interval_get(struct team *team, + struct team_gsetter_ctx *ctx) { ctx->data.u32_val = team->mcast_rejoin.interval; - return 0; } static int team_mcast_rejoin_interval_set(struct team *team, @@ -1440,13 +1437,12 @@ static int team_mcast_rejoin_interval_set(struct team *team, return 0; } -static int team_port_en_option_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_port_en_option_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; ctx->data.bool_val = team_port_enabled(port); - return 0; } static int team_port_en_option_set(struct team *team, @@ -1461,13 +1457,12 @@ static int team_port_en_option_set(struct team *team, return 0; } -static int team_user_linkup_option_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_user_linkup_option_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; ctx->data.bool_val = port->user.linkup; - return 0; } static void __team_carrier_check(struct team *team); @@ -1483,13 +1478,12 @@ static int team_user_linkup_option_set(struct team *team, return 0; } -static int team_user_linkup_en_option_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_user_linkup_en_option_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; ctx->data.bool_val = port->user.linkup_enabled; - return 0; } static int team_user_linkup_en_option_set(struct team *team, @@ -1503,13 +1497,12 @@ static int team_user_linkup_en_option_set(struct team *team, return 0; } -static int team_priority_option_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_priority_option_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; ctx->data.s32_val = port->priority; - return 0; } static int team_priority_option_set(struct team *team, @@ -1525,13 +1518,12 @@ static int team_priority_option_set(struct team *team, return 0; } -static int team_queue_id_option_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void team_queue_id_option_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; ctx->data.u32_val = port->queue_id; - return 0; } static int team_queue_id_option_set(struct team *team, diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c index 44d604f1c512..e0f599e2a51d 100644 --- a/drivers/net/team/team_mode_activebackup.c +++ b/drivers/net/team/team_mode_activebackup.c @@ -63,7 +63,7 @@ static void ab_active_port_init(struct team *team, ab_priv(team)->ap_opt_inst_info = info; } -static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) +static void ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) { struct team_port *active_port; @@ -73,7 +73,6 @@ static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) ctx->data.u32_val = active_port->dev->ifindex; else ctx->data.u32_val = 0; - return 0; } static int ab_active_port_set(struct team *team, struct team_gsetter_ctx *ctx) diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index 50c015cd0682..2f1573f253ec 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -242,19 +242,18 @@ drop: return false; } -static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); if (!lb_priv->ex->orig_fprog) { ctx->data.bin_val.len = 0; ctx->data.bin_val.ptr = NULL; - return 0; + return; } ctx->data.bin_val.len = lb_priv->ex->orig_fprog->len * sizeof(struct sock_filter); ctx->data.bin_val.ptr = lb_priv->ex->orig_fprog->filter; - return 0; } static int __fprog_create(struct sock_fprog_kern **pfprog, u32 data_len, @@ -335,7 +334,7 @@ static void lb_bpf_func_free(struct team *team) bpf_prog_destroy(fp); } -static int lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); lb_select_tx_port_func_t *func; @@ -346,7 +345,6 @@ static int lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) name = lb_select_tx_port_get_name(func); BUG_ON(!name); ctx->data.str_val = name; - return 0; } static int lb_tx_method_set(struct team *team, struct team_gsetter_ctx *ctx) @@ -370,8 +368,8 @@ static void lb_tx_hash_to_port_mapping_init(struct team *team, LB_HTPM_OPT_INST_INFO_BY_HASH(lb_priv, hash) = info; } -static int lb_tx_hash_to_port_mapping_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void lb_tx_hash_to_port_mapping_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); struct team_port *port; @@ -379,7 +377,6 @@ static int lb_tx_hash_to_port_mapping_get(struct team *team, port = LB_HTPM_PORT_BY_HASH(lb_priv, hash); ctx->data.u32_val = port ? port->dev->ifindex : 0; - return 0; } static int lb_tx_hash_to_port_mapping_set(struct team *team, @@ -409,14 +406,13 @@ static void lb_hash_stats_init(struct team *team, lb_priv->ex->stats.info[hash].opt_inst_info = info; } -static int lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_hash_stats_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); unsigned char hash = ctx->info->array_index; ctx->data.bin_val.ptr = &lb_priv->ex->stats.info[hash].stats; ctx->data.bin_val.len = sizeof(struct lb_stats); - return 0; } static void lb_port_stats_init(struct team *team, @@ -428,14 +424,13 @@ static void lb_port_stats_init(struct team *team, lb_port_priv->stats_info.opt_inst_info = info; } -static int lb_port_stats_get(struct team *team, struct team_gsetter_ctx *ctx) +static void lb_port_stats_get(struct team *team, struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; struct lb_port_priv *lb_port_priv = get_lb_port_priv(port); ctx->data.bin_val.ptr = &lb_port_priv->stats_info.stats; ctx->data.bin_val.len = sizeof(struct lb_stats); - return 0; } static void __lb_stats_info_refresh_prepare(struct lb_stats_info *s_info) @@ -528,13 +523,12 @@ static void lb_stats_refresh(struct work_struct *work) mutex_unlock(&team->lock); } -static int lb_stats_refresh_interval_get(struct team *team, - struct team_gsetter_ctx *ctx) +static void lb_stats_refresh_interval_get(struct team *team, + struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); ctx->data.u32_val = lb_priv->ex->stats.refresh_interval; - return 0; } static int lb_stats_refresh_interval_set(struct team *team, -- cgit From 7790eaeb688f9ded41d90abafda98f0389008e03 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 7 Aug 2023 09:25:56 +0800 Subject: team: remove unused input parameters in lb_htpm_select_tx_port and lb_hash_select_tx_port The input parameters "lb_priv" and "skb" in lb_htpm_select_tx_port and lb_hash_select_tx_port are unused, so remove them. Signed-off-by: Zhengchao Shao Reviewed-by: Hangbin Liu Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230807012556.3146071-6-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/team/team_mode_loadbalance.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index 2f1573f253ec..00f8989c29c0 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -30,8 +30,6 @@ static rx_handler_result_t lb_receive(struct team *team, struct team_port *port, struct lb_priv; typedef struct team_port *lb_select_tx_port_func_t(struct team *, - struct lb_priv *, - struct sk_buff *, unsigned char); #define LB_TX_HASHTABLE_SIZE 256 /* hash is a char */ @@ -118,8 +116,6 @@ static void lb_tx_hash_to_port_mapping_null_port(struct team *team, /* Basic tx selection based solely by hash */ static struct team_port *lb_hash_select_tx_port(struct team *team, - struct lb_priv *lb_priv, - struct sk_buff *skb, unsigned char hash) { int port_index = team_num_to_port_index(team, hash); @@ -129,17 +125,16 @@ static struct team_port *lb_hash_select_tx_port(struct team *team, /* Hash to port mapping select tx port */ static struct team_port *lb_htpm_select_tx_port(struct team *team, - struct lb_priv *lb_priv, - struct sk_buff *skb, unsigned char hash) { + struct lb_priv *lb_priv = get_lb_priv(team); struct team_port *port; port = rcu_dereference_bh(LB_HTPM_PORT_BY_HASH(lb_priv, hash)); if (likely(port)) return port; /* If no valid port in the table, fall back to simple hash */ - return lb_hash_select_tx_port(team, lb_priv, skb, hash); + return lb_hash_select_tx_port(team, hash); } struct lb_select_tx_port { @@ -229,7 +224,7 @@ static bool lb_transmit(struct team *team, struct sk_buff *skb) hash = lb_get_skb_hash(lb_priv, skb); select_tx_port_func = rcu_dereference_bh(lb_priv->select_tx_port_func); - port = select_tx_port_func(team, lb_priv, skb, hash); + port = select_tx_port_func(team, hash); if (unlikely(!port)) goto drop; if (team_dev_queue_xmit(team, port, skb)) -- cgit From 48d17c517a7af933346bd095e8ccc52b8477b274 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Aug 2023 16:01:53 +0300 Subject: net: bcmasp: Prevent array undereflow in bcmasp_netfilt_get_init() The "loc" value comes from the user and it can be negative leading to an an array underflow when we check "priv->net_filters[loc].claimed". Fix this by changing the type to u32. Fixes: c5d511c49587 ("net: bcmasp: Add support for wake on net filters") Signed-off-by: Dan Carpenter Reviewed-by: Florian Fainelli Reviewed-by: Justin Chen Link: https://lore.kernel.org/r/b3b47b25-01fc-4d9f-a6c3-e037ad4d71d7@moroto.mountain Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 2 +- drivers/net/ethernet/broadcom/asp2/bcmasp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index eb35ced1c8ba..d63d321f3e7b 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c @@ -640,7 +640,7 @@ bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf, * If no more open filters return NULL */ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, - int loc, bool wake_filter, + u32 loc, bool wake_filter, bool init) { struct bcmasp_net_filter *nfilter = NULL; diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h index 6bfcaa7f95a8..5b512f7f5e94 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h @@ -566,7 +566,7 @@ void bcmasp_disable_all_filters(struct bcmasp_intf *intf); void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en); struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, - int loc, bool wake_filter, + u32 loc, bool wake_filter, bool init); bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf, -- cgit From ac1b8c978a7acce25a530b02e7b3f0e74ac931c8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 7 Aug 2023 07:57:19 -0700 Subject: bnxt_en: Fix W=1 warning in bnxt_dcb.c from fortify memcpy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following warning: inlined from ‘bnxt_hwrm_queue_cos2bw_qcfg’ at drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c:165:3, ./include/linux/fortify-string.h:592:4: error: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror] __read_overflow2_field(q_size_field, size); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modify the FW interface defintion of struct hwrm_queue_cos2bw_qcfg_output to use an array of sub struct for the queue1 to queue7 fields. Note that the layout of the queue0 fields are different and these are not part of the array. This makes the code much cleaner by removing the pointer arithmetic for memcpy(). Link: https://lore.kernel.org/netdev/20230727190726.1859515-2-kuba@kernel.org/ Reviewed-by: Andy Gospodarek Signed-off-by: Michael Chan Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20230807145720.159645-2-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c | 15 +- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 322 ++++---------------------- 2 files changed, 52 insertions(+), 285 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index 31f85f3e2364..052a0821153e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -144,7 +144,6 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets) struct hwrm_queue_cos2bw_qcfg_output *resp; struct hwrm_queue_cos2bw_qcfg_input *req; struct bnxt_cos2bw_cfg cos2bw; - void *data; int rc, i; rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_QCFG); @@ -158,13 +157,19 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets) return rc; } - data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); - for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw.cfg)) { + for (i = 0; i < bp->max_tc; i++) { int tc; - memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg)); - if (i == 0) + if (i == 0) { cos2bw.queue_id = resp->queue_id0; + cos2bw.min_bw = resp->queue_id0_min_bw; + cos2bw.max_bw = resp->queue_id0_max_bw; + cos2bw.tsa = resp->queue_id0_tsa_assign; + cos2bw.pri_lvl = resp->queue_id0_pri_lvl; + cos2bw.bw_weight = resp->queue_id0_bw_weight; + } else { + memcpy(&cos2bw.cfg, &resp->cfg[i - 1], sizeof(cos2bw.cfg)); + } tc = bnxt_queue_to_tc(bp, cos2bw.queue_id); if (tc < 0) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index b31de4cf6534..fd38d5dcbc25 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -5739,286 +5739,48 @@ struct hwrm_queue_cos2bw_qcfg_output { #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST 0xffUL u8 queue_id0_pri_lvl; u8 queue_id0_bw_weight; - u8 queue_id1; - __le32 queue_id1_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id1_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id1_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id1_pri_lvl; - u8 queue_id1_bw_weight; - u8 queue_id2; - __le32 queue_id2_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id2_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id2_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id2_pri_lvl; - u8 queue_id2_bw_weight; - u8 queue_id3; - __le32 queue_id3_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id3_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id3_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id3_pri_lvl; - u8 queue_id3_bw_weight; - u8 queue_id4; - __le32 queue_id4_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id4_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id4_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id4_pri_lvl; - u8 queue_id4_bw_weight; - u8 queue_id5; - __le32 queue_id5_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id5_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id5_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id5_pri_lvl; - u8 queue_id5_bw_weight; - u8 queue_id6; - __le32 queue_id6_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id6_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id6_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id6_pri_lvl; - u8 queue_id6_bw_weight; - u8 queue_id7; - __le32 queue_id7_min_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id7_max_bw; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id7_tsa_assign; - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id7_pri_lvl; - u8 queue_id7_bw_weight; + struct { + u8 queue_id; + __le32 queue_id_min_bw; + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_MASK 0xfffffffUL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_SFT 0 + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_SCALE 0x10000000UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_SCALE_BITS (0x0UL << 28) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_SCALE_BYTES (0x1UL << 28) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_SCALE_BYTES + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_SFT 29 + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_INVALID + __le32 queue_id_max_bw; + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_MASK 0xfffffffUL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_SFT 0 + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_SCALE 0x10000000UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_SCALE_BITS (0x0UL << 28) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_SCALE_BYTES (0x1UL << 28) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_SCALE_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_SCALE_BYTES + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_SFT 29 + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_INVALID + u8 queue_id_tsa_assign; + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_TSA_ASSIGN_SP 0x0UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_TSA_ASSIGN_ETS 0x1UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_TSA_ASSIGN_RESERVED_FIRST 0x2UL + #define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID_TSA_ASSIGN_RESERVED_LAST 0xffUL + u8 queue_id_pri_lvl; + u8 queue_id_bw_weight; + } __packed cfg[7]; u8 unused_2[4]; u8 valid; }; -- cgit From 3d5ecada049f4afdad71be09295c4cd0bbf105c3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 7 Aug 2023 07:57:20 -0700 Subject: bnxt_en: Fix W=stringop-overflow warning in bnxt_dcb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following warning: drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c: In function ‘bnxt_hwrm_queue_cos2bw_cfg’: cc1: error: writing 12 bytes into a region of size 1 [-Werror=stringop-overflow ] In file included from drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c:19: drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h:6045:17: note: destination object ‘unused_0’ of size 1 6045 | u8 unused_0; Fix it by modifying struct hwrm_queue_cos2bw_cfg_input to use an array of sub struct similar to the previous patch. This will eliminate the pointer arithmetc to calculate the destination pointer passed to memcpy(). Link: https://lore.kernel.org/netdev/CACKFLinikvXmKcxr4kjWO9TPYxTd2cb5agT1j=w9Qyj5-24s5A@mail.gmail.com/ Signed-off-by: Michael Chan Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20230807145720.159645-3-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c | 11 +- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 322 ++++---------------------- 2 files changed, 49 insertions(+), 284 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index 052a0821153e..63e067038385 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -98,7 +98,6 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets, { struct hwrm_queue_cos2bw_cfg_input *req; struct bnxt_cos2bw_cfg cos2bw; - void *data; int rc, i; rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_CFG); @@ -129,11 +128,15 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets, cpu_to_le32((ets->tc_tx_bw[i] * 100) | BW_VALUE_UNIT_PERCENT1_100); } - data = &req->unused_0 + qidx * (sizeof(cos2bw) - 4); - memcpy(data, &cos2bw.cfg, sizeof(cos2bw) - 4); if (qidx == 0) { req->queue_id0 = cos2bw.queue_id; - req->unused_0 = 0; + req->queue_id0_min_bw = cos2bw.min_bw; + req->queue_id0_max_bw = cos2bw.max_bw; + req->queue_id0_tsa_assign = cos2bw.tsa; + req->queue_id0_pri_lvl = cos2bw.pri_lvl; + req->queue_id0_bw_weight = cos2bw.bw_weight; + } else { + memcpy(&req->cfg[i - 1], &cos2bw.cfg, sizeof(cos2bw.cfg)); } } return hwrm_req_send(bp, req); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index fd38d5dcbc25..f178ed9899a9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -5844,286 +5844,48 @@ struct hwrm_queue_cos2bw_cfg_input { #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST 0xffUL u8 queue_id0_pri_lvl; u8 queue_id0_bw_weight; - u8 queue_id1; - __le32 queue_id1_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id1_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id1_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id1_pri_lvl; - u8 queue_id1_bw_weight; - u8 queue_id2; - __le32 queue_id2_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id2_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id2_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id2_pri_lvl; - u8 queue_id2_bw_weight; - u8 queue_id3; - __le32 queue_id3_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id3_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id3_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id3_pri_lvl; - u8 queue_id3_bw_weight; - u8 queue_id4; - __le32 queue_id4_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id4_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id4_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id4_pri_lvl; - u8 queue_id4_bw_weight; - u8 queue_id5; - __le32 queue_id5_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id5_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id5_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id5_pri_lvl; - u8 queue_id5_bw_weight; - u8 queue_id6; - __le32 queue_id6_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id6_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id6_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id6_pri_lvl; - u8 queue_id6_bw_weight; - u8 queue_id7; - __le32 queue_id7_min_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID - __le32 queue_id7_max_bw; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_MASK 0xfffffffUL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_SFT 0 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_SCALE 0x10000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_SCALE_BITS (0x0UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_SCALE_BYTES (0x1UL << 28) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_SCALE_BYTES - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_SFT 29 - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID - u8 queue_id7_tsa_assign; - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_SP 0x0UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_ETS 0x1UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST 0x2UL - #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST 0xffUL - u8 queue_id7_pri_lvl; - u8 queue_id7_bw_weight; + struct { + u8 queue_id; + __le32 queue_id_min_bw; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_MASK 0xfffffffUL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_SFT 0 + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_SCALE 0x10000000UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_SCALE_BITS (0x0UL << 28) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_SCALE_BYTES (0x1UL << 28) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_SCALE_BYTES + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_SFT 29 + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MIN_BW_BW_VALUE_UNIT_INVALID + __le32 queue_id_max_bw; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_MASK 0xfffffffUL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_SFT 0 + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_SCALE 0x10000000UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_SCALE_BITS (0x0UL << 28) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_SCALE_BYTES (0x1UL << 28) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_SCALE_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_SCALE_BYTES + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_SFT 29 + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_MEGA (0x0UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_KILO (0x2UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_BASE (0x4UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_GIGA (0x6UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_LAST QUEUE_COS2BW_CFG_REQ_QUEUE_ID_MAX_BW_BW_VALUE_UNIT_INVALID + u8 queue_id_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_TSA_ASSIGN_SP 0x0UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_TSA_ASSIGN_ETS 0x1UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_TSA_ASSIGN_RESERVED_FIRST 0x2UL + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID_TSA_ASSIGN_RESERVED_LAST 0xffUL + u8 queue_id_pri_lvl; + u8 queue_id_bw_weight; + } __packed cfg[7]; u8 unused_1[5]; }; -- cgit From f1d152eb66a30aecd19f22ff2676a7cb2584a920 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Mon, 7 Aug 2023 17:13:47 +0800 Subject: rtnetlink: remove redundant checks for nlattr IFLA_BRIDGE_MODE The commit d73ef2d69c0d ("rtnetlink: let rtnl_bridge_setlink checks IFLA_BRIDGE_MODE length") added the nla_len check in rtnl_bridge_setlink, which is the only caller for ndo_bridge_setlink handlers defined in low-level driver codes. Hence, this patch cleanups the redundant checks in each ndo_bridge_setlink handler function. Suggested-by: Hangbin Liu Signed-off-by: Lin Ma Acked-by: Pavan Chebbi Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230807091347.3804523-1-linma@zju.edu.cn Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 --- drivers/net/ethernet/emulex/benet/be_main.c | 3 --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 3 --- 5 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index eb168ca983b7..7be917a8da48 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -13132,9 +13132,6 @@ static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; - if (nla_len(attr) < sizeof(mode)) - return -EINVAL; - mode = nla_get_u16(attr); if (mode == bp->br_mode) break; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 0616b5fe241c..ad862ed7888a 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4986,9 +4986,6 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; - if (nla_len(attr) < sizeof(mode)) - return -EINVAL; - mode = nla_get_u16(attr); if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA) return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 8eb9839a3ca6..dd03b017dfc5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -10042,9 +10042,6 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; - if (nla_len(attr) < sizeof(mode)) - return -EINVAL; - mode = nla_get_u16(attr); status = ixgbe_configure_bridge_mode(adapter, mode); if (status) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index c8ec6467d4d1..ca80c220e4b0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4896,9 +4896,6 @@ static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; - if (nla_len(attr) < sizeof(mode)) - return -EINVAL; - mode = nla_get_u16(attr); if (mode > BRIDGE_MODE_VEPA) return -EINVAL; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index f18c791cf698..de0a5d5ded30 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2108,9 +2108,6 @@ static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; - if (nla_len(attr) < sizeof(mode)) - return -EINVAL; - new_ctrl = nn->dp.ctrl; mode = nla_get_u16(attr); if (mode == BRIDGE_MODE_VEPA) -- cgit From c009b903f8ccfce5844c91f005b0f152a5518526 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 7 Aug 2023 09:32:30 +0900 Subject: net: renesas: rswitch: Add runtime speed change support The latest SoC version can support runtime speed change. So, add detect SoC version by using soc_device_match() and then reconfigure the hardware of this and SerDes if needed. Signed-off-by: Yoshihiro Shimoda Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230807003231.1552062-2-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/renesas/rswitch.c | 27 ++++++++++++++++++++++++--- drivers/net/ethernet/renesas/rswitch.h | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 0ba7fb75d589..fd3668b95834 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "rswitch.h" @@ -1243,7 +1244,6 @@ static void rswitch_adjust_link(struct net_device *ndev) struct rswitch_device *rdev = netdev_priv(ndev); struct phy_device *phydev = ndev->phydev; - /* Current hardware has a restriction not to change speed at runtime */ if (phydev->link != rdev->etha->link) { phy_print_status(phydev); if (phydev->link) @@ -1252,13 +1252,23 @@ static void rswitch_adjust_link(struct net_device *ndev) phy_power_off(rdev->serdes); rdev->etha->link = phydev->link; + + if (!rdev->priv->etha_no_runtime_change && + phydev->speed != rdev->etha->speed) { + rdev->etha->speed = phydev->speed; + + rswitch_etha_hw_init(rdev->etha, rdev->ndev->dev_addr); + phy_set_speed(rdev->serdes, rdev->etha->speed); + } } } static void rswitch_phy_remove_link_mode(struct rswitch_device *rdev, struct phy_device *phydev) { - /* Current hardware has a restriction not to change speed at runtime */ + if (!rdev->priv->etha_no_runtime_change) + return; + switch (rdev->etha->speed) { case SPEED_2500: phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Full_BIT); @@ -1347,7 +1357,8 @@ static int rswitch_ether_port_init_one(struct rswitch_device *rdev) err = rswitch_etha_hw_init(rdev->etha, rdev->ndev->dev_addr); if (err < 0) return err; - rdev->etha->operated = true; + if (rdev->priv->etha_no_runtime_change) + rdev->etha->operated = true; } err = rswitch_mii_register(rdev); @@ -1853,8 +1864,14 @@ err_ts_queue_alloc: return err; } +static const struct soc_device_attribute rswitch_soc_no_speed_change[] = { + { .soc_id = "r8a779f0", .revision = "ES1.0" }, + { /* Sentinel */ } +}; + static int renesas_eth_sw_probe(struct platform_device *pdev) { + const struct soc_device_attribute *attr; struct rswitch_private *priv; struct resource *res; int ret; @@ -1869,6 +1886,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + attr = soc_device_match(rswitch_soc_no_speed_change); + if (attr) + priv->etha_no_runtime_change = true; + priv->ptp_priv = rcar_gen4_ptp_alloc(pdev); if (!priv->ptp_priv) return -ENOMEM; diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index bb9ed971a97c..54f397effbc6 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -1011,6 +1011,7 @@ struct rswitch_private { struct rswitch_etha etha[RSWITCH_NUM_PORTS]; struct rswitch_mfwd mfwd; + bool etha_no_runtime_change; bool gwca_halt; }; -- cgit From 20f8be6b24da814912c09cdb5b3457f0a3ecf505 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 7 Aug 2023 09:32:31 +0900 Subject: net: renesas: rswitch: Add .[gs]et_link_ksettings support Add .[gs]et_link_ksettings support by using phy_ethtool_[gs]et_link_ksettings() functions. Signed-off-by: Yoshihiro Shimoda Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230807003231.1552062-3-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/renesas/rswitch.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index fd3668b95834..6083b1c8e4fb 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -1664,6 +1664,8 @@ static int rswitch_get_ts_info(struct net_device *ndev, struct ethtool_ts_info * static const struct ethtool_ops rswitch_ethtool_ops = { .get_ts_info = rswitch_get_ts_info, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, }; static const struct of_device_id renesas_eth_sw_of_table[] = { -- cgit From 3bf969e88ada7265ed6ef6f4b52a0c7d1d35c0b6 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:05 +0100 Subject: sfc: add MAE table machinery for conntrack table Access to the connection tracking table in EF100 hardware is through a "generic" table mechanism, whereby a firmware call at probe time gives the driver a description of the field widths and offsets, so that the driver can then construct key and response bitstrings at runtime. Probe the NIC for this information and populate the needed metadata into a new meta_ct field of struct efx_tc_state. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mae.c | 250 ++++++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 3 + drivers/net/ethernet/sfc/mcdi.h | 3 + drivers/net/ethernet/sfc/tc.c | 9 +- drivers/net/ethernet/sfc/tc.h | 44 +++++++ 5 files changed, 308 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 0cab508f2f9d..33ae2c852b44 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -227,6 +227,256 @@ void efx_mae_counters_grant_credits(struct work_struct *work) rx_queue->granted_count += credits; } +static int efx_mae_table_get_desc(struct efx_nic *efx, + struct efx_tc_table_desc *desc, + u32 table_id) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(16)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_TABLE_DESCRIPTOR_IN_LEN); + unsigned int offset = 0, i; + size_t outlen; + int rc; + + memset(desc, 0, sizeof(*desc)); + + MCDI_SET_DWORD(inbuf, TABLE_DESCRIPTOR_IN_TABLE_ID, table_id); +more: + MCDI_SET_DWORD(inbuf, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, offset); + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_DESCRIPTOR, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), &outlen); + if (rc) + goto fail; + if (outlen < MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(1)) { + rc = -EIO; + goto fail; + } + if (!offset) { /* first iteration: get metadata */ + desc->type = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_TYPE); + desc->key_width = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_KEY_WIDTH); + desc->resp_width = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_RESP_WIDTH); + desc->n_keys = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS); + desc->n_resps = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS); + desc->n_prios = MCDI_WORD(outbuf, TABLE_DESCRIPTOR_OUT_N_PRIORITIES); + desc->flags = MCDI_BYTE(outbuf, TABLE_DESCRIPTOR_OUT_FLAGS); + rc = -EOPNOTSUPP; + if (desc->flags) + goto fail; + desc->scheme = MCDI_BYTE(outbuf, TABLE_DESCRIPTOR_OUT_SCHEME); + if (desc->scheme) + goto fail; + rc = -ENOMEM; + desc->keys = kcalloc(desc->n_keys, + sizeof(struct efx_tc_table_field_fmt), + GFP_KERNEL); + if (!desc->keys) + goto fail; + desc->resps = kcalloc(desc->n_resps, + sizeof(struct efx_tc_table_field_fmt), + GFP_KERNEL); + if (!desc->resps) + goto fail; + } + /* FW could have returned more than the 16 field_descrs we + * made room for in our outbuf + */ + outlen = min(outlen, sizeof(outbuf)); + for (i = 0; i + offset < desc->n_keys + desc->n_resps; i++) { + struct efx_tc_table_field_fmt *field; + MCDI_DECLARE_STRUCT_PTR(fdesc); + + if (outlen < MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(i + 1)) { + offset += i; + goto more; + } + if (i + offset < desc->n_keys) + field = desc->keys + i + offset; + else + field = desc->resps + (i + offset - desc->n_keys); + fdesc = MCDI_ARRAY_STRUCT_PTR(outbuf, + TABLE_DESCRIPTOR_OUT_FIELDS, i); + field->field_id = MCDI_STRUCT_WORD(fdesc, + TABLE_FIELD_DESCR_FIELD_ID); + field->lbn = MCDI_STRUCT_WORD(fdesc, TABLE_FIELD_DESCR_LBN); + field->width = MCDI_STRUCT_WORD(fdesc, TABLE_FIELD_DESCR_WIDTH); + field->masking = MCDI_STRUCT_BYTE(fdesc, TABLE_FIELD_DESCR_MASK_TYPE); + field->scheme = MCDI_STRUCT_BYTE(fdesc, TABLE_FIELD_DESCR_SCHEME); + } + return 0; + +fail: + kfree(desc->keys); + kfree(desc->resps); + return rc; +} + +static int efx_mae_table_hook_find(u16 n_fields, + struct efx_tc_table_field_fmt *fields, + u16 field_id) +{ + unsigned int i; + + for (i = 0; i < n_fields; i++) { + if (fields[i].field_id == field_id) + return i; + } + return -EPROTO; +} + +#define TABLE_FIND_KEY(_desc, _id) \ + efx_mae_table_hook_find((_desc)->n_keys, (_desc)->keys, _id) +#define TABLE_FIND_RESP(_desc, _id) \ + efx_mae_table_hook_find((_desc)->n_resps, (_desc)->resps, _id) + +#define TABLE_HOOK_KEY(_meta, _name, _mcdi_name) ({ \ + int _rc = TABLE_FIND_KEY(&_meta->desc, TABLE_FIELD_ID_##_mcdi_name); \ + \ + if (_rc > U8_MAX) \ + _rc = -EOPNOTSUPP; \ + if (_rc >= 0) { \ + _meta->keys._name##_idx = _rc; \ + _rc = 0; \ + } \ + _rc; \ +}) +#define TABLE_HOOK_RESP(_meta, _name, _mcdi_name) ({ \ + int _rc = TABLE_FIND_RESP(&_meta->desc, TABLE_FIELD_ID_##_mcdi_name); \ + \ + if (_rc > U8_MAX) \ + _rc = -EOPNOTSUPP; \ + if (_rc >= 0) { \ + _meta->resps._name##_idx = _rc; \ + _rc = 0; \ + } \ + _rc; \ +}) + +static int efx_mae_table_hook_ct(struct efx_nic *efx, + struct efx_tc_table_ct *meta_ct) +{ + int rc; + + rc = TABLE_HOOK_KEY(meta_ct, eth_proto, ETHER_TYPE); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, ip_proto, IP_PROTO); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, src_ip, SRC_IP); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, dst_ip, DST_IP); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, l4_sport, SRC_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, l4_dport, DST_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_KEY(meta_ct, zone, DOMAIN); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, dnat, NAT_DIR); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, nat_ip, NAT_IP); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, l4_natport, NAT_PORT); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, mark, CT_MARK); + if (rc) + return rc; + rc = TABLE_HOOK_RESP(meta_ct, counter_id, COUNTER_ID); + if (rc) + return rc; + meta_ct->hooked = true; + return 0; +} + +static void efx_mae_table_free_desc(struct efx_tc_table_desc *desc) +{ + kfree(desc->keys); + kfree(desc->resps); + memset(desc, 0, sizeof(*desc)); +} + +static bool efx_mae_check_table_exists(struct efx_nic *efx, u32 tbl_req) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_TABLE_LIST_OUT_LEN(16)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_TABLE_LIST_IN_LEN); + u32 tbl_id, tbl_total, tbl_cnt, pos = 0; + size_t outlen, msg_max; + bool ct_tbl = false; + int rc, idx; + + msg_max = sizeof(outbuf); + efx->tc->meta_ct.hooked = false; +more: + memset(outbuf, 0, sizeof(*outbuf)); + MCDI_SET_DWORD(inbuf, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, pos); + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_LIST, inbuf, sizeof(inbuf), outbuf, + msg_max, &outlen); + if (rc) + return false; + + if (outlen < MC_CMD_TABLE_LIST_OUT_LEN(1)) + return false; + + tbl_total = MCDI_DWORD(outbuf, TABLE_LIST_OUT_N_TABLES); + tbl_cnt = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(min(outlen, msg_max)); + + for (idx = 0; idx < tbl_cnt; idx++) { + tbl_id = MCDI_ARRAY_DWORD(outbuf, TABLE_LIST_OUT_TABLE_ID, idx); + if (tbl_id == tbl_req) { + ct_tbl = true; + break; + } + } + + pos += tbl_cnt; + if (!ct_tbl && pos < tbl_total) + goto more; + + return ct_tbl; +} + +int efx_mae_get_tables(struct efx_nic *efx) +{ + int rc; + + efx->tc->meta_ct.hooked = false; + if (efx_mae_check_table_exists(efx, TABLE_ID_CONNTRACK_TABLE)) { + rc = efx_mae_table_get_desc(efx, &efx->tc->meta_ct.desc, + TABLE_ID_CONNTRACK_TABLE); + if (rc) { + pci_info(efx->pci_dev, + "FW does not support conntrack desc rc %d\n", + rc); + return 0; + } + + rc = efx_mae_table_hook_ct(efx, &efx->tc->meta_ct); + if (rc) { + pci_info(efx->pci_dev, + "FW does not support conntrack hook rc %d\n", + rc); + return 0; + } + } else { + pci_info(efx->pci_dev, + "FW does not support conntrack table\n"); + } + return 0; +} + +void efx_mae_free_tables(struct efx_nic *efx) +{ + efx_mae_table_free_desc(&efx->tc->meta_ct.desc); + efx->tc->meta_ct.hooked = false; +} + static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_CAPS_OUT_LEN); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 24abfe509690..afdf738254b2 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -66,6 +66,9 @@ int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue); int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue); void efx_mae_counters_grant_credits(struct work_struct *work); +int efx_mae_get_tables(struct efx_nic *efx); +void efx_mae_free_tables(struct efx_nic *efx); + #define MAE_NUM_FIELDS (MAE_FIELD_ENC_VNET_ID + 1) struct mae_caps { diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 454e9d51a4c2..995a26686fd8 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -221,6 +221,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_BYTE(_buf, _field) \ ((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \ *MCDI_PTR(_buf, _field)) +#define MCDI_STRUCT_BYTE(_buf, _field) \ + ((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 1), \ + *MCDI_STRUCT_PTR(_buf, _field)) #define MCDI_SET_WORD(_buf, _field, _value) do { \ BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2); \ BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \ diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 4dc881159246..4dc979fdc968 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -1658,13 +1658,19 @@ int efx_init_tc(struct efx_nic *efx) if (rc) return rc; rc = efx_tc_configure_fallback_acts_reps(efx); + if (rc) + return rc; + rc = efx_mae_get_tables(efx); if (rc) return rc; efx->tc->up = true; rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx); if (rc) - return rc; + goto out_free; return 0; +out_free: + efx_mae_free_tables(efx); + return rc; } void efx_fini_tc(struct efx_nic *efx) @@ -1680,6 +1686,7 @@ void efx_fini_tc(struct efx_nic *efx) efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf); efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps); efx->tc->up = false; + efx_mae_free_tables(efx); } /* At teardown time, all TC filter rules (and thus all resources they created) diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 1549c3df43bb..27592f10b536 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -143,6 +143,48 @@ enum efx_tc_rule_prios { EFX_TC_PRIO__NUM }; +struct efx_tc_table_field_fmt { + u16 field_id; + u16 lbn; + u16 width; + u8 masking; + u8 scheme; +}; + +struct efx_tc_table_desc { + u16 type; + u16 key_width; + u16 resp_width; + u16 n_keys; + u16 n_resps; + u16 n_prios; + u8 flags; + u8 scheme; + struct efx_tc_table_field_fmt *keys; + struct efx_tc_table_field_fmt *resps; +}; + +struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ + struct efx_tc_table_desc desc; + bool hooked; + struct { /* indices of named fields within @desc.keys */ + u8 eth_proto_idx; + u8 ip_proto_idx; + u8 src_ip_idx; /* either v4 or v6 */ + u8 dst_ip_idx; + u8 l4_sport_idx; + u8 l4_dport_idx; + u8 zone_idx; /* for TABLE_FIELD_ID_DOMAIN */ + } keys; + struct { /* indices of named fields within @desc.resps */ + u8 dnat_idx; + u8 nat_ip_idx; + u8 l4_natport_idx; + u8 mark_idx; + u8 counter_id_idx; + } resps; +}; + /** * struct efx_tc_state - control plane data for TC offload * @@ -155,6 +197,7 @@ enum efx_tc_rule_prios { * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) + * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) @@ -186,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable neigh_ht; + struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; bool flush_counters; -- cgit From c3bb5c6acd4e0104522f6b1a22f7d62e37e8fa02 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:06 +0100 Subject: sfc: functions to register for conntrack zone offload Bind a stub callback to the netfilter flow table. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/Makefile | 2 +- drivers/net/ethernet/sfc/tc.c | 7 ++ drivers/net/ethernet/sfc/tc.h | 2 + drivers/net/ethernet/sfc/tc_conntrack.c | 109 ++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc_conntrack.h | 37 +++++++++++ 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/sfc/tc_conntrack.c create mode 100644 drivers/net/ethernet/sfc/tc_conntrack.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index 16293b58e0a8..8f446b9bd5ee 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -11,7 +11,7 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \ mae.o tc.o tc_bindings.o tc_counters.o \ - tc_encap_actions.o + tc_encap_actions.o tc_conntrack.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 4dc979fdc968..44a6fc30b722 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -15,6 +15,7 @@ #include "tc.h" #include "tc_bindings.h" #include "tc_encap_actions.h" +#include "tc_conntrack.h" #include "mae.h" #include "ef100_rep.h" #include "efx.h" @@ -1747,6 +1748,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = rhashtable_init(&efx->tc->match_action_ht, &efx_tc_match_action_ht_params); if (rc < 0) goto fail_match_action_ht; + rc = efx_tc_init_conntrack(efx); + if (rc < 0) + goto fail_conntrack; efx->tc->reps_filter_uc = -1; efx->tc->reps_filter_mc = -1; INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list); @@ -1759,6 +1763,8 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; +fail_conntrack: + rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); fail_encap_match_ht: @@ -1792,6 +1798,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); + efx_tc_fini_conntrack(efx); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 27592f10b536..fc196eb897af 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -196,6 +196,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX @@ -228,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable ct_zone_ht; struct rhashtable neigh_ht; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c new file mode 100644 index 000000000000..d67302715ec3 --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-only +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include "tc_conntrack.h" +#include "tc.h" +#include "mae.h" + +static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, + void *cb_priv); + +static const struct rhashtable_params efx_tc_ct_zone_ht_params = { + .key_len = offsetof(struct efx_tc_ct_zone, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_ct_zone, linkage), +}; + +static void efx_tc_ct_zone_free(void *ptr, void *arg) +{ + struct efx_tc_ct_zone *zone = ptr; + struct efx_nic *efx = zone->efx; + + netif_err(efx, drv, efx->net_dev, + "tc ct_zone %u still present at teardown, removing\n", + zone->zone); + + nf_flow_table_offload_del_cb(zone->nf_ft, efx_tc_flow_block, zone); + kfree(zone); +} + +int efx_tc_init_conntrack(struct efx_nic *efx) +{ + int rc; + + rc = rhashtable_init(&efx->tc->ct_zone_ht, &efx_tc_ct_zone_ht_params); + if (rc < 0) + return rc; + return 0; +} + +void efx_tc_fini_conntrack(struct efx_nic *efx) +{ + rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); +} + +static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, + void *cb_priv) +{ + return -EOPNOTSUPP; +} + +struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, + struct nf_flowtable *ct_ft) +{ + struct efx_tc_ct_zone *ct_zone, *old; + int rc; + + ct_zone = kzalloc(sizeof(*ct_zone), GFP_USER); + if (!ct_zone) + return ERR_PTR(-ENOMEM); + ct_zone->zone = zone; + old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_zone_ht, + &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + if (old) { + /* don't need our new entry */ + kfree(ct_zone); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found */ + WARN_ON_ONCE(old->nf_ft != ct_ft); + netif_dbg(efx, drv, efx->net_dev, + "Found existing ct_zone for %u\n", zone); + return old; + } + ct_zone->nf_ft = ct_ft; + ct_zone->efx = efx; + rc = nf_flow_table_offload_add_cb(ct_ft, efx_tc_flow_block, ct_zone); + netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", + zone, rc); + if (rc < 0) + goto fail; + refcount_set(&ct_zone->ref, 1); + return ct_zone; +fail: + rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + kfree(ct_zone); + return ERR_PTR(rc); +} + +void efx_tc_ct_unregister_zone(struct efx_nic *efx, + struct efx_tc_ct_zone *ct_zone) +{ + if (!refcount_dec_and_test(&ct_zone->ref)) + return; /* still in use */ + nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); + rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, + efx_tc_ct_zone_ht_params); + netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", + ct_zone->zone); + kfree(ct_zone); +} diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h new file mode 100644 index 000000000000..f1e5fb74a73f --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef EFX_TC_CONNTRACK_H +#define EFX_TC_CONNTRACK_H +#include "net_driver.h" + +#if IS_ENABLED(CONFIG_SFC_SRIOV) +#include +#include + +struct efx_tc_ct_zone { + u16 zone; + struct rhash_head linkage; + refcount_t ref; + struct nf_flowtable *nf_ft; + struct efx_nic *efx; +}; + +/* create/teardown hashtables */ +int efx_tc_init_conntrack(struct efx_nic *efx); +void efx_tc_fini_conntrack(struct efx_nic *efx); + +struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, + struct nf_flowtable *ct_ft); +void efx_tc_ct_unregister_zone(struct efx_nic *efx, + struct efx_tc_ct_zone *ct_zone); + +#endif /* CONFIG_SFC_SRIOV */ +#endif /* EFX_TC_CONNTRACK_H */ -- cgit From 94aa05bdc77731043b6239a7b810c586be2dce46 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:07 +0100 Subject: sfc: functions to insert/remove conntrack entries to MAE hardware Translate from software struct efx_tc_ct_entry objects to the key and response bitstrings, and implement insertion and removal of these entries from the hardware table. Callers of these functions will be added in subsequent patches. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mae.c | 257 ++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 3 + drivers/net/ethernet/sfc/tc_conntrack.h | 14 ++ 3 files changed, 274 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 33ae2c852b44..8ebf71a54bf9 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -16,6 +16,7 @@ #include "mcdi_pcol.h" #include "mcdi_pcol_mae.h" #include "tc_encap_actions.h" +#include "tc_conntrack.h" int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label) { @@ -1403,6 +1404,262 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, return 0; } +/* Populating is done by taking each byte of @value in turn and storing + * it in the appropriate bits of @row. @value must be big-endian; we + * convert it to little-endianness as we go. + */ +static int efx_mae_table_populate(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, + void *value, size_t value_size) +{ + unsigned int i; + + /* For now only scheme 0 is supported for any field, so we check here + * (rather than, say, in calling code, which knows the semantics and + * could in principle encode for other schemes). + */ + if (field.scheme) + return -EOPNOTSUPP; + if (DIV_ROUND_UP(field.width, 8) != value_size) + return -EINVAL; + if (field.lbn + field.width > row_bits) + return -EINVAL; + for (i = 0; i < value_size; i++) { + unsigned int bn = field.lbn + i * 8; + unsigned int wn = bn / 32; + u64 v; + + v = ((u8 *)value)[value_size - i - 1]; + v <<= (bn % 32); + row[wn] |= cpu_to_le32(v & 0xffffffff); + if (wn * 32 < row_bits) + row[wn + 1] |= cpu_to_le32(v >> 32); + } + return 0; +} + +static int efx_mae_table_populate_bool(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, bool value) +{ + u8 v = value ? 1 : 0; + + if (field.width != 1) + return -EINVAL; + return efx_mae_table_populate(field, row, row_bits, &v, 1); +} + +static int efx_mae_table_populate_ipv4(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, __be32 value) +{ + /* IPv4 is placed in the first 4 bytes of an IPv6-sized field */ + struct in6_addr v = {}; + + if (field.width != 128) + return -EINVAL; + v.s6_addr32[0] = value; + return efx_mae_table_populate(field, row, row_bits, &v, sizeof(v)); +} + +static int efx_mae_table_populate_u24(struct efx_tc_table_field_fmt field, + __le32 *row, size_t row_bits, u32 value) +{ + __be32 v = cpu_to_be32(value); + + /* We adjust value_size here since just 3 bytes will be copied, and + * the pointer to the value is set discarding the first byte which is + * the most significant byte for a big-endian 4-bytes value. + */ + return efx_mae_table_populate(field, row, row_bits, ((void *)&v) + 1, + sizeof(v) - 1); +} + +#define _TABLE_POPULATE(dst, dw, _field, _value) ({ \ + typeof(_value) _v = _value; \ + \ + (_field.width == sizeof(_value) * 8) ? \ + efx_mae_table_populate(_field, dst, dw, &_v, \ + sizeof(_v)) : -EINVAL; \ +}) +#define TABLE_POPULATE_KEY_IPV4(dst, _table, _field, _value) \ + efx_mae_table_populate_ipv4(efx->tc->meta_##_table.desc.keys \ + [efx->tc->meta_##_table.keys._field##_idx],\ + dst, efx->tc->meta_##_table.desc.key_width,\ + _value) +#define TABLE_POPULATE_KEY(dst, _table, _field, _value) \ + _TABLE_POPULATE(dst, efx->tc->meta_##_table.desc.key_width, \ + efx->tc->meta_##_table.desc.keys \ + [efx->tc->meta_##_table.keys._field##_idx], \ + _value) + +#define TABLE_POPULATE_RESP_BOOL(dst, _table, _field, _value) \ + efx_mae_table_populate_bool(efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx],\ + dst, efx->tc->meta_##_table.desc.resp_width,\ + _value) +#define TABLE_POPULATE_RESP(dst, _table, _field, _value) \ + _TABLE_POPULATE(dst, efx->tc->meta_##_table.desc.resp_width, \ + efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx], \ + _value) + +#define TABLE_POPULATE_RESP_U24(dst, _table, _field, _value) \ + efx_mae_table_populate_u24(efx->tc->meta_##_table.desc.resps \ + [efx->tc->meta_##_table.resps._field##_idx],\ + dst, efx->tc->meta_##_table.desc.resp_width,\ + _value) + +static int efx_mae_populate_ct_key(struct efx_nic *efx, __le32 *key, size_t kw, + struct efx_tc_ct_entry *conn) +{ + bool ipv6 = conn->eth_proto == htons(ETH_P_IPV6); + int rc; + + rc = TABLE_POPULATE_KEY(key, ct, eth_proto, conn->eth_proto); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, ip_proto, conn->ip_proto); + if (rc) + return rc; + if (ipv6) + rc = TABLE_POPULATE_KEY(key, ct, src_ip, conn->src_ip6); + else + rc = TABLE_POPULATE_KEY_IPV4(key, ct, src_ip, conn->src_ip); + if (rc) + return rc; + if (ipv6) + rc = TABLE_POPULATE_KEY(key, ct, dst_ip, conn->dst_ip6); + else + rc = TABLE_POPULATE_KEY_IPV4(key, ct, dst_ip, conn->dst_ip); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, l4_sport, conn->l4_sport); + if (rc) + return rc; + rc = TABLE_POPULATE_KEY(key, ct, l4_dport, conn->l4_dport); + if (rc) + return rc; + return TABLE_POPULATE_KEY(key, ct, zone, cpu_to_be16(conn->zone->zone)); +} + +int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + bool ipv6 = conn->eth_proto == htons(ETH_P_IPV6); + __le32 *key = NULL, *resp = NULL; + size_t inlen, kw, rw; + efx_dword_t *inbuf; + int rc = -ENOMEM; + + /* Check table access is supported */ + if (!efx->tc->meta_ct.hooked) + return -EOPNOTSUPP; + + /* key/resp widths are in bits; convert to dwords for IN_LEN */ + kw = DIV_ROUND_UP(efx->tc->meta_ct.desc.key_width, 32); + rw = DIV_ROUND_UP(efx->tc->meta_ct.desc.resp_width, 32); + BUILD_BUG_ON(sizeof(__le32) != MC_CMD_TABLE_INSERT_IN_DATA_LEN); + inlen = MC_CMD_TABLE_INSERT_IN_LEN(kw + rw); + if (inlen > MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2) + return -E2BIG; + inbuf = kzalloc(inlen, GFP_KERNEL); + if (!inbuf) + return -ENOMEM; + + key = kcalloc(kw, sizeof(__le32), GFP_KERNEL); + if (!key) + goto out_free; + resp = kcalloc(rw, sizeof(__le32), GFP_KERNEL); + if (!resp) + goto out_free; + + rc = efx_mae_populate_ct_key(efx, key, kw, conn); + if (rc) + goto out_free; + + rc = TABLE_POPULATE_RESP_BOOL(resp, ct, dnat, conn->dnat); + if (rc) + goto out_free; + /* No support in hw for IPv6 NAT; field is only 32 bits */ + if (!ipv6) + rc = TABLE_POPULATE_RESP(resp, ct, nat_ip, conn->nat_ip); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP(resp, ct, l4_natport, conn->l4_natport); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP(resp, ct, mark, cpu_to_be32(conn->mark)); + if (rc) + goto out_free; + rc = TABLE_POPULATE_RESP_U24(resp, ct, counter_id, conn->cnt->fw_id); + if (rc) + goto out_free; + + MCDI_SET_DWORD(inbuf, TABLE_INSERT_IN_TABLE_ID, TABLE_ID_CONNTRACK_TABLE); + MCDI_SET_WORD(inbuf, TABLE_INSERT_IN_KEY_WIDTH, + efx->tc->meta_ct.desc.key_width); + /* MASK_WIDTH is zero as CT is a BCAM */ + MCDI_SET_WORD(inbuf, TABLE_INSERT_IN_RESP_WIDTH, + efx->tc->meta_ct.desc.resp_width); + memcpy(MCDI_PTR(inbuf, TABLE_INSERT_IN_DATA), key, kw * sizeof(__le32)); + memcpy(MCDI_PTR(inbuf, TABLE_INSERT_IN_DATA) + kw * sizeof(__le32), + resp, rw * sizeof(__le32)); + + BUILD_BUG_ON(MC_CMD_TABLE_INSERT_OUT_LEN); + + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_INSERT, inbuf, inlen, NULL, 0, NULL); + +out_free: + kfree(resp); + kfree(key); + kfree(inbuf); + return rc; +} + +int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + __le32 *key = NULL; + efx_dword_t *inbuf; + size_t inlen, kw; + int rc = -ENOMEM; + + /* Check table access is supported */ + if (!efx->tc->meta_ct.hooked) + return -EOPNOTSUPP; + + /* key width is in bits; convert to dwords for IN_LEN */ + kw = DIV_ROUND_UP(efx->tc->meta_ct.desc.key_width, 32); + BUILD_BUG_ON(sizeof(__le32) != MC_CMD_TABLE_DELETE_IN_DATA_LEN); + inlen = MC_CMD_TABLE_DELETE_IN_LEN(kw); + if (inlen > MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2) + return -E2BIG; + inbuf = kzalloc(inlen, GFP_KERNEL); + if (!inbuf) + return -ENOMEM; + + key = kcalloc(kw, sizeof(__le32), GFP_KERNEL); + if (!key) + goto out_free; + + rc = efx_mae_populate_ct_key(efx, key, kw, conn); + if (rc) + goto out_free; + + MCDI_SET_DWORD(inbuf, TABLE_DELETE_IN_TABLE_ID, TABLE_ID_CONNTRACK_TABLE); + MCDI_SET_WORD(inbuf, TABLE_DELETE_IN_KEY_WIDTH, + efx->tc->meta_ct.desc.key_width); + /* MASK_WIDTH is zero as CT is a BCAM */ + /* RESP_WIDTH is zero for DELETE */ + memcpy(MCDI_PTR(inbuf, TABLE_DELETE_IN_DATA), key, kw * sizeof(__le32)); + + BUILD_BUG_ON(MC_CMD_TABLE_DELETE_OUT_LEN); + + rc = efx_mcdi_rpc(efx, MC_CMD_TABLE_DELETE, inbuf, inlen, NULL, 0, NULL); + +out_free: + kfree(key); + kfree(inbuf); + return rc; +} + static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), const struct efx_tc_match *match) { diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index afdf738254b2..24f29a4fc0e1 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -112,6 +112,9 @@ int efx_mae_register_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); int efx_mae_unregister_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); +struct efx_tc_ct_entry; /* see tc_conntrack.h */ +int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); +int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, u32 prio, u32 acts_id, u32 *id); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index f1e5fb74a73f..a3e518344cbc 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -33,5 +33,19 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, void efx_tc_ct_unregister_zone(struct efx_nic *efx, struct efx_tc_ct_zone *ct_zone); +struct efx_tc_ct_entry { + unsigned long cookie; + struct rhash_head linkage; + __be16 eth_proto; + u8 ip_proto; + bool dnat; + __be32 src_ip, dst_ip, nat_ip; + struct in6_addr src_ip6, dst_ip6; + __be16 l4_sport, l4_dport, l4_natport; /* Ports (UDP, TCP) */ + struct efx_tc_ct_zone *zone; + u32 mark; + struct efx_tc_counter *cnt; +}; + #endif /* CONFIG_SFC_SRIOV */ #endif /* EFX_TC_CONNTRACK_H */ -- cgit From 1909387fcfcfc9197a0adcaa9702967e5c18f812 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:08 +0100 Subject: sfc: offload conntrack flow entries (match only) from CT zones No handling yet for FLOW_ACTION_MANGLE (NAT or NAPT) actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.h | 4 +- drivers/net/ethernet/sfc/tc_conntrack.c | 417 +++++++++++++++++++++++++++++++- drivers/net/ethernet/sfc/tc_conntrack.h | 3 + drivers/net/ethernet/sfc/tc_counters.c | 8 +- drivers/net/ethernet/sfc/tc_counters.h | 4 + 5 files changed, 429 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index fc196eb897af..2aba9ca00618 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -18,12 +18,10 @@ #define IS_ALL_ONES(v) (!(typeof (v))~(v)) -#ifdef CONFIG_IPV6 static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) { return !memchr_inv(addr, 0xff, sizeof(*addr)); } -#endif struct efx_tc_encap_action; /* see tc_encap_actions.h */ @@ -197,6 +195,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings + * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX @@ -230,6 +229,7 @@ struct efx_tc_state { struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable ct_zone_ht; + struct rhashtable ct_ht; struct rhashtable neigh_ht; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c index d67302715ec3..6729b3796a8b 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.c +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -21,6 +21,12 @@ static const struct rhashtable_params efx_tc_ct_zone_ht_params = { .head_offset = offsetof(struct efx_tc_ct_zone, linkage), }; +static const struct rhashtable_params efx_tc_ct_ht_params = { + .key_len = offsetof(struct efx_tc_ct_entry, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_ct_entry, linkage), +}; + static void efx_tc_ct_zone_free(void *ptr, void *arg) { struct efx_tc_ct_zone *zone = ptr; @@ -34,24 +40,420 @@ static void efx_tc_ct_zone_free(void *ptr, void *arg) kfree(zone); } +static void efx_tc_ct_free(void *ptr, void *arg) +{ + struct efx_tc_ct_entry *conn = ptr; + struct efx_nic *efx = arg; + + netif_err(efx, drv, efx->net_dev, + "tc ct_entry %lx still present at teardown\n", + conn->cookie); + + /* We can release the counter, but we can't remove the CT itself + * from hardware because the table meta is already gone. + */ + efx_tc_flower_release_counter(efx, conn->cnt); + kfree(conn); +} + int efx_tc_init_conntrack(struct efx_nic *efx) { int rc; rc = rhashtable_init(&efx->tc->ct_zone_ht, &efx_tc_ct_zone_ht_params); if (rc < 0) - return rc; + goto fail_ct_zone_ht; + rc = rhashtable_init(&efx->tc->ct_ht, &efx_tc_ct_ht_params); + if (rc < 0) + goto fail_ct_ht; return 0; +fail_ct_ht: + rhashtable_destroy(&efx->tc->ct_zone_ht); +fail_ct_zone_ht: + return rc; } void efx_tc_fini_conntrack(struct efx_nic *efx) { rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); + rhashtable_free_and_destroy(&efx->tc->ct_ht, efx_tc_ct_free, efx); +} + +#define EFX_NF_TCP_FLAG(flg) cpu_to_be16(be32_to_cpu(TCP_FLAG_##flg) >> 16) + +static int efx_tc_ct_parse_match(struct efx_nic *efx, struct flow_rule *fr, + struct efx_tc_ct_entry *conn) +{ + struct flow_dissector *dissector = fr->match.dissector; + unsigned char ipv = 0; + bool tcp = false; + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control fm; + + flow_rule_match_control(fr, &fm); + if (IS_ALL_ONES(fm.mask->addr_type)) + switch (fm.key->addr_type) { + case FLOW_DISSECTOR_KEY_IPV4_ADDRS: + ipv = 4; + break; + case FLOW_DISSECTOR_KEY_IPV6_ADDRS: + ipv = 6; + break; + default: + break; + } + } + + if (!ipv) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing ipv specification\n"); + return -EOPNOTSUPP; + } + + if (dissector->used_keys & + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | + BIT_ULL(FLOW_DISSECTOR_KEY_META))) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack keys %#llx\n", + dissector->used_keys); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic fm; + + flow_rule_match_basic(fr, &fm); + if (!IS_ALL_ONES(fm.mask->n_proto)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack eth_proto is not exact-match; mask %04x\n", + ntohs(fm.mask->n_proto)); + return -EOPNOTSUPP; + } + conn->eth_proto = fm.key->n_proto; + if (conn->eth_proto != (ipv == 4 ? htons(ETH_P_IP) + : htons(ETH_P_IPV6))) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack eth_proto is not IPv%u, is %04x\n", + ipv, ntohs(conn->eth_proto)); + return -EOPNOTSUPP; + } + if (!IS_ALL_ONES(fm.mask->ip_proto)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ip_proto is not exact-match; mask %02x\n", + fm.mask->ip_proto); + return -EOPNOTSUPP; + } + conn->ip_proto = fm.key->ip_proto; + switch (conn->ip_proto) { + case IPPROTO_TCP: + tcp = true; + break; + case IPPROTO_UDP: + break; + default: + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ip_proto not TCP or UDP, is %02x\n", + conn->ip_proto); + return -EOPNOTSUPP; + } + } else { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing eth_proto, ip_proto\n"); + return -EOPNOTSUPP; + } + + if (ipv == 4 && flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs fm; + + flow_rule_match_ipv4_addrs(fr, &fm); + if (!IS_ALL_ONES(fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv4.src is not exact-match; mask %08x\n", + ntohl(fm.mask->src)); + return -EOPNOTSUPP; + } + conn->src_ip = fm.key->src; + if (!IS_ALL_ONES(fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv4.dst is not exact-match; mask %08x\n", + ntohl(fm.mask->dst)); + return -EOPNOTSUPP; + } + conn->dst_ip = fm.key->dst; + } else if (ipv == 6 && flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs fm; + + flow_rule_match_ipv6_addrs(fr, &fm); + if (!efx_ipv6_addr_all_ones(&fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv6.src is not exact-match; mask %pI6\n", + &fm.mask->src); + return -EOPNOTSUPP; + } + conn->src_ip6 = fm.key->src; + if (!efx_ipv6_addr_all_ones(&fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ipv6.dst is not exact-match; mask %pI6\n", + &fm.mask->dst); + return -EOPNOTSUPP; + } + conn->dst_ip6 = fm.key->dst; + } else { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack missing IPv%u addrs\n", ipv); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports fm; + + flow_rule_match_ports(fr, &fm); + if (!IS_ALL_ONES(fm.mask->src)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ports.src is not exact-match; mask %04x\n", + ntohs(fm.mask->src)); + return -EOPNOTSUPP; + } + conn->l4_sport = fm.key->src; + if (!IS_ALL_ONES(fm.mask->dst)) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack ports.dst is not exact-match; mask %04x\n", + ntohs(fm.mask->dst)); + return -EOPNOTSUPP; + } + conn->l4_dport = fm.key->dst; + } else { + netif_dbg(efx, drv, efx->net_dev, "Conntrack missing L4 ports\n"); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(fr, FLOW_DISSECTOR_KEY_TCP)) { + __be16 tcp_interesting_flags; + struct flow_match_tcp fm; + + if (!tcp) { + netif_dbg(efx, drv, efx->net_dev, + "Conntrack matching on TCP keys but ipproto is not tcp\n"); + return -EOPNOTSUPP; + } + flow_rule_match_tcp(fr, &fm); + tcp_interesting_flags = EFX_NF_TCP_FLAG(SYN) | + EFX_NF_TCP_FLAG(RST) | + EFX_NF_TCP_FLAG(FIN); + /* If any of the tcp_interesting_flags is set, we always + * inhibit CT lookup in LHS (so SW can update CT table). + */ + if (fm.key->flags & tcp_interesting_flags) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack tcp.flags %04x/%04x\n", + ntohs(fm.key->flags), ntohs(fm.mask->flags)); + return -EOPNOTSUPP; + } + /* Other TCP flags cannot be filtered at CT */ + if (fm.mask->flags & ~tcp_interesting_flags) { + netif_dbg(efx, drv, efx->net_dev, + "Unsupported conntrack tcp.flags %04x/%04x\n", + ntohs(fm.key->flags), ntohs(fm.mask->flags)); + return -EOPNOTSUPP; + } + } + + return 0; +} + +static int efx_tc_ct_replace(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct flow_rule *fr = flow_cls_offload_flow_rule(tc); + struct efx_tc_ct_entry *conn, *old; + struct efx_nic *efx = ct_zone->efx; + const struct flow_action_entry *fa; + struct efx_tc_counter *cnt; + int rc, i; + + if (WARN_ON(!efx->tc)) + return -ENETDOWN; + if (WARN_ON(!efx->tc->up)) + return -ENETDOWN; + + conn = kzalloc(sizeof(*conn), GFP_USER); + if (!conn) + return -ENOMEM; + conn->cookie = tc->cookie; + old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_ht, + &conn->linkage, + efx_tc_ct_ht_params); + if (old) { + netif_dbg(efx, drv, efx->net_dev, + "Already offloaded conntrack (cookie %lx)\n", tc->cookie); + rc = -EEXIST; + goto release; + } + + /* Parse match */ + conn->zone = ct_zone; + rc = efx_tc_ct_parse_match(efx, fr, conn); + if (rc) + goto release; + + /* Parse actions */ + flow_action_for_each(i, fa, &fr->action) { + switch (fa->id) { + case FLOW_ACTION_CT_METADATA: + conn->mark = fa->ct_metadata.mark; + if (memchr_inv(fa->ct_metadata.labels, 0, sizeof(fa->ct_metadata.labels))) { + netif_dbg(efx, drv, efx->net_dev, + "Setting CT label not supported\n"); + rc = -EOPNOTSUPP; + goto release; + } + break; + default: + netif_dbg(efx, drv, efx->net_dev, + "Unhandled action %u for conntrack\n", fa->id); + rc = -EOPNOTSUPP; + goto release; + } + } + + /* fill in defaults for unmangled values */ + conn->nat_ip = conn->dnat ? conn->dst_ip : conn->src_ip; + conn->l4_natport = conn->dnat ? conn->l4_dport : conn->l4_sport; + + cnt = efx_tc_flower_allocate_counter(efx, EFX_TC_COUNTER_TYPE_CT); + if (IS_ERR(cnt)) { + rc = PTR_ERR(cnt); + goto release; + } + conn->cnt = cnt; + + rc = efx_mae_insert_ct(efx, conn); + if (rc) { + netif_dbg(efx, drv, efx->net_dev, + "Failed to insert conntrack, %d\n", rc); + goto release; + } + mutex_lock(&ct_zone->mutex); + list_add_tail(&conn->list, &ct_zone->cts); + mutex_unlock(&ct_zone->mutex); + return 0; +release: + if (conn->cnt) + efx_tc_flower_release_counter(efx, conn->cnt); + if (!old) + rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, + efx_tc_ct_ht_params); + kfree(conn); + return rc; +} + +/* Caller must follow with efx_tc_ct_remove_finish() after RCU grace period! */ +static void efx_tc_ct_remove(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + int rc; + + /* Remove it from HW */ + rc = efx_mae_remove_ct(efx, conn); + /* Delete it from SW */ + rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, + efx_tc_ct_ht_params); + if (rc) { + netif_err(efx, drv, efx->net_dev, + "Failed to remove conntrack %lx from hw, rc %d\n", + conn->cookie, rc); + } else { + netif_dbg(efx, drv, efx->net_dev, "Removed conntrack %lx\n", + conn->cookie); + } +} + +static void efx_tc_ct_remove_finish(struct efx_nic *efx, struct efx_tc_ct_entry *conn) +{ + /* Remove related CT counter. This is delayed after the conn object we + * are working with has been successfully removed. This protects the + * counter from being used-after-free inside efx_tc_ct_stats. + */ + efx_tc_flower_release_counter(efx, conn->cnt); + kfree(conn); +} + +static int efx_tc_ct_destroy(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct efx_nic *efx = ct_zone->efx; + struct efx_tc_ct_entry *conn; + + conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, + efx_tc_ct_ht_params); + if (!conn) { + netif_warn(efx, drv, efx->net_dev, + "Conntrack %lx not found to remove\n", tc->cookie); + return -ENOENT; + } + + mutex_lock(&ct_zone->mutex); + list_del(&conn->list); + efx_tc_ct_remove(efx, conn); + mutex_unlock(&ct_zone->mutex); + synchronize_rcu(); + efx_tc_ct_remove_finish(efx, conn); + return 0; +} + +static int efx_tc_ct_stats(struct efx_tc_ct_zone *ct_zone, + struct flow_cls_offload *tc) +{ + struct efx_nic *efx = ct_zone->efx; + struct efx_tc_ct_entry *conn; + struct efx_tc_counter *cnt; + + rcu_read_lock(); + conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, + efx_tc_ct_ht_params); + if (!conn) { + netif_warn(efx, drv, efx->net_dev, + "Conntrack %lx not found for stats\n", tc->cookie); + rcu_read_unlock(); + return -ENOENT; + } + + cnt = conn->cnt; + spin_lock_bh(&cnt->lock); + /* Report only last use */ + flow_stats_update(&tc->stats, 0, 0, 0, cnt->touched, + FLOW_ACTION_HW_STATS_DELAYED); + spin_unlock_bh(&cnt->lock); + rcu_read_unlock(); + + return 0; } static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, void *cb_priv) { + struct flow_cls_offload *tcb = type_data; + struct efx_tc_ct_zone *ct_zone = cb_priv; + + if (type != TC_SETUP_CLSFLOWER) + return -EOPNOTSUPP; + + switch (tcb->command) { + case FLOW_CLS_REPLACE: + return efx_tc_ct_replace(ct_zone, tcb); + case FLOW_CLS_DESTROY: + return efx_tc_ct_destroy(ct_zone, tcb); + case FLOW_CLS_STATS: + return efx_tc_ct_stats(ct_zone, tcb); + default: + break; + }; + return -EOPNOTSUPP; } @@ -81,6 +483,8 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, } ct_zone->nf_ft = ct_ft; ct_zone->efx = efx; + INIT_LIST_HEAD(&ct_zone->cts); + mutex_init(&ct_zone->mutex); rc = nf_flow_table_offload_add_cb(ct_ft, efx_tc_flow_block, ct_zone); netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", zone, rc); @@ -98,11 +502,22 @@ fail: void efx_tc_ct_unregister_zone(struct efx_nic *efx, struct efx_tc_ct_zone *ct_zone) { + struct efx_tc_ct_entry *conn, *next; + if (!refcount_dec_and_test(&ct_zone->ref)) return; /* still in use */ nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, efx_tc_ct_zone_ht_params); + mutex_lock(&ct_zone->mutex); + list_for_each_entry(conn, &ct_zone->cts, list) + efx_tc_ct_remove(efx, conn); + synchronize_rcu(); + /* need to use _safe because efx_tc_ct_remove_finish() frees conn */ + list_for_each_entry_safe(conn, next, &ct_zone->cts, list) + efx_tc_ct_remove_finish(efx, conn); + mutex_unlock(&ct_zone->mutex); + mutex_destroy(&ct_zone->mutex); netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", ct_zone->zone); kfree(ct_zone); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index a3e518344cbc..ef5cf96c0649 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -22,6 +22,8 @@ struct efx_tc_ct_zone { refcount_t ref; struct nf_flowtable *nf_ft; struct efx_nic *efx; + struct mutex mutex; /* protects cts list */ + struct list_head cts; /* list of efx_tc_ct_entry in this zone */ }; /* create/teardown hashtables */ @@ -45,6 +47,7 @@ struct efx_tc_ct_entry { struct efx_tc_ct_zone *zone; u32 mark; struct efx_tc_counter *cnt; + struct list_head list; /* entry on zone->cts */ }; #endif /* CONFIG_SFC_SRIOV */ diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c index 979f49058a0c..0fafb47ea082 100644 --- a/drivers/net/ethernet/sfc/tc_counters.c +++ b/drivers/net/ethernet/sfc/tc_counters.c @@ -129,8 +129,8 @@ static void efx_tc_counter_work(struct work_struct *work) /* Counter allocation */ -static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, - int type) +struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, + int type) { struct efx_tc_counter *cnt; int rc, rc2; @@ -169,8 +169,8 @@ fail1: return ERR_PTR(rc > 0 ? -EIO : rc); } -static void efx_tc_flower_release_counter(struct efx_nic *efx, - struct efx_tc_counter *cnt) +void efx_tc_flower_release_counter(struct efx_nic *efx, + struct efx_tc_counter *cnt) { int rc; diff --git a/drivers/net/ethernet/sfc/tc_counters.h b/drivers/net/ethernet/sfc/tc_counters.h index 41e57f34b763..f18d71c13600 100644 --- a/drivers/net/ethernet/sfc/tc_counters.h +++ b/drivers/net/ethernet/sfc/tc_counters.h @@ -49,6 +49,10 @@ int efx_tc_init_counters(struct efx_nic *efx); void efx_tc_destroy_counters(struct efx_nic *efx); void efx_tc_fini_counters(struct efx_nic *efx); +struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, + int type); +void efx_tc_flower_release_counter(struct efx_nic *efx, + struct efx_tc_counter *cnt); struct efx_tc_counter_index *efx_tc_flower_get_counter_index( struct efx_nic *efx, unsigned long cookie, enum efx_tc_counter_type type); -- cgit From 29416025185383aba51d863b9e9eff234b54d855 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:09 +0100 Subject: sfc: handle non-zero chain_index on TC rules Map it to an 8-bit recirc_id for use by the hardware. Currently nothing in the driver is offloading 'goto chain' actions, so these rules cannot yet be hit. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.c | 169 +++++++++++++++++++++++++++----- drivers/net/ethernet/sfc/tc.h | 15 ++- drivers/net/ethernet/sfc/tc_conntrack.c | 9 ++ drivers/net/ethernet/sfc/tc_conntrack.h | 3 +- 4 files changed, 170 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 44a6fc30b722..181636d07024 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -97,6 +97,12 @@ static const struct rhashtable_params efx_tc_match_action_ht_params = { .head_offset = offsetof(struct efx_tc_flow_rule, linkage), }; +static const struct rhashtable_params efx_tc_recirc_ht_params = { + .key_len = offsetof(struct efx_tc_recirc_id, linkage), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_recirc_id, linkage), +}; + static void efx_tc_free_action_set(struct efx_nic *efx, struct efx_tc_action_set *act, bool in_hw) { @@ -576,12 +582,65 @@ fail_pseudo: return rc; } +static struct efx_tc_recirc_id *efx_tc_get_recirc_id(struct efx_nic *efx, + u32 chain_index, + struct net_device *net_dev) +{ + struct efx_tc_recirc_id *rid, *old; + int rc; + + rid = kzalloc(sizeof(*rid), GFP_USER); + if (!rid) + return ERR_PTR(-ENOMEM); + rid->chain_index = chain_index; + /* We don't take a reference here, because it's implied - if there's + * a rule on the net_dev that's been offloaded to us, then the net_dev + * can't go away until the rule has been deoffloaded. + */ + rid->net_dev = net_dev; + old = rhashtable_lookup_get_insert_fast(&efx->tc->recirc_ht, + &rid->linkage, + efx_tc_recirc_ht_params); + if (old) { + /* don't need our new entry */ + kfree(rid); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found */ + rid = old; + } else { + rc = ida_alloc_range(&efx->tc->recirc_ida, 1, U8_MAX, GFP_USER); + if (rc < 0) { + rhashtable_remove_fast(&efx->tc->recirc_ht, + &rid->linkage, + efx_tc_recirc_ht_params); + kfree(rid); + return ERR_PTR(rc); + } + rid->fw_id = rc; + refcount_set(&rid->ref, 1); + } + return rid; +} + +static void efx_tc_put_recirc_id(struct efx_nic *efx, struct efx_tc_recirc_id *rid) +{ + if (!refcount_dec_and_test(&rid->ref)) + return; /* still in use */ + rhashtable_remove_fast(&efx->tc->recirc_ht, &rid->linkage, + efx_tc_recirc_ht_params); + ida_free(&efx->tc->recirc_ida, rid->fw_id); + kfree(rid); +} + static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule) { efx_mae_delete_rule(efx, rule->fw_id); /* Release entries in subsidiary tables */ efx_tc_free_action_set_list(efx, &rule->acts, true); + if (rule->match.rid) + efx_tc_put_recirc_id(efx, rule->match.rid); if (rule->match.encap) efx_tc_flower_release_encap_match(efx, rule->match.encap); rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; @@ -685,8 +744,17 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, match.mask.ingress_port = ~0; if (tc->common.chain_index) { - NL_SET_ERR_MSG_MOD(extack, "No support for nonzero chain_index"); - return -EOPNOTSUPP; + struct efx_tc_recirc_id *rid; + + rid = efx_tc_get_recirc_id(efx, tc->common.chain_index, net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Failed to allocate a hardware recirculation ID for chain_index %u", + tc->common.chain_index); + return PTR_ERR(rid); + } + match.rid = rid; + match.value.recirc_id = rid->fw_id; } match.mask.recirc_id = 0xff; @@ -706,12 +774,13 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (!found) { /* We don't care. */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter that doesn't egdev us\n"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rc = efx_mae_match_check_caps(efx, &match.mask, NULL); if (rc) - return rc; + goto release; if (efx_tc_match_is_encap(&match.mask)) { enum efx_encap_type type; @@ -720,7 +789,8 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (type == EFX_ENCAP_TYPE_NONE) { NL_SET_ERR_MSG_MOD(extack, "Egress encap match on unsupported tunnel device"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rc = efx_mae_check_encap_type_supported(efx, type); @@ -728,25 +798,26 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, NL_SET_ERR_MSG_FMT_MOD(extack, "Firmware reports no support for %s encap match", efx_tc_encap_type_name(type)); - return rc; + goto release; } rc = efx_tc_flower_record_encap_match(efx, &match, type, EFX_TC_EM_DIRECT, 0, 0, extack); if (rc) - return rc; + goto release; } else { /* This is not a tunnel decap rule, ignore it */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter without encap match\n"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto release; } rule = kzalloc(sizeof(*rule), GFP_USER); if (!rule) { rc = -ENOMEM; - goto out_free; + goto release; } INIT_LIST_HEAD(&rule->acts.list); rule->cookie = tc->cookie; @@ -758,7 +829,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, "Ignoring already-offloaded rule (cookie %lx)\n", tc->cookie); rc = -EEXIST; - goto out_free; + goto release; } act = kzalloc(sizeof(*act), GFP_USER); @@ -916,15 +987,17 @@ release: /* We failed to insert the rule, so free up any entries we created in * subsidiary tables. */ + if (match.rid) + efx_tc_put_recirc_id(efx, match.rid); if (act) efx_tc_free_action_set(efx, act, false); if (rule) { - rhashtable_remove_fast(&efx->tc->match_action_ht, - &rule->linkage, - efx_tc_match_action_ht_params); + if (!old) + rhashtable_remove_fast(&efx->tc->match_action_ht, + &rule->linkage, + efx_tc_match_action_ht_params); efx_tc_free_action_set_list(efx, &rule->acts, false); } -out_free: kfree(rule); if (match.encap) efx_tc_flower_release_encap_match(efx, match.encap); @@ -986,19 +1059,45 @@ static int efx_tc_flower_replace(struct efx_nic *efx, return -EOPNOTSUPP; } + /* chain_index 0 is always recirc_id 0 (and does not appear in recirc_ht). + * Conveniently, match.rid == NULL and match.value.recirc_id == 0 owing + * to the initial memset(), so we don't need to do anything in that case. + */ if (tc->common.chain_index) { - NL_SET_ERR_MSG_MOD(extack, "No support for nonzero chain_index"); - return -EOPNOTSUPP; + struct efx_tc_recirc_id *rid; + + /* Note regarding passed net_dev: + * VFreps and PF can share chain namespace, as they have + * distinct ingress_mports. So we don't need to burn an + * extra recirc_id if both use the same chain_index. + * (Strictly speaking, we could give each VFrep its own + * recirc_id namespace that doesn't take IDs away from the + * PF, but that would require a bunch of additional IDAs - + * one for each representor - and that's not likely to be + * the main cause of recirc_id exhaustion anyway.) + */ + rid = efx_tc_get_recirc_id(efx, tc->common.chain_index, + efx->net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Failed to allocate a hardware recirculation ID for chain_index %u", + tc->common.chain_index); + return PTR_ERR(rid); + } + match.rid = rid; + match.value.recirc_id = rid->fw_id; } match.mask.recirc_id = 0xff; rc = efx_mae_match_check_caps(efx, &match.mask, extack); if (rc) - return rc; + goto release; rule = kzalloc(sizeof(*rule), GFP_USER); - if (!rule) - return -ENOMEM; + if (!rule) { + rc = -ENOMEM; + goto release; + } INIT_LIST_HEAD(&rule->acts.list); rule->cookie = tc->cookie; old = rhashtable_lookup_get_insert_fast(&efx->tc->match_action_ht, @@ -1008,8 +1107,8 @@ static int efx_tc_flower_replace(struct efx_nic *efx, netif_dbg(efx, drv, efx->net_dev, "Already offloaded rule (cookie %lx)\n", tc->cookie); NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded"); - kfree(rule); - return -EEXIST; + rc = -EEXIST; + goto release; } /* Parse actions */ @@ -1327,12 +1426,15 @@ release: /* We failed to insert the rule, so free up any entries we created in * subsidiary tables. */ + if (match.rid) + efx_tc_put_recirc_id(efx, match.rid); if (act) efx_tc_free_action_set(efx, act, false); if (rule) { - rhashtable_remove_fast(&efx->tc->match_action_ht, - &rule->linkage, - efx_tc_match_action_ht_params); + if (!old) + rhashtable_remove_fast(&efx->tc->match_action_ht, + &rule->linkage, + efx_tc_match_action_ht_params); efx_tc_free_action_set_list(efx, &rule->acts, false); } kfree(rule); @@ -1702,6 +1804,16 @@ static void efx_tc_encap_match_free(void *ptr, void *__unused) kfree(encap); } +static void efx_tc_recirc_free(void *ptr, void *arg) +{ + struct efx_tc_recirc_id *rid = ptr; + struct efx_nic *efx = arg; + + WARN_ON(refcount_read(&rid->ref)); + ida_free(&efx->tc->recirc_ida, rid->fw_id); + kfree(rid); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -1751,6 +1863,10 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = efx_tc_init_conntrack(efx); if (rc < 0) goto fail_conntrack; + rc = rhashtable_init(&efx->tc->recirc_ht, &efx_tc_recirc_ht_params); + if (rc < 0) + goto fail_recirc_ht; + ida_init(&efx->tc->recirc_ida); efx->tc->reps_filter_uc = -1; efx->tc->reps_filter_mc = -1; INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list); @@ -1763,6 +1879,8 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; +fail_recirc_ht: + efx_tc_destroy_conntrack(efx); fail_conntrack: rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: @@ -1799,6 +1917,9 @@ void efx_fini_struct_tc(struct efx_nic *efx) rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); efx_tc_fini_conntrack(efx); + rhashtable_free_and_destroy(&efx->tc->recirc_ht, efx_tc_recirc_free, efx); + WARN_ON(!ida_is_empty(&efx->tc->recirc_ida)); + ida_destroy(&efx->tc->recirc_ida); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 2aba9ca00618..af15020c8da7 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -45,7 +45,7 @@ struct efx_tc_action_set { struct efx_tc_match_fields { /* L1 */ u32 ingress_port; - u8 recirc_id; + u8 recirc_id; /* mapped from (u32) TC chain_index to smaller space */ /* L2 (inner when encap) */ __be16 eth_proto; __be16 vlan_tci[2], vlan_proto[2]; @@ -115,10 +115,19 @@ struct efx_tc_encap_match { struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */ }; +struct efx_tc_recirc_id { + u32 chain_index; + struct net_device *net_dev; + struct rhash_head linkage; + refcount_t ref; + u8 fw_id; /* index allocated for use in the MAE */ +}; + struct efx_tc_match { struct efx_tc_match_fields value; struct efx_tc_match_fields mask; struct efx_tc_encap_match *encap; + struct efx_tc_recirc_id *rid; }; struct efx_tc_action_set_list { @@ -197,6 +206,8 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) + * @recirc_ht: Hashtable of recirculation ID mappings (&struct efx_tc_recirc_id) + * @recirc_ida: Recirculation ID allocator * @meta_ct: MAE table layout for conntrack table * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) @@ -231,6 +242,8 @@ struct efx_tc_state { struct rhashtable ct_zone_ht; struct rhashtable ct_ht; struct rhashtable neigh_ht; + struct rhashtable recirc_ht; + struct ida recirc_ida; struct efx_tc_table_ct meta_ct; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c index 6729b3796a8b..54ed288543d0 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.c +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -73,6 +73,15 @@ fail_ct_zone_ht: return rc; } +/* Only call this in init failure teardown. + * Normal exit should fini instead as there may be entries in the table. + */ +void efx_tc_destroy_conntrack(struct efx_nic *efx) +{ + rhashtable_destroy(&efx->tc->ct_ht); + rhashtable_destroy(&efx->tc->ct_zone_ht); +} + void efx_tc_fini_conntrack(struct efx_nic *efx) { rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); diff --git a/drivers/net/ethernet/sfc/tc_conntrack.h b/drivers/net/ethernet/sfc/tc_conntrack.h index ef5cf96c0649..e75c8eb1965d 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.h +++ b/drivers/net/ethernet/sfc/tc_conntrack.h @@ -26,8 +26,9 @@ struct efx_tc_ct_zone { struct list_head cts; /* list of efx_tc_ct_entry in this zone */ }; -/* create/teardown hashtables */ +/* create/uncreate/teardown hashtables */ int efx_tc_init_conntrack(struct efx_nic *efx); +void efx_tc_destroy_conntrack(struct efx_nic *efx); void efx_tc_fini_conntrack(struct efx_nic *efx); struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone, -- cgit From 1dfc29be4d743bba9c249b50acf8e44cb5477624 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:10 +0100 Subject: sfc: conntrack state matches in TC rules Parse ct_state trk/est, mark and zone out of flower keys, and plumb them through to the hardware, performing some minor translations. Nothing can actually hit them yet as we're not offloading any DO_CT actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mae.c | 33 ++++++++++++++++++--- drivers/net/ethernet/sfc/mcdi.h | 5 ++++ drivers/net/ethernet/sfc/tc.c | 66 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 5 ++++ 4 files changed, 105 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 8ebf71a54bf9..1fa0958d5262 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -695,8 +695,13 @@ int efx_mae_match_check_caps(struct efx_nic *efx, CHECK(L4_SPORT, l4_sport) || CHECK(L4_DPORT, l4_dport) || CHECK(TCP_FLAGS, tcp_flags) || + CHECK_BIT(TCP_SYN_FIN_RST, tcp_syn_fin_rst) || CHECK_BIT(IS_IP_FRAG, ip_frag) || CHECK_BIT(IP_FIRST_FRAG, ip_firstfrag) || + CHECK_BIT(DO_CT, ct_state_trk) || + CHECK_BIT(CT_HIT, ct_state_est) || + CHECK(CT_MARK, ct_mark) || + CHECK(CT_DOMAIN, ct_zone) || CHECK(RECIRC_ID, recirc_id)) return rc; /* Matches on outer fields are done in a separate hardware table, @@ -1672,20 +1677,40 @@ static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), } MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK, match->mask.ingress_port); - EFX_POPULATE_DWORD_2(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS), + EFX_POPULATE_DWORD_5(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS), + MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT, + match->value.ct_state_trk, + MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT, + match->value.ct_state_est, MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG, match->value.ip_frag, MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FIRST_FRAG, - match->value.ip_firstfrag); - EFX_POPULATE_DWORD_2(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK), + match->value.ip_firstfrag, + MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_SYN_FIN_RST, + match->value.tcp_syn_fin_rst); + EFX_POPULATE_DWORD_5(*_MCDI_STRUCT_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK), + MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT, + match->mask.ct_state_trk, + MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT, + match->mask.ct_state_est, MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG, match->mask.ip_frag, MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FIRST_FRAG, - match->mask.ip_firstfrag); + match->mask.ip_firstfrag, + MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_SYN_FIN_RST, + match->mask.tcp_syn_fin_rst); MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID, match->value.recirc_id); MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK, match->mask.recirc_id); + MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK, + match->value.ct_mark); + MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK, + match->mask.ct_mark); + MCDI_STRUCT_SET_WORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN, + match->value.ct_zone); + MCDI_STRUCT_SET_WORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK, + match->mask.ct_zone); MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE, match->value.eth_proto); MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK, diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 995a26686fd8..700d0252aebd 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -229,6 +229,11 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \ *(__force __le16 *)MCDI_PTR(_buf, _field) = cpu_to_le16(_value);\ } while (0) +#define MCDI_STRUCT_SET_WORD(_buf, _field, _value) do { \ + BUILD_BUG_ON(_field ## _LEN != 2); \ + BUILD_BUG_ON(_field ## _OFST & 1); \ + *(__force __le16 *)MCDI_STRUCT_PTR(_buf, _field) = cpu_to_le16(_value);\ + } while (0) #define MCDI_WORD(_buf, _field) \ ((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \ le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field))) diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 181636d07024..a9f4bfaacac3 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -222,6 +222,7 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_CT) | BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | BIT_ULL(FLOW_DISSECTOR_KEY_IP))) { NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#llx", @@ -363,6 +364,31 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, dissector->used_keys); return -EOPNOTSUPP; } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CT)) { + struct flow_match_ct fm; + + flow_rule_match_ct(rule, &fm); + match->value.ct_state_trk = !!(fm.key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED); + match->mask.ct_state_trk = !!(fm.mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_TRACKED); + match->value.ct_state_est = !!(fm.key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED); + match->mask.ct_state_est = !!(fm.mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED); + if (fm.mask->ct_state & ~(TCA_FLOWER_KEY_CT_FLAGS_TRACKED | + TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported ct_state match %#x", + fm.mask->ct_state); + return -EOPNOTSUPP; + } + match->value.ct_mark = fm.key->ct_mark; + match->mask.ct_mark = fm.mask->ct_mark; + match->value.ct_zone = fm.key->ct_zone; + match->mask.ct_zone = fm.mask->ct_zone; + + if (memchr_inv(fm.mask->ct_labels, 0, sizeof(fm.mask->ct_labels))) { + NL_SET_ERR_MSG_MOD(extack, "Matching on ct_label not supported"); + return -EOPNOTSUPP; + } + } return 0; } @@ -758,6 +784,26 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, } match.mask.recirc_id = 0xff; + /* AR table can't match on DO_CT (+trk). But a commonly used pattern is + * +trk+est, which is strictly implied by +est, so rewrite it to that. + */ + if (match.mask.ct_state_trk && match.value.ct_state_trk && + match.mask.ct_state_est && match.value.ct_state_est) + match.mask.ct_state_trk = 0; + /* Thanks to CT_TCP_FLAGS_INHIBIT, packets with interesting flags could + * match +trk-est (CT_HIT=0) despite being on an established connection. + * So make -est imply -tcp_syn_fin_rst match to ensure these packets + * still hit the software path. + */ + if (match.mask.ct_state_est && !match.value.ct_state_est) { + if (match.value.tcp_syn_fin_rst) { + /* Can't offload this combination */ + rc = -EOPNOTSUPP; + goto release; + } + match.mask.tcp_syn_fin_rst = true; + } + flow_action_for_each(i, fa, &fr->action) { switch (fa->id) { case FLOW_ACTION_REDIRECT: @@ -1089,6 +1135,26 @@ static int efx_tc_flower_replace(struct efx_nic *efx, } match.mask.recirc_id = 0xff; + /* AR table can't match on DO_CT (+trk). But a commonly used pattern is + * +trk+est, which is strictly implied by +est, so rewrite it to that. + */ + if (match.mask.ct_state_trk && match.value.ct_state_trk && + match.mask.ct_state_est && match.value.ct_state_est) + match.mask.ct_state_trk = 0; + /* Thanks to CT_TCP_FLAGS_INHIBIT, packets with interesting flags could + * match +trk-est (CT_HIT=0) despite being on an established connection. + * So make -est imply -tcp_syn_fin_rst match to ensure these packets + * still hit the software path. + */ + if (match.mask.ct_state_est && !match.value.ct_state_est) { + if (match.value.tcp_syn_fin_rst) { + /* Can't offload this combination */ + rc = -EOPNOTSUPP; + goto release; + } + match.mask.tcp_syn_fin_rst = true; + } + rc = efx_mae_match_check_caps(efx, &match.mask, extack); if (rc) goto release; diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index af15020c8da7..ce8e30743a3a 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -60,6 +60,7 @@ struct efx_tc_match_fields { /* L4 */ __be16 l4_sport, l4_dport; /* Ports (UDP, TCP) */ __be16 tcp_flags; + bool tcp_syn_fin_rst; /* true if ANY of SYN/FIN/RST are set */ /* Encap. The following are *outer* fields. Note that there are no * outer eth (L2) fields; this is because TC doesn't have them. */ @@ -68,6 +69,10 @@ struct efx_tc_match_fields { u8 enc_ip_tos, enc_ip_ttl; __be16 enc_sport, enc_dport; __be32 enc_keyid; /* e.g. VNI, VSID */ + /* Conntrack. */ + u16 ct_state_trk:1, ct_state_est:1; + u32 ct_mark; + u16 ct_zone; }; static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask) -- cgit From 01ad088fb05cb69bb2e061dc2ebddb67c62aeaf4 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 7 Aug 2023 14:48:11 +0100 Subject: sfc: offload left-hand side rules for conntrack Handle the (comparatively) simple case of a -trk rule on an efx netdev (i.e. not a tunnel decap rule) with ct and goto chain actions. Reviewed-by: Pieter Jansen van Vuuren Reviewed-by: Simon Horman Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/bitfield.h | 2 + drivers/net/ethernet/sfc/mae.c | 287 ++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/mae.h | 6 + drivers/net/ethernet/sfc/mcdi.h | 6 + drivers/net/ethernet/sfc/tc.c | 282 +++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 16 ++ 6 files changed, 599 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index 1f981dfe4bdc..89665fc9b8d0 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -26,6 +26,8 @@ /* Lowest bit numbers and widths */ #define EFX_DUMMY_FIELD_LBN 0 #define EFX_DUMMY_FIELD_WIDTH 0 +#define EFX_BYTE_0_LBN 0 +#define EFX_BYTE_0_WIDTH 8 #define EFX_WORD_0_LBN 0 #define EFX_WORD_0_WIDTH 16 #define EFX_WORD_1_LBN 16 diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 1fa0958d5262..3b8780c76b6e 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -727,6 +727,90 @@ int efx_mae_match_check_caps(struct efx_nic *efx, } return 0; } + +/* Checks for match fields not supported in LHS Outer Rules */ +#define UNSUPPORTED(_field) ({ \ + enum mask_type typ = classify_mask((const u8 *)&mask->_field, \ + sizeof(mask->_field)); \ + \ + if (typ != MASK_ZEROES) { \ + NL_SET_ERR_MSG_MOD(extack, "Unsupported match field " #_field);\ + rc = -EOPNOTSUPP; \ + } \ + rc; \ +}) +#define UNSUPPORTED_BIT(_field) ({ \ + if (mask->_field) { \ + NL_SET_ERR_MSG_MOD(extack, "Unsupported match field " #_field);\ + rc = -EOPNOTSUPP; \ + } \ + rc; \ +}) + +/* LHS rules are (normally) inserted in the Outer Rule table, which means + * they use ENC_ fields in hardware to match regular (not enc_) fields from + * &struct efx_tc_match_fields. + */ +int efx_mae_match_check_caps_lhs(struct efx_nic *efx, + const struct efx_tc_match_fields *mask, + struct netlink_ext_ack *extack) +{ + const u8 *supported_fields = efx->tc->caps->outer_rule_fields; + __be32 ingress_port = cpu_to_be32(mask->ingress_port); + enum mask_type ingress_port_mask_type; + int rc; + + /* Check for _PREFIX assumes big-endian, so we need to convert */ + ingress_port_mask_type = classify_mask((const u8 *)&ingress_port, + sizeof(ingress_port)); + rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_INGRESS_PORT], + ingress_port_mask_type); + if (rc) { + NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s\n", + mask_type_name(ingress_port_mask_type), + "ingress_port"); + return rc; + } + if (CHECK(ENC_ETHER_TYPE, eth_proto) || + CHECK(ENC_VLAN0_TCI, vlan_tci[0]) || + CHECK(ENC_VLAN0_PROTO, vlan_proto[0]) || + CHECK(ENC_VLAN1_TCI, vlan_tci[1]) || + CHECK(ENC_VLAN1_PROTO, vlan_proto[1]) || + CHECK(ENC_ETH_SADDR, eth_saddr) || + CHECK(ENC_ETH_DADDR, eth_daddr) || + CHECK(ENC_IP_PROTO, ip_proto) || + CHECK(ENC_IP_TOS, ip_tos) || + CHECK(ENC_IP_TTL, ip_ttl) || + CHECK_BIT(ENC_IP_FRAG, ip_frag) || + UNSUPPORTED_BIT(ip_firstfrag) || + CHECK(ENC_SRC_IP4, src_ip) || + CHECK(ENC_DST_IP4, dst_ip) || +#ifdef CONFIG_IPV6 + CHECK(ENC_SRC_IP6, src_ip6) || + CHECK(ENC_DST_IP6, dst_ip6) || +#endif + CHECK(ENC_L4_SPORT, l4_sport) || + CHECK(ENC_L4_DPORT, l4_dport) || + UNSUPPORTED(tcp_flags) || + CHECK_BIT(TCP_SYN_FIN_RST, tcp_syn_fin_rst)) + return rc; + if (efx_tc_match_is_encap(mask)) { + /* can't happen; disallowed for local rules, translated + * for foreign rules. + */ + NL_SET_ERR_MSG_MOD(extack, "Unexpected encap match in LHS rule"); + return -EOPNOTSUPP; + } + if (UNSUPPORTED(enc_keyid) || + /* Can't filter on conntrack in LHS rules */ + UNSUPPORTED_BIT(ct_state_trk) || + UNSUPPORTED_BIT(ct_state_est) || + UNSUPPORTED(ct_mark) || + UNSUPPORTED(recirc_id)) + return rc; + return 0; +} +#undef UNSUPPORTED #undef CHECK_BIT #undef CHECK @@ -1409,6 +1493,209 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, return 0; } +static int efx_mae_populate_lhs_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), + const struct efx_tc_match *match) +{ + if (match->mask.ingress_port) { + if (~match->mask.ingress_port) + return -EOPNOTSUPP; + MCDI_STRUCT_SET_DWORD(match_crit, + MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR, + match->value.ingress_port); + } + MCDI_STRUCT_SET_DWORD(match_crit, MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK, + match->mask.ingress_port); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE, + match->value.eth_proto); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK, + match->mask.eth_proto); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE, + match->value.vlan_tci[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK, + match->mask.vlan_tci[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE, + match->value.vlan_proto[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK, + match->mask.vlan_proto[0]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE, + match->value.vlan_tci[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK, + match->mask.vlan_tci[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE, + match->value.vlan_proto[1]); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK, + match->mask.vlan_proto[1]); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE), + match->value.eth_saddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK), + match->mask.eth_saddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE), + match->value.eth_daddr, ETH_ALEN); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK), + match->mask.eth_daddr, ETH_ALEN); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, + match->value.ip_proto); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, + match->mask.ip_proto); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS, + match->value.ip_tos); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK, + match->mask.ip_tos); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TTL, + match->value.ip_ttl); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK, + match->mask.ip_ttl); + MCDI_STRUCT_POPULATE_BYTE_1(match_crit, + MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS, + MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG, + match->value.ip_frag); + MCDI_STRUCT_POPULATE_BYTE_1(match_crit, + MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK, + MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK, + match->mask.ip_frag); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE, + match->value.src_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK, + match->mask.src_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE, + match->value.dst_ip); + MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK, + match->mask.dst_ip); +#ifdef CONFIG_IPV6 + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE), + &match->value.src_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK), + &match->mask.src_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE), + &match->value.dst_ip6, sizeof(struct in6_addr)); + memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK), + &match->mask.dst_ip6, sizeof(struct in6_addr)); +#endif + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE, + match->value.l4_sport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK, + match->mask.l4_sport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE, + match->value.l4_dport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK, + match->mask.l4_dport); + /* No enc-keys in LHS rules. Caps check should have caught this; any + * enc-keys from an fLHS should have been translated to regular keys + * and any EM should be a pseudo (we're an OR so can't have a direct + * EM with another OR). + */ + if (WARN_ON_ONCE(match->encap && !match->encap->type)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_src_ip)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_dst_ip)) + return -EOPNOTSUPP; +#ifdef CONFIG_IPV6 + if (WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_src_ip6))) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_dst_ip6))) + return -EOPNOTSUPP; +#endif + if (WARN_ON_ONCE(match->mask.enc_ip_tos)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_ip_ttl)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_sport)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_dport)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(match->mask.enc_keyid)) + return -EOPNOTSUPP; + return 0; +} + +static int efx_mae_insert_lhs_outer_rule(struct efx_nic *efx, + struct efx_tc_lhs_rule *rule, u32 prio) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(MAE_ENC_FIELD_PAIRS_LEN)); + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN); + MCDI_DECLARE_STRUCT_PTR(match_crit); + const struct efx_tc_lhs_action *act; + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_PRIO, prio); + /* match */ + match_crit = _MCDI_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA); + rc = efx_mae_populate_lhs_match_criteria(match_crit, &rule->match); + if (rc) + return rc; + + /* action */ + act = &rule->lhs_act; + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, + MAE_MCDI_ENCAP_TYPE_NONE); + /* We always inhibit CT lookup on TCP_INTERESTING_FLAGS, since the + * SW path needs to process the packet to update the conntrack tables + * on connection establishment (SYN) or termination (FIN, RST). + */ + MCDI_POPULATE_DWORD_6(inbuf, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL, + MAE_OUTER_RULE_INSERT_IN_DO_CT, !!act->zone, + MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT, 1, + MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN, + act->zone ? act->zone->zone : 0, + MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE, + MAE_CT_VNI_MODE_ZERO, + MAE_OUTER_RULE_INSERT_IN_DO_COUNT, !!act->count, + MAE_OUTER_RULE_INSERT_IN_RECIRC_ID, + act->rid ? act->rid->fw_id : 0); + if (act->count) + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_COUNTER_ID, + act->count->cnt->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + rule->fw_id = MCDI_DWORD(outbuf, MAE_OUTER_RULE_INSERT_OUT_OR_ID); + return 0; +} + +int efx_mae_insert_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule, + u32 prio) +{ + return efx_mae_insert_lhs_outer_rule(efx, rule, prio); +} + +static int efx_mae_remove_lhs_outer_rule(struct efx_nic *efx, + struct efx_tc_lhs_rule *rule) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_REMOVE_IN_OR_ID, rule->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_REMOVE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what encap_mds exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) != rule->fw_id)) + return -EIO; + /* We're probably about to free @rule, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + rule->fw_id = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL; + return 0; +} + +int efx_mae_remove_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule) +{ + return efx_mae_remove_lhs_outer_rule(efx, rule); +} + /* Populating is done by taking each byte of @value in turn and storing * it in the appropriate bits of @row. @value must be big-endian; we * convert it to little-endianness as we go. diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 24f29a4fc0e1..e88e80574f15 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -84,6 +84,9 @@ int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps); int efx_mae_match_check_caps(struct efx_nic *efx, const struct efx_tc_match_fields *mask, struct netlink_ext_ack *extack); +int efx_mae_match_check_caps_lhs(struct efx_nic *efx, + const struct efx_tc_match_fields *mask, + struct netlink_ext_ack *extack); int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, u8 ip_tos_mask, __be16 udp_sport_mask, struct netlink_ext_ack *extack); @@ -112,6 +115,9 @@ int efx_mae_register_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); int efx_mae_unregister_encap_match(struct efx_nic *efx, struct efx_tc_encap_match *encap); +int efx_mae_insert_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule, + u32 prio); +int efx_mae_remove_lhs_rule(struct efx_nic *efx, struct efx_tc_lhs_rule *rule); struct efx_tc_ct_entry; /* see tc_conntrack.h */ int efx_mae_insert_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); int efx_mae_remove_ct(struct efx_nic *efx, struct efx_tc_ct_entry *conn); diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 700d0252aebd..ea612c619874 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -218,6 +218,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); BUILD_BUG_ON(_field ## _LEN != 1); \ *(u8 *)MCDI_STRUCT_PTR(_buf, _field) = _value; \ } while (0) +#define MCDI_STRUCT_POPULATE_BYTE_1(_buf, _field, _name, _value) do { \ + efx_dword_t _temp; \ + EFX_POPULATE_DWORD_1(_temp, _name, _value); \ + MCDI_STRUCT_SET_BYTE(_buf, _field, \ + EFX_DWORD_FIELD(_temp, EFX_BYTE_0)); \ + } while (0) #define MCDI_BYTE(_buf, _field) \ ((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \ *MCDI_PTR(_buf, _field)) diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index a9f4bfaacac3..246657222958 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "tc.h" #include "tc_bindings.h" #include "tc_encap_actions.h" @@ -97,6 +98,12 @@ static const struct rhashtable_params efx_tc_match_action_ht_params = { .head_offset = offsetof(struct efx_tc_flow_rule, linkage), }; +static const struct rhashtable_params efx_tc_lhs_rule_ht_params = { + .key_len = sizeof(unsigned long), + .key_offset = offsetof(struct efx_tc_lhs_rule, cookie), + .head_offset = offsetof(struct efx_tc_lhs_rule, linkage), +}; + static const struct rhashtable_params efx_tc_recirc_ht_params = { .key_len = offsetof(struct efx_tc_recirc_id, linkage), .key_offset = 0, @@ -736,6 +743,163 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, } } +/** + * DOC: TC conntrack sequences + * + * The MAE hardware can handle at most two rounds of action rule matching, + * consequently we support conntrack through the notion of a "left-hand side + * rule". This is a rule which typically contains only the actions "ct" and + * "goto chain N", and corresponds to one or more "right-hand side rules" in + * chain N, which typically match on +trk+est, and may perform ct(nat) actions. + * RHS rules go in the Action Rule table as normal but with a nonzero recirc_id + * (the hardware equivalent of chain_index), while LHS rules may go in either + * the Action Rule or the Outer Rule table, the latter being preferred for + * performance reasons, and set both DO_CT and a recirc_id in their response. + * + * Besides the RHS rules, there are often also similar rules matching on + * +trk+new which perform the ct(commit) action. These are not offloaded. + */ + +static bool efx_tc_rule_is_lhs_rule(struct flow_rule *fr, + struct efx_tc_match *match) +{ + const struct flow_action_entry *fa; + int i; + + flow_action_for_each(i, fa, &fr->action) { + switch (fa->id) { + case FLOW_ACTION_GOTO: + return true; + case FLOW_ACTION_CT: + /* If rule is -trk, or doesn't mention trk at all, then + * a CT action implies a conntrack lookup (hence it's an + * LHS rule). If rule is +trk, then a CT action could + * just be ct(nat) or even ct(commit) (though the latter + * can't be offloaded). + */ + if (!match->mask.ct_state_trk || !match->value.ct_state_trk) + return true; + break; + default: + break; + } + } + return false; +} + +static int efx_tc_flower_handle_lhs_actions(struct efx_nic *efx, + struct flow_cls_offload *tc, + struct flow_rule *fr, + struct net_device *net_dev, + struct efx_tc_lhs_rule *rule) + +{ + struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_action *act = &rule->lhs_act; + const struct flow_action_entry *fa; + bool pipe = true; + int i; + + flow_action_for_each(i, fa, &fr->action) { + struct efx_tc_ct_zone *ct_zone; + struct efx_tc_recirc_id *rid; + + if (!pipe) { + /* more actions after a non-pipe action */ + NL_SET_ERR_MSG_MOD(extack, "Action follows non-pipe action"); + return -EINVAL; + } + switch (fa->id) { + case FLOW_ACTION_GOTO: + if (!fa->chain_index) { + NL_SET_ERR_MSG_MOD(extack, "Can't goto chain 0, no looping in hw"); + return -EOPNOTSUPP; + } + rid = efx_tc_get_recirc_id(efx, fa->chain_index, + net_dev); + if (IS_ERR(rid)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to allocate a hardware recirculation ID for this chain_index"); + return PTR_ERR(rid); + } + act->rid = rid; + if (fa->hw_stats) { + struct efx_tc_counter_index *cnt; + + if (!(fa->hw_stats & FLOW_ACTION_HW_STATS_DELAYED)) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "hw_stats_type %u not supported (only 'delayed')", + fa->hw_stats); + return -EOPNOTSUPP; + } + cnt = efx_tc_flower_get_counter_index(efx, tc->cookie, + EFX_TC_COUNTER_TYPE_OR); + if (IS_ERR(cnt)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to obtain a counter"); + return PTR_ERR(cnt); + } + WARN_ON(act->count); /* can't happen */ + act->count = cnt; + } + pipe = false; + break; + case FLOW_ACTION_CT: + if (act->zone) { + NL_SET_ERR_MSG_MOD(extack, "Can't offload multiple ct actions"); + return -EOPNOTSUPP; + } + if (fa->ct.action & (TCA_CT_ACT_COMMIT | + TCA_CT_ACT_FORCE)) { + NL_SET_ERR_MSG_MOD(extack, "Can't offload ct commit/force"); + return -EOPNOTSUPP; + } + if (fa->ct.action & TCA_CT_ACT_CLEAR) { + NL_SET_ERR_MSG_MOD(extack, "Can't clear ct in LHS rule"); + return -EOPNOTSUPP; + } + if (fa->ct.action & (TCA_CT_ACT_NAT | + TCA_CT_ACT_NAT_SRC | + TCA_CT_ACT_NAT_DST)) { + NL_SET_ERR_MSG_MOD(extack, "Can't perform NAT in LHS rule - packet isn't conntracked yet"); + return -EOPNOTSUPP; + } + if (fa->ct.action) { + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled ct.action %u for LHS rule\n", + fa->ct.action); + return -EOPNOTSUPP; + } + ct_zone = efx_tc_ct_register_zone(efx, fa->ct.zone, + fa->ct.flow_table); + if (IS_ERR(ct_zone)) { + NL_SET_ERR_MSG_MOD(extack, "Failed to register for CT updates"); + return PTR_ERR(ct_zone); + } + act->zone = ct_zone; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u for LHS rule\n", + fa->id); + return -EOPNOTSUPP; + } + } + + if (pipe) { + NL_SET_ERR_MSG_MOD(extack, "Missing goto chain in LHS rule"); + return -EOPNOTSUPP; + } + return 0; +} + +static void efx_tc_flower_release_lhs_actions(struct efx_nic *efx, + struct efx_tc_lhs_action *act) +{ + if (act->rid) + efx_tc_put_recirc_id(efx, act->rid); + if (act->zone) + efx_tc_ct_unregister_zone(efx, act->zone); + if (act->count) + efx_tc_flower_put_counter_index(efx, act->count); +} + static int efx_tc_flower_replace_foreign(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc) @@ -1050,6 +1214,78 @@ release: return rc; } +static int efx_tc_flower_replace_lhs(struct efx_nic *efx, + struct flow_cls_offload *tc, + struct flow_rule *fr, + struct efx_tc_match *match, + struct efx_rep *efv, + struct net_device *net_dev) +{ + struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_rule *rule, *old; + int rc; + + if (tc->common.chain_index) { + NL_SET_ERR_MSG_MOD(extack, "LHS rule only allowed in chain 0"); + return -EOPNOTSUPP; + } + + if (match->mask.ct_state_trk && match->value.ct_state_trk) { + NL_SET_ERR_MSG_MOD(extack, "LHS rule can never match +trk"); + return -EOPNOTSUPP; + } + /* LHS rules are always -trk, so we don't need to match on that */ + match->mask.ct_state_trk = 0; + match->value.ct_state_trk = 0; + + rc = efx_mae_match_check_caps_lhs(efx, &match->mask, extack); + if (rc) + return rc; + + rule = kzalloc(sizeof(*rule), GFP_USER); + if (!rule) + return -ENOMEM; + rule->cookie = tc->cookie; + old = rhashtable_lookup_get_insert_fast(&efx->tc->lhs_rule_ht, + &rule->linkage, + efx_tc_lhs_rule_ht_params); + if (old) { + netif_dbg(efx, drv, efx->net_dev, + "Already offloaded rule (cookie %lx)\n", tc->cookie); + rc = -EEXIST; + NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded"); + goto release; + } + + /* Parse actions */ + /* See note in efx_tc_flower_replace() regarding passed net_dev + * (used for efx_tc_get_recirc_id()). + */ + rc = efx_tc_flower_handle_lhs_actions(efx, tc, fr, efx->net_dev, rule); + if (rc) + goto release; + + rule->match = *match; + + rc = efx_mae_insert_lhs_rule(efx, rule, EFX_TC_PRIO_TC); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw"); + goto release; + } + netif_dbg(efx, drv, efx->net_dev, + "Successfully parsed lhs rule (cookie %lx)\n", + tc->cookie); + return 0; + +release: + efx_tc_flower_release_lhs_actions(efx, &rule->lhs_act); + if (!old) + rhashtable_remove_fast(&efx->tc->lhs_rule_ht, &rule->linkage, + efx_tc_lhs_rule_ht_params); + kfree(rule); + return rc; +} + static int efx_tc_flower_replace(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc, @@ -1105,6 +1341,10 @@ static int efx_tc_flower_replace(struct efx_nic *efx, return -EOPNOTSUPP; } + if (efx_tc_rule_is_lhs_rule(fr, &match)) + return efx_tc_flower_replace_lhs(efx, tc, fr, &match, efv, + net_dev); + /* chain_index 0 is always recirc_id 0 (and does not appear in recirc_ht). * Conveniently, match.rid == NULL and match.value.recirc_id == 0 owing * to the initial memset(), so we don't need to do anything in that case. @@ -1512,8 +1752,26 @@ static int efx_tc_flower_destroy(struct efx_nic *efx, struct flow_cls_offload *tc) { struct netlink_ext_ack *extack = tc->common.extack; + struct efx_tc_lhs_rule *lhs_rule; struct efx_tc_flow_rule *rule; + lhs_rule = rhashtable_lookup_fast(&efx->tc->lhs_rule_ht, &tc->cookie, + efx_tc_lhs_rule_ht_params); + if (lhs_rule) { + /* Remove it from HW */ + efx_mae_remove_lhs_rule(efx, lhs_rule); + /* Delete it from SW */ + efx_tc_flower_release_lhs_actions(efx, &lhs_rule->lhs_act); + rhashtable_remove_fast(&efx->tc->lhs_rule_ht, &lhs_rule->linkage, + efx_tc_lhs_rule_ht_params); + if (lhs_rule->match.encap) + efx_tc_flower_release_encap_match(efx, lhs_rule->match.encap); + netif_dbg(efx, drv, efx->net_dev, "Removed (lhs) filter %lx\n", + lhs_rule->cookie); + kfree(lhs_rule); + return 0; + } + rule = rhashtable_lookup_fast(&efx->tc->match_action_ht, &tc->cookie, efx_tc_match_action_ht_params); if (!rule) { @@ -1880,6 +2138,24 @@ static void efx_tc_recirc_free(void *ptr, void *arg) kfree(rid); } +static void efx_tc_lhs_free(void *ptr, void *arg) +{ + struct efx_tc_lhs_rule *rule = ptr; + struct efx_nic *efx = arg; + + netif_err(efx, drv, efx->net_dev, + "tc lhs_rule %lx still present at teardown, removing\n", + rule->cookie); + + if (rule->lhs_act.zone) + efx_tc_ct_unregister_zone(efx, rule->lhs_act.zone); + if (rule->lhs_act.count) + efx_tc_flower_put_counter_index(efx, rule->lhs_act.count); + efx_mae_remove_lhs_rule(efx, rule); + + kfree(rule); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -1926,6 +2202,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = rhashtable_init(&efx->tc->match_action_ht, &efx_tc_match_action_ht_params); if (rc < 0) goto fail_match_action_ht; + rc = rhashtable_init(&efx->tc->lhs_rule_ht, &efx_tc_lhs_rule_ht_params); + if (rc < 0) + goto fail_lhs_rule_ht; rc = efx_tc_init_conntrack(efx); if (rc < 0) goto fail_conntrack; @@ -1948,6 +2227,8 @@ int efx_init_struct_tc(struct efx_nic *efx) fail_recirc_ht: efx_tc_destroy_conntrack(efx); fail_conntrack: + rhashtable_destroy(&efx->tc->lhs_rule_ht); +fail_lhs_rule_ht: rhashtable_destroy(&efx->tc->match_action_ht); fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); @@ -1978,6 +2259,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id != MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + rhashtable_free_and_destroy(&efx->tc->lhs_rule_ht, efx_tc_lhs_free, efx); rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free, efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index ce8e30743a3a..40d2c803fca8 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -140,6 +140,12 @@ struct efx_tc_action_set_list { u32 fw_id; }; +struct efx_tc_lhs_action { + struct efx_tc_recirc_id *rid; + struct efx_tc_ct_zone *zone; + struct efx_tc_counter_index *count; +}; + struct efx_tc_flow_rule { unsigned long cookie; struct rhash_head linkage; @@ -149,6 +155,14 @@ struct efx_tc_flow_rule { u32 fw_id; }; +struct efx_tc_lhs_rule { + unsigned long cookie; + struct efx_tc_match match; + struct efx_tc_lhs_action lhs_act; + struct rhash_head linkage; + u32 fw_id; +}; + enum efx_tc_rule_prios { EFX_TC_PRIO_TC, /* Rule inserted by TC */ EFX_TC_PRIO_DFLT, /* Default switch rule; one of efx_tc_default_rules */ @@ -208,6 +222,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings * @ct_ht: Hashtable of TC conntrack flow entries * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) @@ -244,6 +259,7 @@ struct efx_tc_state { struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable lhs_rule_ht; struct rhashtable ct_zone_ht; struct rhashtable ct_ht; struct rhashtable neigh_ht; -- cgit From b9b05381e5d76a5ad05aedf5357c585d4a1f78cd Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 5 Aug 2023 15:45:36 +0100 Subject: net: dsa: mt7530: improve and relax PHY driver dependency Different MT7530 variants require different PHY drivers. Use 'imply' instead of 'select' to relax the dependency on the PHY driver, and choose the appropriate driver. Signed-off-by: Daniel Golle Reviewed-by: Simon Horman Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index 3ed5391bb18d..f8c1d73b251d 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig @@ -37,7 +37,6 @@ config NET_DSA_LANTIQ_GSWIP config NET_DSA_MT7530 tristate "MediaTek MT7530 and MT7531 Ethernet switch support" select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY imply NET_DSA_MT7530_MDIO imply NET_DSA_MT7530_MMIO help @@ -49,6 +48,7 @@ config NET_DSA_MT7530 config NET_DSA_MT7530_MDIO tristate "MediaTek MT7530 MDIO interface driver" depends on NET_DSA_MT7530 + imply MEDIATEK_GE_PHY select PCS_MTK_LYNXI help This enables support for the MediaTek MT7530 and MT7531 switch @@ -60,6 +60,7 @@ config NET_DSA_MT7530_MMIO tristate "MediaTek MT7530 MMIO interface driver" depends on NET_DSA_MT7530 depends on HAS_IOMEM + imply MEDIATEK_GE_SOC_PHY help This enables support for the built-in Ethernet switch found in the MediaTek MT7988 SoC. -- cgit From 09c80167dbec3c742ed0d0218eef13be648b47ed Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 09:47:02 +0800 Subject: bcm63xx_enet: Remove redundant initialization owner The platform_register_drivers() will set "THIS_MODULE" to driver.owner when register a platform_driver driver, so it is redundant initialization to set driver.owner in the statement. Remove it for clean code. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Reviewed-by: Kalesh AP Link: https://lore.kernel.org/r/20230808014702.2712699-1-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 2cf96892e565..a741070f1f9a 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1940,7 +1940,6 @@ static struct platform_driver bcm63xx_enet_driver = { .remove = bcm_enet_remove, .driver = { .name = "bcm63xx_enet", - .owner = THIS_MODULE, }, }; @@ -2761,7 +2760,6 @@ static struct platform_driver bcm63xx_enetsw_driver = { .remove = bcm_enetsw_remove, .driver = { .name = "bcm63xx_enetsw", - .owner = THIS_MODULE, }, }; @@ -2791,7 +2789,6 @@ struct platform_driver bcm63xx_enet_shared_driver = { .probe = bcm_enet_shared_probe, .driver = { .name = "bcm63xx_enet_shared", - .owner = THIS_MODULE, }, }; -- cgit From d8c21ef7b2b147a7e0d0497da120a3bc73be7fbe Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Tue, 8 Aug 2023 10:49:31 +0800 Subject: net: txgbe: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Xiongfeng Wang Reviewed-by: Yang Yingliang Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230808024931.147048-1-wangxiongfeng2@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 8779645a54be..819d1db34643 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -26,7 +26,7 @@ static int txgbe_swnodes_register(struct txgbe *txgbe) struct software_node *swnodes; u32 id; - id = (pdev->bus->number << 8) | pdev->devfn; + id = pci_dev_id(pdev); snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id); snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id); @@ -140,7 +140,7 @@ static int txgbe_mdio_pcs_init(struct txgbe *txgbe) mii_bus->phy_mask = ~0; mii_bus->priv = wx; snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x", - (pdev->bus->number << 8) | pdev->devfn); + pci_dev_id(pdev)); ret = devm_mdiobus_register(&pdev->dev, mii_bus); if (ret) @@ -459,7 +459,7 @@ static int txgbe_gpio_init(struct txgbe *txgbe) return -ENOMEM; gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x", - (wx->pdev->bus->number << 8) | wx->pdev->devfn); + pci_dev_id(wx->pdev)); if (!gc->label) return -ENOMEM; @@ -503,7 +503,7 @@ static int txgbe_clock_register(struct txgbe *txgbe) struct clk *clk; snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", - (pdev->bus->number << 8) | pdev->devfn); + pci_dev_id(pdev)); clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); if (IS_ERR(clk)) @@ -566,7 +566,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe) info.parent = &pdev->dev; info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); info.name = "i2c_designware"; - info.id = (pdev->bus->number << 8) | pdev->devfn; + info.id = pci_dev_id(pdev); info.res = &DEFINE_RES_IRQ(pdev->irq); info.num_res = 1; @@ -588,7 +588,7 @@ static int txgbe_sfp_register(struct txgbe *txgbe) info.parent = &pdev->dev; info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]); info.name = "sfp"; - info.id = (pdev->bus->number << 8) | pdev->devfn; + info.id = pci_dev_id(pdev); sfp_dev = platform_device_register_full(&info); if (IS_ERR(sfp_dev)) return PTR_ERR(sfp_dev); -- cgit From 98261be155f8de38f11b6542d4a8935e5532687b Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Tue, 8 Aug 2023 22:52:49 +0800 Subject: mlxbf_gige: Remove two unused function declarations Commit f92e1869d74e ("Add Mellanox BlueField Gigabit Ethernet driver") declared but never implemented these. Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Reviewed-by: Asmaa Mnebhi Link: https://lore.kernel.org/r/20230808145249.41596-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h index a453b9cd9033..bc94e75a7aeb 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h @@ -175,9 +175,6 @@ enum mlxbf_gige_res { int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv); void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv); -irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(int irq, void *dev_id); -void mlxbf_gige_mdio_enable_phy_int(struct mlxbf_gige *priv); - void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, unsigned int index, u64 dmac); void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, -- cgit From 99ecd6d065270c0447e33b7a14acf990fe6a2668 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Tue, 8 Aug 2023 21:35:28 +0800 Subject: mlxsw: spectrum_switchdev: Use is_zero_ether_addr() instead of ether_addr_equal() Use is_zero_ether_addr() instead of ether_addr_equal() to check if the ethernet address is all zeros. Signed-off-by: Ruan Jinjie Reviewed-by: Ido Schimmel Link: https://lore.kernel.org/r/20230808133528.4083501-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 5376d4af5f91..efacb057d1d4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3549,7 +3549,6 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info; struct mlxsw_sp_bridge_device *bridge_device; struct net_device *dev = switchdev_work->dev; - u8 all_zeros_mac[ETH_ALEN] = { 0 }; enum mlxsw_sp_l3proto proto; union mlxsw_sp_l3addr addr; struct net_device *br_dev; @@ -3571,7 +3570,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_switchdev_vxlan_addr_convert(&vxlan_fdb_info->remote_ip, &proto, &addr); - if (ether_addr_equal(vxlan_fdb_info->eth_addr, all_zeros_mac)) { + if (is_zero_ether_addr(vxlan_fdb_info->eth_addr)) { err = mlxsw_sp_nve_flood_ip_add(mlxsw_sp, fid, proto, &addr); if (err) { mlxsw_sp_fid_put(fid); @@ -3623,7 +3622,6 @@ mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_bridge_device *bridge_device; struct net_device *dev = switchdev_work->dev; struct net_device *br_dev = netdev_master_upper_dev_get(dev); - u8 all_zeros_mac[ETH_ALEN] = { 0 }; enum mlxsw_sp_l3proto proto; union mlxsw_sp_l3addr addr; struct mlxsw_sp_fid *fid; @@ -3644,7 +3642,7 @@ mlxsw_sp_switchdev_vxlan_fdb_del(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_switchdev_vxlan_addr_convert(&vxlan_fdb_info->remote_ip, &proto, &addr); - if (ether_addr_equal(vxlan_fdb_info->eth_addr, all_zeros_mac)) { + if (is_zero_ether_addr(vxlan_fdb_info->eth_addr)) { mlxsw_sp_nve_flood_ip_del(mlxsw_sp, fid, proto, &addr); mlxsw_sp_fid_put(fid); return; -- cgit From b77049f04ed16cb0ab89b1cca689cd16a3071fd2 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 19:38:49 +0800 Subject: ethernet: s2io: Use ether_addr_to_u64() to convert ethernet address Use ether_addr_to_u64() to convert an Ethernet address into a u64 value, instead of directly calculating, as this is exactly what this function does. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230808113849.4033657-1-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/neterion/s2io.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 700c05fb05b9..61d8bfd12d5f 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -5091,13 +5091,10 @@ static void do_s2io_restore_unicast_mc(struct s2io_nic *sp) static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr) { int i; - u64 mac_addr = 0; + u64 mac_addr; struct config_param *config = &sp->config; - for (i = 0; i < ETH_ALEN; i++) { - mac_addr <<= 8; - mac_addr |= addr[i]; - } + mac_addr = ether_addr_to_u64(addr); if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY)) return SUCCESS; @@ -5220,7 +5217,7 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p) static int do_s2io_prog_unicast(struct net_device *dev, const u8 *addr) { struct s2io_nic *sp = netdev_priv(dev); - register u64 mac_addr = 0, perm_addr = 0; + register u64 mac_addr, perm_addr; int i; u64 tmp64; struct config_param *config = &sp->config; @@ -5230,12 +5227,8 @@ static int do_s2io_prog_unicast(struct net_device *dev, const u8 *addr) * change on the device address registered with the OS. It will be * at offset 0. */ - for (i = 0; i < ETH_ALEN; i++) { - mac_addr <<= 8; - mac_addr |= addr[i]; - perm_addr <<= 8; - perm_addr |= sp->def_mac_addr[0].mac_addr[i]; - } + mac_addr = ether_addr_to_u64(addr); + perm_addr = ether_addr_to_u64(sp->def_mac_addr[0].mac_addr); /* check if the dev_addr is different than perm_addr */ if (mac_addr == perm_addr) -- cgit From a76ca8afd45af103fc61217eebe90cae7c02cf6c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 8 Aug 2023 15:18:15 +0200 Subject: mlxsw: Set port STP state on bridge enslavement When the first port joins a LAG that already has a bridge upper, an instance of struct mlxsw_sp_bridge_port is created for the LAG to keep track of it as a bridge port. The bridge_port's STP state is initialized to BR_STATE_DISABLED. This made sense previously, because mlxsw would only ever allow a port to join a LAG if the LAG had no uppers. Thus if a bridge_port was instantiated, it must have been because the LAG as such is joining a bridge, and the STP state is correspondingly disabled. However as of commit 2c5ffe8d7226 ("mlxsw: spectrum: Permit enslavement to netdevices with uppers"), mlxsw allows a port to join a LAG that is already a member of a bridge. The STP state may be different than disabled in that case. Initialize it properly by querying the actual state. This bug may cause an issue as traffic on ports attached to a bridged LAG gets dropped on ingress with discard_ingress_general counter bumped. Fixes: c6514f3627a0 ("Merge branch 'mlxsw-enslavement'") Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/39f4a5781050866b4132f350d7d8cf7ab23ea070.1691498735.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index efacb057d1d4..3662b9da5489 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -490,7 +490,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device, bridge_port->system_port = mlxsw_sp_port->local_port; bridge_port->dev = brport_dev; bridge_port->bridge_device = bridge_device; - bridge_port->stp_state = BR_STATE_DISABLED; + bridge_port->stp_state = br_port_get_stp_state(brport_dev); bridge_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC | BR_MCAST_FLOOD; INIT_LIST_HEAD(&bridge_port->vlans_list); -- cgit From 7d0bc2602308ec0a183241914b0646d99d0fb541 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 19:45:02 +0800 Subject: octeontx2-af: Remove redundant functions mac2u64() and cfg2mac() The mac2u64() is used to convert an Ethernet MAC address into a u64 value, as this is exactly what ether_addr_to_u64() does. Similarly, the cfg2mac() is also the case. Use ether_addr_to_u64() and u64_to_ether_addr() instead of these two. Signed-off-by: Li Zetao Acked-by: Geethasowjanya Akula Link: https://lore.kernel.org/r/20230808114504.4036008-2-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 26 ++++--------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 592037f4e55b..988383e20bb8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -223,24 +223,6 @@ int cgx_get_link_info(void *cgxd, int lmac_id, return 0; } -static u64 mac2u64 (u8 *mac_addr) -{ - u64 mac = 0; - int index; - - for (index = ETH_ALEN - 1; index >= 0; index--) - mac |= ((u64)*mac_addr++) << (8 * index); - return mac; -} - -static void cfg2mac(u64 cfg, u8 *mac_addr) -{ - int i, index = 0; - - for (i = ETH_ALEN - 1; i >= 0; i--, index++) - mac_addr[i] = (cfg >> (8 * index)) & 0xFF; -} - int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr) { struct cgx *cgx_dev = cgx_get_pdata(cgx_id); @@ -255,7 +237,7 @@ int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr) /* copy 6bytes from macaddr */ /* memcpy(&cfg, mac_addr, 6); */ - cfg = mac2u64 (mac_addr); + cfg = ether_addr_to_u64(mac_addr); id = get_sequence_id_of_lmac(cgx_dev, lmac_id); @@ -322,7 +304,7 @@ int cgx_lmac_addr_add(u8 cgx_id, u8 lmac_id, u8 *mac_addr) index = id * lmac->mac_to_index_bmap.max + idx; - cfg = mac2u64 (mac_addr); + cfg = ether_addr_to_u64(mac_addr); cfg |= CGX_DMAC_CAM_ADDR_ENABLE; cfg |= ((u64)lmac_id << 49); cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg); @@ -405,7 +387,7 @@ int cgx_lmac_addr_update(u8 cgx_id, u8 lmac_id, u8 *mac_addr, u8 index) cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8))); cfg &= ~CGX_RX_DMAC_ADR_MASK; - cfg |= mac2u64 (mac_addr); + cfg |= ether_addr_to_u64(mac_addr); cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg); return 0; @@ -441,7 +423,7 @@ int cgx_lmac_addr_del(u8 cgx_id, u8 lmac_id, u8 index) /* Read MAC address to check whether it is ucast or mcast */ cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8))); - cfg2mac(cfg, mac); + u64_to_ether_addr(cfg, mac); if (is_multicast_ether_addr(mac)) lmac->mcast_filters_count--; -- cgit From e62c7adfd4acc394c448870ba63d4315e7a662f6 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 19:45:03 +0800 Subject: octeontx2-af: Use u64_to_ether_addr() to convert ethernet address Use u64_to_ether_addr() to convert a u64 value to an Ethernet MAC address, instead of directly calculating, as this is exactly what this function does. Signed-off-by: Li Zetao Acked-by: Geethasowjanya Akula Link: https://lore.kernel.org/r/20230808114504.4036008-3-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 095b2cc4a699..b3f766b970ca 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -686,7 +686,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu, { int pf = rvu_get_pf(req->hdr.pcifunc); u8 cgx_id, lmac_id; - int rc = 0, i; + int rc = 0; u64 cfg; if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) @@ -697,8 +697,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu, rsp->hdr.rc = rc; cfg = cgx_lmac_addr_get(cgx_id, lmac_id); /* copy 48 bit mac address to req->mac_addr */ - for (i = 0; i < ETH_ALEN; i++) - rsp->mac_addr[i] = cfg >> (ETH_ALEN - 1 - i) * 8; + u64_to_ether_addr(cfg, rsp->mac_addr); return 0; } -- cgit From 47f8dc0938e95fc98bd1a61d49717c892eb5f9f7 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 19:45:04 +0800 Subject: octeontx2-af: Remove redundant functions rvu_npc_exact_mac2u64() The rvu_npc_exact_mac2u64() is used to convert an Ethernet MAC address into a u64 value, as this is exactly what ether_addr_to_u64() does. Use ether_addr_to_u64() to replace the rvu_npc_exact_mac2u64(). Signed-off-by: Li Zetao Acked-by: Geethasowjanya Akula Link: https://lore.kernel.org/r/20230808114504.4036008-4-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c index 7e20282c12d0..d2661e7fabdb 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c @@ -390,22 +390,6 @@ int rvu_mbox_handler_npc_get_field_hash_info(struct rvu *rvu, return 0; } -/** - * rvu_npc_exact_mac2u64 - utility function to convert mac address to u64. - * @mac_addr: MAC address. - * Return: mdata for exact match table. - */ -static u64 rvu_npc_exact_mac2u64(u8 *mac_addr) -{ - u64 mac = 0; - int index; - - for (index = ETH_ALEN - 1; index >= 0; index--) - mac |= ((u64)*mac_addr++) << (8 * index); - - return mac; -} - /** * rvu_exact_prepare_mdata - Make mdata for mcam entry * @mac: MAC address @@ -416,7 +400,7 @@ static u64 rvu_npc_exact_mac2u64(u8 *mac_addr) */ static u64 rvu_exact_prepare_mdata(u8 *mac, u16 chan, u16 ctype, u64 mask) { - u64 ldata = rvu_npc_exact_mac2u64(mac); + u64 ldata = ether_addr_to_u64(mac); /* Please note that mask is 48bit which excludes chan and ctype. * Increase mask bits if we need to include them as well. @@ -604,7 +588,7 @@ static u64 rvu_exact_prepare_table_entry(struct rvu *rvu, bool enable, u8 ctype, u16 chan, u8 *mac_addr) { - u64 ldata = rvu_npc_exact_mac2u64(mac_addr); + u64 ldata = ether_addr_to_u64(mac_addr); /* Enable or disable */ u64 mdata = FIELD_PREP(GENMASK_ULL(63, 63), enable ? 1 : 0); -- cgit From 383a4de3b44744b194848089db9e13ec98af2881 Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Mon, 7 Aug 2023 11:05:06 -0700 Subject: net/mlx5: Expose port.c/mlx5_query_module_num() function Make mlx5_query_module_num() defined in port.c, a non-static, so it can be used by other files. CC: Jean Delvare CC: Guenter Roeck Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Reviewed-by: Gal Pressman Signed-off-by: Saeed Mahameed Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230807180507.22984-2-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/port.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 43b0144121ca..d54afb07d972 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -176,6 +176,7 @@ static inline int mlx5_flexible_inlen(struct mlx5_core_dev *dev, size_t fixed, int mlx5_query_hca_caps(struct mlx5_core_dev *dev); int mlx5_query_board_id(struct mlx5_core_dev *dev); +int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num); int mlx5_cmd_init(struct mlx5_core_dev *dev); void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); int mlx5_cmd_enable(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 0daeb4b72cca..be70d1f23a5d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -271,7 +271,7 @@ void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, u16 *oper_mtu, } EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu); -static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) +int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) { u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0}; u32 out[MLX5_ST_SZ_DW(pmlp_reg)]; -- cgit From 1f507e80c700e31e358bf4213dc7e4dd614c7c72 Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Mon, 7 Aug 2023 11:05:07 -0700 Subject: net/mlx5: Expose NIC temperature via hardware monitoring kernel API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose NIC temperature by implementing hwmon kernel API, which turns current thermal zone kernel API to redundant. For each one of the supported and exposed thermal diode sensors, expose the following attributes: 1) Input temperature. 2) Highest temperature. 3) Temperature label: Depends on the firmware capability, if firmware doesn't support sensors naming, the fallback naming convention would be: "sensorX", where X is the HW spec (MTMP register) sensor index. 4) Temperature critical max value: refers to the high threshold of Warning Event. Will be exposed as `tempY_crit` hwmon attribute (RO attribute). For example for ConnectX5 HCA's this temperature value will be 105 Celsius, 10 degrees lower than the HW shutdown temperature). 5) Temperature reset history: resets highest temperature. For example, for dualport ConnectX5 NIC with a single IC thermal diode sensor will have 2 hwmon directories (one for each PCI function) under "/sys/class/hwmon/hwmon[X,Y]". Listing one of the directories above (hwmonX/Y) generates the corresponding output below: $ grep -H -d skip . /sys/class/hwmon/hwmon0/* Output ======================================================================= /sys/class/hwmon/hwmon0/name:mlx5 /sys/class/hwmon/hwmon0/temp1_crit:105000 /sys/class/hwmon/hwmon0/temp1_highest:48000 /sys/class/hwmon/hwmon0/temp1_input:46000 /sys/class/hwmon/hwmon0/temp1_label:asic grep: /sys/class/hwmon/hwmon0/temp1_reset_history: Permission denied In addition, displaying the sensors data via lm_sensors generates the corresponding output below: $ sensors Output ======================================================================= mlx5-pci-0800 Adapter: PCI adapter asic: +46.0°C (crit = +105.0°C, highest = +48.0°C) mlx5-pci-0801 Adapter: PCI adapter asic: +46.0°C (crit = +105.0°C, highest = +48.0°C) CC: Jean Delvare Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Reviewed-by: Gal Pressman Signed-off-by: Saeed Mahameed Acked-by: Guenter Roeck Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230807180507.22984-3-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 1 + drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/hwmon.c | 418 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/hwmon.h | 24 ++ drivers/net/ethernet/mellanox/mlx5/core/main.c | 8 +- drivers/net/ethernet/mellanox/mlx5/core/thermal.c | 114 ------ drivers/net/ethernet/mellanox/mlx5/core/thermal.h | 20 -- 7 files changed, 448 insertions(+), 139 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/hwmon.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/hwmon.h delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/thermal.c delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/thermal.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index bb1d7b039a7e..d537d517cabe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -12,6 +12,7 @@ config MLX5_CORE depends on MLXFW || !MLXFW depends on PTP_1588_CLOCK_OPTIONAL depends on PCI_HYPERV_INTERFACE || !PCI_HYPERV_INTERFACE + depends on HWMON || !HWMON help Core driver for low level functionality of the ConnectX-4 and Connect-IB cards by Mellanox Technologies. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 63a2f2bb80a6..946310390659 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -82,7 +82,7 @@ endif mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \ en/rep/bridge.o -mlx5_core-$(CONFIG_THERMAL) += thermal.o +mlx5_core-$(CONFIG_HWMON) += hwmon.o mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/hwmon.c b/drivers/net/ethernet/mellanox/mlx5/core/hwmon.c new file mode 100644 index 000000000000..353f81dccd1c --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/hwmon.c @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved + +#include +#include +#include +#include +#include +#include "mlx5_core.h" +#include "hwmon.h" + +#define CHANNELS_TYPE_NUM 2 /* chip channel and temp channel */ +#define CHIP_CONFIG_NUM 1 + +/* module 0 is mapped to sensor_index 64 in MTMP register */ +#define to_mtmp_module_sensor_idx(idx) (64 + (idx)) + +/* All temperatures retrieved in units of 0.125C. hwmon framework expect + * it in units of millidegrees C. Hence multiply values by 125. + */ +#define mtmp_temp_to_mdeg(temp) ((temp) * 125) + +struct temp_channel_desc { + u32 sensor_index; + char sensor_name[32]; +}; + +/* chip_channel_config and channel_info arrays must be 0-terminated, hence + 1 */ +struct mlx5_hwmon { + struct mlx5_core_dev *mdev; + struct device *hwmon_dev; + struct hwmon_channel_info chip_info; + u32 chip_channel_config[CHIP_CONFIG_NUM + 1]; + struct hwmon_channel_info temp_info; + u32 *temp_channel_config; + const struct hwmon_channel_info *channel_info[CHANNELS_TYPE_NUM + 1]; + struct hwmon_chip_info chip; + struct temp_channel_desc *temp_channel_desc; + u32 asic_platform_scount; + u32 module_scount; +}; + +static int mlx5_hwmon_query_mtmp(struct mlx5_core_dev *mdev, u32 sensor_index, u32 *mtmp_out) +{ + u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + + MLX5_SET(mtmp_reg, mtmp_in, sensor_index, sensor_index); + + return mlx5_core_access_reg(mdev, mtmp_in, sizeof(mtmp_in), + mtmp_out, MLX5_ST_SZ_BYTES(mtmp_reg), + MLX5_REG_MTMP, 0, 0); +} + +static int mlx5_hwmon_reset_max_temp(struct mlx5_core_dev *mdev, int sensor_index) +{ + u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + + MLX5_SET(mtmp_reg, mtmp_in, sensor_index, sensor_index); + MLX5_SET(mtmp_reg, mtmp_in, mtr, 1); + + return mlx5_core_access_reg(mdev, mtmp_in, sizeof(mtmp_in), + mtmp_out, sizeof(mtmp_out), + MLX5_REG_MTMP, 0, 0); +} + +static int mlx5_hwmon_enable_max_temp(struct mlx5_core_dev *mdev, int sensor_index) +{ + u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + int err; + + err = mlx5_hwmon_query_mtmp(mdev, sensor_index, mtmp_in); + if (err) + return err; + + MLX5_SET(mtmp_reg, mtmp_in, mte, 1); + return mlx5_core_access_reg(mdev, mtmp_in, sizeof(mtmp_in), + mtmp_out, sizeof(mtmp_out), + MLX5_REG_MTMP, 0, 1); +} + +static int mlx5_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long *val) +{ + struct mlx5_hwmon *hwmon = dev_get_drvdata(dev); + u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + int err; + + if (type != hwmon_temp) + return -EOPNOTSUPP; + + err = mlx5_hwmon_query_mtmp(hwmon->mdev, hwmon->temp_channel_desc[channel].sensor_index, + mtmp_out); + if (err) + return err; + + switch (attr) { + case hwmon_temp_input: + *val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, temperature)); + return 0; + case hwmon_temp_highest: + *val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, max_temperature)); + return 0; + case hwmon_temp_crit: + *val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, temp_threshold_hi)); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int mlx5_hwmon_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long val) +{ + struct mlx5_hwmon *hwmon = dev_get_drvdata(dev); + + if (type != hwmon_temp || attr != hwmon_temp_reset_history) + return -EOPNOTSUPP; + + return mlx5_hwmon_reset_max_temp(hwmon->mdev, + hwmon->temp_channel_desc[channel].sensor_index); +} + +static umode_t mlx5_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, + int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_highest: + case hwmon_temp_crit: + case hwmon_temp_label: + return 0444; + case hwmon_temp_reset_history: + return 0200; + default: + return 0; + } +} + +static int mlx5_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, const char **str) +{ + struct mlx5_hwmon *hwmon = dev_get_drvdata(dev); + + if (type != hwmon_temp || attr != hwmon_temp_label) + return -EOPNOTSUPP; + + *str = (const char *)hwmon->temp_channel_desc[channel].sensor_name; + return 0; +} + +static const struct hwmon_ops mlx5_hwmon_ops = { + .read = mlx5_hwmon_read, + .read_string = mlx5_hwmon_read_string, + .is_visible = mlx5_hwmon_is_visible, + .write = mlx5_hwmon_write, +}; + +static int mlx5_hwmon_init_channels_names(struct mlx5_hwmon *hwmon) +{ + u32 i; + + for (i = 0; i < hwmon->asic_platform_scount + hwmon->module_scount; i++) { + u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; + char *sensor_name; + int err; + + err = mlx5_hwmon_query_mtmp(hwmon->mdev, hwmon->temp_channel_desc[i].sensor_index, + mtmp_out); + if (err) + return err; + + sensor_name = MLX5_ADDR_OF(mtmp_reg, mtmp_out, sensor_name_hi); + if (!*sensor_name) { + snprintf(hwmon->temp_channel_desc[i].sensor_name, + sizeof(hwmon->temp_channel_desc[i].sensor_name), "sensor%u", + hwmon->temp_channel_desc[i].sensor_index); + continue; + } + + memcpy(&hwmon->temp_channel_desc[i].sensor_name, sensor_name, + MLX5_FLD_SZ_BYTES(mtmp_reg, sensor_name_hi) + + MLX5_FLD_SZ_BYTES(mtmp_reg, sensor_name_lo)); + } + + return 0; +} + +static int mlx5_hwmon_get_module_sensor_index(struct mlx5_core_dev *mdev, u32 *module_index) +{ + int module_num; + int err; + + err = mlx5_query_module_num(mdev, &module_num); + if (err) + return err; + + *module_index = to_mtmp_module_sensor_idx(module_num); + + return 0; +} + +static int mlx5_hwmon_init_sensors_indexes(struct mlx5_hwmon *hwmon, u64 sensor_map) +{ + DECLARE_BITMAP(smap, BITS_PER_TYPE(sensor_map)); + unsigned long bit_pos; + int err = 0; + int i = 0; + + bitmap_from_u64(smap, sensor_map); + + for_each_set_bit(bit_pos, smap, BITS_PER_TYPE(sensor_map)) { + hwmon->temp_channel_desc[i].sensor_index = bit_pos; + i++; + } + + if (hwmon->module_scount) + err = mlx5_hwmon_get_module_sensor_index(hwmon->mdev, + &hwmon->temp_channel_desc[i].sensor_index); + + return err; +} + +static void mlx5_hwmon_channel_info_init(struct mlx5_hwmon *hwmon) +{ + int i; + + hwmon->channel_info[0] = &hwmon->chip_info; + hwmon->channel_info[1] = &hwmon->temp_info; + + hwmon->chip_channel_config[0] = HWMON_C_REGISTER_TZ; + hwmon->chip_info.config = (const u32 *)hwmon->chip_channel_config; + hwmon->chip_info.type = hwmon_chip; + + for (i = 0; i < hwmon->asic_platform_scount + hwmon->module_scount; i++) + hwmon->temp_channel_config[i] = HWMON_T_INPUT | HWMON_T_HIGHEST | HWMON_T_CRIT | + HWMON_T_RESET_HISTORY | HWMON_T_LABEL; + + hwmon->temp_info.config = (const u32 *)hwmon->temp_channel_config; + hwmon->temp_info.type = hwmon_temp; +} + +static int mlx5_hwmon_is_module_mon_cap(struct mlx5_core_dev *mdev, bool *mon_cap) +{ + u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)]; + u32 module_index; + int err; + + err = mlx5_hwmon_get_module_sensor_index(mdev, &module_index); + if (err) + return err; + + err = mlx5_hwmon_query_mtmp(mdev, module_index, mtmp_out); + if (err) + return err; + + if (MLX5_GET(mtmp_reg, mtmp_out, temperature)) + *mon_cap = true; + + return 0; +} + +static int mlx5_hwmon_get_sensors_count(struct mlx5_core_dev *mdev, u32 *asic_platform_scount) +{ + u32 mtcap_out[MLX5_ST_SZ_DW(mtcap_reg)] = {}; + u32 mtcap_in[MLX5_ST_SZ_DW(mtcap_reg)] = {}; + int err; + + err = mlx5_core_access_reg(mdev, mtcap_in, sizeof(mtcap_in), + mtcap_out, sizeof(mtcap_out), + MLX5_REG_MTCAP, 0, 0); + if (err) + return err; + + *asic_platform_scount = MLX5_GET(mtcap_reg, mtcap_out, sensor_count); + + return 0; +} + +static void mlx5_hwmon_free(struct mlx5_hwmon *hwmon) +{ + if (!hwmon) + return; + + kfree(hwmon->temp_channel_config); + kfree(hwmon->temp_channel_desc); + kfree(hwmon); +} + +static struct mlx5_hwmon *mlx5_hwmon_alloc(struct mlx5_core_dev *mdev) +{ + struct mlx5_hwmon *hwmon; + bool mon_cap = false; + u32 sensors_count; + int err; + + hwmon = kzalloc(sizeof(*mdev->hwmon), GFP_KERNEL); + if (!hwmon) + return ERR_PTR(-ENOMEM); + + err = mlx5_hwmon_get_sensors_count(mdev, &hwmon->asic_platform_scount); + if (err) + goto err_free_hwmon; + + /* check if module sensor has thermal mon cap. if yes, allocate channel desc for it */ + err = mlx5_hwmon_is_module_mon_cap(mdev, &mon_cap); + if (err) + goto err_free_hwmon; + + hwmon->module_scount = mon_cap ? 1 : 0; + sensors_count = hwmon->asic_platform_scount + hwmon->module_scount; + hwmon->temp_channel_desc = kcalloc(sensors_count, sizeof(*hwmon->temp_channel_desc), + GFP_KERNEL); + if (!hwmon->temp_channel_desc) { + err = -ENOMEM; + goto err_free_hwmon; + } + + /* sensors configuration values array, must be 0-terminated hence, + 1 */ + hwmon->temp_channel_config = kcalloc(sensors_count + 1, sizeof(*hwmon->temp_channel_config), + GFP_KERNEL); + if (!hwmon->temp_channel_config) { + err = -ENOMEM; + goto err_free_temp_channel_desc; + } + + hwmon->mdev = mdev; + + return hwmon; + +err_free_temp_channel_desc: + kfree(hwmon->temp_channel_desc); +err_free_hwmon: + kfree(hwmon); + return ERR_PTR(err); +} + +static int mlx5_hwmon_dev_init(struct mlx5_hwmon *hwmon) +{ + u32 mtcap_out[MLX5_ST_SZ_DW(mtcap_reg)] = {}; + u32 mtcap_in[MLX5_ST_SZ_DW(mtcap_reg)] = {}; + int err; + int i; + + err = mlx5_core_access_reg(hwmon->mdev, mtcap_in, sizeof(mtcap_in), + mtcap_out, sizeof(mtcap_out), + MLX5_REG_MTCAP, 0, 0); + if (err) + return err; + + mlx5_hwmon_channel_info_init(hwmon); + mlx5_hwmon_init_sensors_indexes(hwmon, MLX5_GET64(mtcap_reg, mtcap_out, sensor_map)); + err = mlx5_hwmon_init_channels_names(hwmon); + if (err) + return err; + + for (i = 0; i < hwmon->asic_platform_scount + hwmon->module_scount; i++) { + err = mlx5_hwmon_enable_max_temp(hwmon->mdev, + hwmon->temp_channel_desc[i].sensor_index); + if (err) + return err; + } + + hwmon->chip.ops = &mlx5_hwmon_ops; + hwmon->chip.info = (const struct hwmon_channel_info **)hwmon->channel_info; + + return 0; +} + +int mlx5_hwmon_dev_register(struct mlx5_core_dev *mdev) +{ + struct device *dev = mdev->device; + struct mlx5_hwmon *hwmon; + int err; + + if (!MLX5_CAP_MCAM_REG(mdev, mtmp)) + return 0; + + hwmon = mlx5_hwmon_alloc(mdev); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); + + err = mlx5_hwmon_dev_init(hwmon); + if (err) + goto err_free_hwmon; + + hwmon->hwmon_dev = hwmon_device_register_with_info(dev, "mlx5", + hwmon, + &hwmon->chip, + NULL); + if (IS_ERR(hwmon->hwmon_dev)) { + err = PTR_ERR(hwmon->hwmon_dev); + goto err_free_hwmon; + } + + mdev->hwmon = hwmon; + return 0; + +err_free_hwmon: + mlx5_hwmon_free(hwmon); + return err; +} + +void mlx5_hwmon_dev_unregister(struct mlx5_core_dev *mdev) +{ + struct mlx5_hwmon *hwmon = mdev->hwmon; + + if (!hwmon) + return; + + hwmon_device_unregister(hwmon->hwmon_dev); + mlx5_hwmon_free(hwmon); + mdev->hwmon = NULL; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/hwmon.h b/drivers/net/ethernet/mellanox/mlx5/core/hwmon.h new file mode 100644 index 000000000000..999654a9b9da --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/hwmon.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved + */ +#ifndef __MLX5_HWMON_H__ +#define __MLX5_HWMON_H__ + +#include + +#if IS_ENABLED(CONFIG_HWMON) + +int mlx5_hwmon_dev_register(struct mlx5_core_dev *mdev); +void mlx5_hwmon_dev_unregister(struct mlx5_core_dev *mdev); + +#else +static inline int mlx5_hwmon_dev_register(struct mlx5_core_dev *mdev) +{ + return 0; +} + +static inline void mlx5_hwmon_dev_unregister(struct mlx5_core_dev *mdev) {} + +#endif + +#endif /* __MLX5_HWMON_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index db2e8e4f848d..0389e84f9815 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -49,7 +49,6 @@ #include #include #include "mlx5_core.h" -#include "thermal.h" #include "lib/eq.h" #include "fs_core.h" #include "lib/mpfs.h" @@ -73,6 +72,7 @@ #include "sf/dev/dev.h" #include "sf/sf.h" #include "mlx5_irq.h" +#include "hwmon.h" MODULE_AUTHOR("Eli Cohen "); MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver"); @@ -1930,9 +1930,9 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (err) dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); - err = mlx5_thermal_init(dev); + err = mlx5_hwmon_dev_register(dev); if (err) - dev_err(&pdev->dev, "mlx5_thermal_init failed with error code %d\n", err); + mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err); pci_save_state(pdev); devlink_register(devlink); @@ -1964,7 +1964,7 @@ static void remove_one(struct pci_dev *pdev) mlx5_drain_health_wq(dev); devlink_unregister(devlink); mlx5_sriov_disable(pdev, false); - mlx5_thermal_uninit(dev); + mlx5_hwmon_dev_unregister(dev); mlx5_crdump_disable(dev); mlx5_uninit_one(dev); mlx5_pci_close(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c deleted file mode 100644 index 52199d39657e..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB -// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. - -#include -#include -#include -#include -#include -#include -#include "mlx5_core.h" -#include "thermal.h" - -#define MLX5_THERMAL_POLL_INT_MSEC 1000 -#define MLX5_THERMAL_NUM_TRIPS 0 -#define MLX5_THERMAL_ASIC_SENSOR_INDEX 0 - -/* Bit string indicating the writeablility of trip points if any */ -#define MLX5_THERMAL_TRIP_MASK (BIT(MLX5_THERMAL_NUM_TRIPS) - 1) - -struct mlx5_thermal { - struct mlx5_core_dev *mdev; - struct thermal_zone_device *tzdev; -}; - -static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p_temp) -{ - u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; - u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {}; - int err; - - MLX5_SET(mtmp_reg, mtmp_in, sensor_index, id); - - err = mlx5_core_access_reg(mdev, mtmp_in, sizeof(mtmp_in), - mtmp_out, sizeof(mtmp_out), - MLX5_REG_MTMP, 0, 0); - - if (err) - return err; - - *p_temp = MLX5_GET(mtmp_reg, mtmp_out, temperature); - - return 0; -} - -static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev, - int *p_temp) -{ - struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev); - struct mlx5_core_dev *mdev = thermal->mdev; - int err; - - err = mlx5_thermal_get_mtmp_temp(mdev, MLX5_THERMAL_ASIC_SENSOR_INDEX, p_temp); - - if (err) - return err; - - /* The unit of temp returned is in 0.125 C. The thermal - * framework expects the value in 0.001 C. - */ - *p_temp *= 125; - - return 0; -} - -static struct thermal_zone_device_ops mlx5_thermal_ops = { - .get_temp = mlx5_thermal_get_temp, -}; - -int mlx5_thermal_init(struct mlx5_core_dev *mdev) -{ - char data[THERMAL_NAME_LENGTH]; - struct mlx5_thermal *thermal; - int err; - - if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev)) - return 0; - - err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device)); - if (err < 0 || err >= sizeof(data)) { - mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err); - return -EINVAL; - } - - thermal = kzalloc(sizeof(*thermal), GFP_KERNEL); - if (!thermal) - return -ENOMEM; - - thermal->mdev = mdev; - thermal->tzdev = thermal_zone_device_register_with_trips(data, - NULL, - MLX5_THERMAL_NUM_TRIPS, - MLX5_THERMAL_TRIP_MASK, - thermal, - &mlx5_thermal_ops, - NULL, 0, MLX5_THERMAL_POLL_INT_MSEC); - if (IS_ERR(thermal->tzdev)) { - err = PTR_ERR(thermal->tzdev); - mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err); - kfree(thermal); - return err; - } - - mdev->thermal = thermal; - return 0; -} - -void mlx5_thermal_uninit(struct mlx5_core_dev *mdev) -{ - if (!mdev->thermal) - return; - - thermal_zone_device_unregister(mdev->thermal->tzdev); - kfree(mdev->thermal); -} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/thermal.h b/drivers/net/ethernet/mellanox/mlx5/core/thermal.h deleted file mode 100644 index 7d752c122192..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/thermal.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB - * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. - */ -#ifndef __MLX5_THERMAL_DRIVER_H -#define __MLX5_THERMAL_DRIVER_H - -#if IS_ENABLED(CONFIG_THERMAL) -int mlx5_thermal_init(struct mlx5_core_dev *mdev); -void mlx5_thermal_uninit(struct mlx5_core_dev *mdev); -#else -static inline int mlx5_thermal_init(struct mlx5_core_dev *mdev) -{ - mdev->thermal = NULL; - return 0; -} - -static inline void mlx5_thermal_uninit(struct mlx5_core_dev *mdev) { } -#endif - -#endif /* __MLX5_THERMAL_DRIVER_H */ -- cgit From b63e78fca889e07931ec8f259701718a24e5052e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 7 Aug 2023 22:33:20 +0300 Subject: net: netdevsim: use mock PHC driver I'd like to make netdevsim offload tc-taprio, but currently, this Qdisc emits a ETHTOOL_GET_TS_INFO call to the driver to make sure that it has a PTP clock, so that it is reasonably capable of offloading the schedule. By using the mock PHC driver, that becomes possible. Hardware timestamping is not necessary, and netdevsim does not support packet I/O anyway. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230807193324.4128292-8-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/Kconfig | 1 + drivers/net/netdevsim/ethtool.c | 11 +++++++++++ drivers/net/netdevsim/netdev.c | 11 ++++++++++- drivers/net/netdevsim/netdevsim.h | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 368c6f5b327e..4953c1494723 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -592,6 +592,7 @@ config NETDEVSIM depends on INET depends on IPV6 || IPV6=n depends on PSAMPLE || PSAMPLE=n + depends on PTP_1588_CLOCK_MOCK || PTP_1588_CLOCK_MOCK=n select NET_DEVLINK help This driver is a developer testing tool and software model that can diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c index ffd9f84b6644..bd546d4d26c6 100644 --- a/drivers/net/netdevsim/ethtool.c +++ b/drivers/net/netdevsim/ethtool.c @@ -140,6 +140,16 @@ nsim_set_fecparam(struct net_device *dev, struct ethtool_fecparam *fecparam) return 0; } +static int nsim_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) +{ + struct netdevsim *ns = netdev_priv(dev); + + info->phc_index = mock_phc_index(ns->phc); + + return 0; +} + static const struct ethtool_ops nsim_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_ALL_PARAMS, .get_pause_stats = nsim_get_pause_stats, @@ -153,6 +163,7 @@ static const struct ethtool_ops nsim_ethtool_ops = { .set_channels = nsim_set_channels, .get_fecparam = nsim_get_fecparam, .set_fecparam = nsim_set_fecparam, + .get_ts_info = nsim_get_ts_info, }; static void nsim_ethtool_ring_init(struct netdevsim *ns) diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 0c8daeb0d62b..2a4a0c4065cf 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -291,13 +291,19 @@ static void nsim_setup(struct net_device *dev) static int nsim_init_netdevsim(struct netdevsim *ns) { + struct mock_phc *phc; int err; + phc = mock_phc_create(&ns->nsim_bus_dev->dev); + if (IS_ERR(phc)) + return PTR_ERR(phc); + + ns->phc = phc; ns->netdev->netdev_ops = &nsim_netdev_ops; err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev); if (err) - return err; + goto err_phc_destroy; rtnl_lock(); err = nsim_bpf_init(ns); @@ -320,6 +326,8 @@ err_ipsec_teardown: err_utn_destroy: rtnl_unlock(); nsim_udp_tunnels_info_destroy(ns->netdev); +err_phc_destroy: + mock_phc_destroy(ns->phc); return err; } @@ -383,6 +391,7 @@ void nsim_destroy(struct netdevsim *ns) rtnl_unlock(); if (nsim_dev_port_is_pf(ns->nsim_dev_port)) nsim_udp_tunnels_info_destroy(dev); + mock_phc_destroy(ns->phc); free_netdev(dev); } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 7be98b7dcca9..028c825b86db 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,7 @@ struct netdevsim { struct net_device *netdev; struct nsim_dev *nsim_dev; struct nsim_dev_port *nsim_dev_port; + struct mock_phc *phc; u64 tx_packets; u64 tx_bytes; -- cgit From 35da47fe1c4766451def03a1b4f59c6b13a9373c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 7 Aug 2023 22:33:21 +0300 Subject: net: netdevsim: mimic tc-taprio offload To be able to use netdevsim for tc-testing with an offloaded tc-taprio schedule, it needs to report a PTP clock (which it now does), and to accept ndo_setup_tc(TC_SETUP_QDISC_TAPRIO) calls. Since netdevsim has no packet I/O, this doesn't do anything intelligent, it only allows taprio offload code paths to go through some level of automated testing. Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230807193324.4128292-9-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/netdevsim/netdev.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 2a4a0c4065cf..2eac92f49631 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -209,6 +209,31 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state) return 0; } +static void nsim_taprio_stats(struct tc_taprio_qopt_stats *stats) +{ + stats->window_drops = 0; + stats->tx_overruns = 0; +} + +static int nsim_setup_tc_taprio(struct net_device *dev, + struct tc_taprio_qopt_offload *offload) +{ + int err = 0; + + switch (offload->cmd) { + case TAPRIO_CMD_REPLACE: + case TAPRIO_CMD_DESTROY: + break; + case TAPRIO_CMD_STATS: + nsim_taprio_stats(&offload->stats); + break; + default: + err = -EOPNOTSUPP; + } + + return err; +} + static LIST_HEAD(nsim_block_cb_list); static int @@ -217,6 +242,8 @@ nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data) struct netdevsim *ns = netdev_priv(dev); switch (type) { + case TC_SETUP_QDISC_TAPRIO: + return nsim_setup_tc_taprio(dev, type_data); case TC_SETUP_BLOCK: return flow_block_cb_setup_simple(type_data, &nsim_block_cb_list, -- cgit From e55c50eac36a704e9e867257f50cd482e8256755 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 1 Aug 2023 23:05:31 -0600 Subject: i40e: Replace one-element array with flex-array member in struct i40e_package_header One-element and zero-length arrays are deprecated. So, replace one-element array in struct i40e_package_header with flexible-array member. The `+ sizeof(u32)` adjustments ensure that there are no differences in binary output. Link: https://github.com/KSPP/linux/issues/335 Signed-off-by: Gustavo A. R. Silva Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_ddp.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ddp.c b/drivers/net/ethernet/intel/i40e/i40e_ddp.c index 969120587cad..0e72abd178ae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ddp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ddp.c @@ -220,7 +220,7 @@ static bool i40e_ddp_is_pkg_hdr_valid(struct net_device *netdev, netdev_err(netdev, "Invalid DDP profile - size is bigger than 4G"); return false; } - if (size < (sizeof(struct i40e_package_header) + + if (size < (sizeof(struct i40e_package_header) + sizeof(u32) + sizeof(struct i40e_metadata_segment) + sizeof(u32) * 2)) { netdev_err(netdev, "Invalid DDP profile - size is too small."); return false; @@ -281,7 +281,7 @@ int i40e_ddp_load(struct net_device *netdev, const u8 *data, size_t size, if (!i40e_ddp_is_pkg_hdr_valid(netdev, pkg_hdr, size)) return -EINVAL; - if (size < (sizeof(struct i40e_package_header) + + if (size < (sizeof(struct i40e_package_header) + sizeof(u32) + sizeof(struct i40e_metadata_segment) + sizeof(u32) * 2)) { netdev_err(netdev, "Invalid DDP recipe size."); return -EINVAL; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 5f61546f50d8..08ad83ee4a43 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1455,7 +1455,7 @@ struct i40e_ddp_version { struct i40e_package_header { struct i40e_ddp_version version; u32 segment_count; - u32 segment_offset[1]; + u32 segment_offset[]; }; /* Generic segment header */ -- cgit From fbfa49f92484a63574b692069f09cfe9b79ec565 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 1 Aug 2023 23:05:59 -0600 Subject: i40e: Replace one-element array with flex-array member in struct i40e_profile_segment One-element and zero-length arrays are deprecated. So, replace one-element array in struct i40e_profile_segment with flexible-array member. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/335 Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Tested-by: Justin Stitt Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 08ad83ee4a43..6cbc3dbf9b03 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1486,7 +1486,7 @@ struct i40e_profile_segment { struct i40e_ddp_version version; char name[I40E_DDP_NAME_SIZE]; u32 device_table_count; - struct i40e_device_id_entry device_table[1]; + struct i40e_device_id_entry device_table[]; }; struct i40e_section_table { -- cgit From ff1a724c4f6a693d5e829903d80a13e48cd3e64f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 1 Aug 2023 23:06:30 -0600 Subject: i40e: Replace one-element array with flex-array member in struct i40e_section_table One-element and zero-length arrays are deprecated. So, replace one-element array in struct i40e_section_table with flexible-array member. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/335 Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 6cbc3dbf9b03..8ad878ff02cf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1491,7 +1491,7 @@ struct i40e_profile_segment { struct i40e_section_table { u32 section_count; - u32 section_offset[1]; + u32 section_offset[]; }; struct i40e_profile_section_header { -- cgit From 4bb28b27040bb070477ce9610173e7360b02ba9b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 1 Aug 2023 23:07:06 -0600 Subject: i40e: Replace one-element array with flex-array member in struct i40e_profile_aq_section One-element and zero-length arrays are deprecated. So, replace one-element array in struct i40e_profile_aq_section with flexible-array member. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/335 Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 8ad878ff02cf..232131bedc3e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1523,7 +1523,7 @@ struct i40e_profile_aq_section { u16 flags; u8 param[16]; u16 datalen; - u8 data[1]; + u8 data[]; }; struct i40e_profile_info { -- cgit From 1fc04a0b973392df5975901f56addc913d2c8f4d Mon Sep 17 00:00:00 2001 From: Shenwei Wang Date: Mon, 7 Aug 2023 11:07:15 -0500 Subject: net: stmmac: add new mode parameter for fix_mac_speed A mode parameter has been added to the callback function of fix_mac_speed to indicate the physical layer type. The mode can be one the following: MLO_AN_PHY - Conventional PHY MLO_AN_FIXED - Fixed-link mode MLO_AN_INBAND - In-band protocol Signed-off-by: Shenwei Wang Link: https://lore.kernel.org/r/20230807160716.259072-2-shenwei.wang@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 8 ++++---- drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 74c10373cc39..61ebf36da13d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -178,7 +178,7 @@ static void dwc_qos_remove(struct platform_device *pdev) #define AUTO_CAL_STATUS 0x880c #define AUTO_CAL_STATUS_ACTIVE BIT(31) -static void tegra_eqos_fix_speed(void *priv, unsigned int speed) +static void tegra_eqos_fix_speed(void *priv, unsigned int speed, unsigned int mode) { struct tegra_eqos *eqos = priv; unsigned long rate = 125000000; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 645a9454a490..7c4f3ad88bdc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -178,7 +178,7 @@ static void imx_dwmac_exit(struct platform_device *pdev, void *priv) /* nothing to do now */ } -static void imx_dwmac_fix_speed(void *priv, unsigned int speed) +static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mode) { struct plat_stmmacenet_data *plat_dat; struct imx_priv_data *dwmac = priv; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c index a5e639ab0b9e..d352a14f9d48 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c @@ -22,13 +22,13 @@ struct intel_dwmac { }; struct intel_dwmac_data { - void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode); unsigned long ptp_ref_clk_rate; unsigned long tx_clk_rate; bool tx_clk_en; }; -static void kmb_eth_fix_mac_speed(void *priv, unsigned int speed) +static void kmb_eth_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct intel_dwmac *dwmac = priv; unsigned long rate; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index e39406df8516..9b0200749109 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -257,7 +257,7 @@ static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac) return PTR_ERR_OR_ZERO(gmac->qsgmii_csr); } -static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed) +static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct ipq806x_gmac *gmac = priv; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 7aa5e6bc04eb..959f88c6da16 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -22,7 +22,7 @@ struct meson_dwmac { void __iomem *reg; }; -static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) +static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct meson_dwmac *dwmac = priv; unsigned int val; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 5b3df27035ec..d3bf42d0fceb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -630,7 +630,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) return ethqos->configure_func(ethqos); } -static void ethqos_fix_mac_speed(void *priv, unsigned int speed) +static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct qcom_ethqos *ethqos = priv; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 35789cb549f7..d920a50dd16c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1785,7 +1785,7 @@ static void rk_gmac_powerdown(struct rk_priv_data *gmac) gmac_clk_enable(gmac, false); } -static void rk_fix_speed(void *priv, unsigned int speed) +static void rk_fix_speed(void *priv, unsigned int speed, unsigned int mode) { struct rk_priv_data *bsp_priv = priv; struct device *dev = &bsp_priv->pdev->dev; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6267bcb60206..7db176e8691f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -61,7 +61,7 @@ struct socfpga_dwmac { struct mdio_device *pcs_mdiodev; }; -static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) +static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; void __iomem *splitter_base = dwmac->splitter_base; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c index b1c5f2527c0d..892612564694 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c @@ -24,7 +24,7 @@ struct starfive_dwmac { struct clk *clk_tx; }; -static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed) +static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct starfive_dwmac *dwmac = priv; unsigned long rate; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index ef03e4669491..0d653bbb931b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -103,11 +103,11 @@ struct sti_dwmac { struct regmap *regmap; bool gmac_en; u32 speed; - void (*fix_retime_src)(void *priv, unsigned int speed); + void (*fix_retime_src)(void *priv, unsigned int speed, unsigned int mode); }; struct sti_dwmac_of_data { - void (*fix_retime_src)(void *priv, unsigned int speed); + void (*fix_retime_src)(void *priv, unsigned int speed, unsigned int mode); }; static u32 phy_intf_sels[] = { @@ -135,7 +135,7 @@ static u32 stih4xx_tx_retime_val[] = { | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK, }; -static void stih4xx_fix_retime_src(void *priv, u32 spd) +static void stih4xx_fix_retime_src(void *priv, u32 spd, unsigned int mode) { struct sti_dwmac *dwmac = priv; u32 src = dwmac->tx_retime_src; @@ -187,7 +187,7 @@ static int sti_dwmac_set_mode(struct sti_dwmac *dwmac) val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; regmap_update_bits(regmap, reg, ENMII_MASK, val); - dwmac->fix_retime_src(dwmac, dwmac->speed); + dwmac->fix_retime_src(dwmac, dwmac->speed, 0); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index 50963e91c347..beceeae579bf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c @@ -72,7 +72,7 @@ static void sun7i_gmac_exit(struct platform_device *pdev, void *priv) regulator_disable(gmac->regulator); } -static void sun7i_fix_speed(void *priv, unsigned int speed) +static void sun7i_fix_speed(void *priv, unsigned int speed, unsigned int mode) { struct sunxi_priv_data *gmac = priv; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c index a8731ce0fff0..22d113fb8e09 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c @@ -54,7 +54,7 @@ struct visconti_eth { spinlock_t lock; /* lock to protect register update */ }; -static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed) +static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) { struct visconti_eth *dwmac = priv; struct net_device *netdev = dev_get_drvdata(dwmac->dev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fcab363d8dfa..351eca6109e0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1064,7 +1064,7 @@ static void stmmac_mac_link_up(struct phylink_config *config, priv->speed = speed; if (priv->plat->fix_mac_speed) - priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed); + priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed, mode); if (!duplex) ctrl &= ~priv->hw->link.duplex; -- cgit From 4fa6c976158b20eb7da94d35dfe34deec4b2a504 Mon Sep 17 00:00:00 2001 From: Shenwei Wang Date: Mon, 7 Aug 2023 11:07:16 -0500 Subject: net: stmmac: dwmac-imx: pause the TXC clock in fixed-link When using a fixed-link setup, certain devices like the SJA1105 require a small pause in the TXC clock line to enable their internal tunable delay line (TDL). To satisfy this requirement, this patch temporarily disables the TX clock, and restarts it after a required period. This provides the required silent interval on the clock line for SJA1105 to complete the frequency transition and enable the internal TDLs. This action occurs before the link is built up, so it does not impact a normal device too. There is no need to identify if the connected device is an SJA1105 alike or not during the implementation. So far we have only enabled this feature on the i.MX93 platform. Signed-off-by: Shenwei Wang Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20230807160716.259072-3-shenwei.wang@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 7c4f3ad88bdc..535856fffaea 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -31,6 +31,7 @@ #define GPR_ENET_QOS_RGMII_EN (0x1 << 21) #define MX93_GPR_ENET_QOS_INTF_MODE_MASK GENMASK(3, 0) +#define MX93_GPR_ENET_QOS_INTF_MASK GENMASK(3, 1) #define MX93_GPR_ENET_QOS_INTF_SEL_MII (0x0 << 1) #define MX93_GPR_ENET_QOS_INTF_SEL_RMII (0x4 << 1) #define MX93_GPR_ENET_QOS_INTF_SEL_RGMII (0x1 << 1) @@ -39,6 +40,7 @@ #define DMA_BUS_MODE 0x00001000 #define DMA_BUS_MODE_SFT_RESET (0x1 << 0) #define RMII_RESET_SPEED (0x3 << 14) +#define CTRL_SPEED_MASK GENMASK(15, 14) struct imx_dwmac_ops { u32 addr_width; @@ -47,6 +49,7 @@ struct imx_dwmac_ops { int (*fix_soc_reset)(void *priv, void __iomem *ioaddr); int (*set_intf_mode)(struct plat_stmmacenet_data *plat_dat); + void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode); }; struct imx_priv_data { @@ -56,6 +59,7 @@ struct imx_priv_data { struct regmap *intf_regmap; u32 intf_reg_off; bool rmii_refclk_ext; + void __iomem *base_addr; const struct imx_dwmac_ops *ops; struct plat_stmmacenet_data *plat_dat; @@ -212,6 +216,41 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); } +static void imx93_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mode) +{ + struct imx_priv_data *dwmac = priv; + unsigned int iface; + int ctrl, old_ctrl; + + imx_dwmac_fix_speed(priv, speed, mode); + + if (!dwmac || mode != MLO_AN_FIXED) + return; + + if (regmap_read(dwmac->intf_regmap, dwmac->intf_reg_off, &iface)) + return; + + iface &= MX93_GPR_ENET_QOS_INTF_MASK; + if (iface != MX93_GPR_ENET_QOS_INTF_SEL_RGMII) + return; + + old_ctrl = readl(dwmac->base_addr + MAC_CTRL_REG); + ctrl = old_ctrl & ~CTRL_SPEED_MASK; + regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, + MX93_GPR_ENET_QOS_INTF_MODE_MASK, 0); + writel(ctrl, dwmac->base_addr + MAC_CTRL_REG); + + /* Ensure the settings for CTRL are applied. */ + readl(dwmac->base_addr + MAC_CTRL_REG); + + usleep_range(10, 20); + iface |= MX93_GPR_ENET_QOS_CLK_GEN_EN; + regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off, + MX93_GPR_ENET_QOS_INTF_MODE_MASK, iface); + + writel(old_ctrl, dwmac->base_addr + MAC_CTRL_REG); +} + static int imx_dwmac_mx93_reset(void *priv, void __iomem *ioaddr) { struct plat_stmmacenet_data *plat_dat = priv; @@ -322,6 +361,7 @@ static int imx_dwmac_probe(struct platform_device *pdev) plat_dat->fix_mac_speed = imx_dwmac_fix_speed; plat_dat->bsp_priv = dwmac; dwmac->plat_dat = plat_dat; + dwmac->base_addr = stmmac_res.addr; ret = imx_dwmac_clks_config(dwmac, true); if (ret) @@ -331,6 +371,8 @@ static int imx_dwmac_probe(struct platform_device *pdev) if (ret) goto err_dwmac_init; + if (dwmac->ops->fix_mac_speed) + plat_dat->fix_mac_speed = dwmac->ops->fix_mac_speed; dwmac->plat_dat->fix_soc_reset = dwmac->ops->fix_soc_reset; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); @@ -368,6 +410,7 @@ static struct imx_dwmac_ops imx93_dwmac_data = { .mac_rgmii_txclk_auto_adj = true, .set_intf_mode = imx93_set_intf_mode, .fix_soc_reset = imx_dwmac_mx93_reset, + .fix_mac_speed = imx93_dwmac_fix_speed, }; static const struct of_device_id imx_dwmac_match[] = { -- cgit From 215c44fa69d7a873e058b2e1c451c12025d94bee Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Tue, 8 Aug 2023 10:12:38 +0800 Subject: net: mhi: Remove redundant initialization owner in mhi_net_driver The module_mhi_driver() will set "THIS_MODULE" to driver.owner when register a mhi_driver driver, so it is redundant initialization to set driver.owner in the statement. Remove it for clean code. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230808021238.2975585-1-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/mhi_net.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/mhi_net.c b/drivers/net/mhi_net.c index 3d322ac4f6a5..ae169929a9d8 100644 --- a/drivers/net/mhi_net.c +++ b/drivers/net/mhi_net.c @@ -403,7 +403,6 @@ static struct mhi_driver mhi_net_driver = { .id_table = mhi_net_id_table, .driver = { .name = "mhi_net", - .owner = THIS_MODULE, }, }; -- cgit From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 8 Aug 2023 23:04:34 +0200 Subject: net: phy: phy_device: Call into the PHY driver to set LED offload Linux LEDs can be requested to perform hardware accelerated blinking to indicate link, RX, TX etc. Pass the rules for blinking to the PHY driver, if it implements the ops needed to determine if a given pattern can be offloaded, to offload it, and what the current offload is. Additionally implement the op needed to get what device the LED is for. Reviewed-by: Simon Horman Signed-off-by: Andrew Lunn Tested-by: Daniel Golle Link: https://lore.kernel.org/r/20230808210436.838995-3-andrew@lunn.ch Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3e9909b30938..17cb3e07216a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3020,6 +3020,61 @@ static int phy_led_blink_set(struct led_classdev *led_cdev, return err; } +static __maybe_unused struct device * +phy_led_hw_control_get_device(struct led_classdev *led_cdev) +{ + struct phy_led *phyled = to_phy_led(led_cdev); + struct phy_device *phydev = phyled->phydev; + + if (phydev->attached_dev) + return &phydev->attached_dev->dev; + return NULL; +} + +static int __maybe_unused +phy_led_hw_control_get(struct led_classdev *led_cdev, + unsigned long *rules) +{ + struct phy_led *phyled = to_phy_led(led_cdev); + struct phy_device *phydev = phyled->phydev; + int err; + + mutex_lock(&phydev->lock); + err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules); + mutex_unlock(&phydev->lock); + + return err; +} + +static int __maybe_unused +phy_led_hw_control_set(struct led_classdev *led_cdev, + unsigned long rules) +{ + struct phy_led *phyled = to_phy_led(led_cdev); + struct phy_device *phydev = phyled->phydev; + int err; + + mutex_lock(&phydev->lock); + err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules); + mutex_unlock(&phydev->lock); + + return err; +} + +static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev, + unsigned long rules) +{ + struct phy_led *phyled = to_phy_led(led_cdev); + struct phy_device *phydev = phyled->phydev; + int err; + + mutex_lock(&phydev->lock); + err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules); + mutex_unlock(&phydev->lock); + + return err; +} + static void phy_leds_unregister(struct phy_device *phydev) { struct phy_led *phyled; @@ -3057,6 +3112,19 @@ static int of_phy_led(struct phy_device *phydev, cdev->brightness_set_blocking = phy_led_set_brightness; if (phydev->drv->led_blink_set) cdev->blink_set = phy_led_blink_set; + +#ifdef CONFIG_LEDS_TRIGGERS + if (phydev->drv->led_hw_is_supported && + phydev->drv->led_hw_control_set && + phydev->drv->led_hw_control_get) { + cdev->hw_control_is_supported = phy_led_hw_is_supported; + cdev->hw_control_set = phy_led_hw_control_set; + cdev->hw_control_get = phy_led_hw_control_get; + cdev->hw_control_trigger = "netdev"; + } + + cdev->hw_control_get_device = phy_led_hw_control_get_device; +#endif cdev->max_brightness = 1; init_data.devicename = dev_name(&phydev->mdio.dev); init_data.fwnode = of_fwnode_handle(led); -- cgit From 460b0b648fab24f576c481424e0de5479ffb9786 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 8 Aug 2023 23:04:35 +0200 Subject: net: phy: marvell: Add support for offloading LED blinking Add the code needed to indicate if a given blinking pattern can be offloaded, to offload a pattern and to try to return the current pattern. Reviewed-by: Simon Horman Signed-off-by: Andrew Lunn Tested-by: Daniel Golle Link: https://lore.kernel.org/r/20230808210436.838995-4-andrew@lunn.ch Signed-off-by: Jakub Kicinski --- drivers/net/phy/marvell.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 43b6cb725551..eba652a4c1d8 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -2893,6 +2893,272 @@ static int m88e1318_led_blink_set(struct phy_device *phydev, u8 index, MII_88E1318S_PHY_LED_FUNC, reg); } +struct marvell_led_rules { + int mode; + unsigned long rules; +}; + +static const struct marvell_led_rules marvell_led0[] = { + { + .mode = 0, + .rules = BIT(TRIGGER_NETDEV_LINK), + }, + { + .mode = 1, + .rules = (BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 3, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 4, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 5, + .rules = BIT(TRIGGER_NETDEV_TX), + }, + { + .mode = 6, + .rules = BIT(TRIGGER_NETDEV_LINK), + }, + { + .mode = 7, + .rules = BIT(TRIGGER_NETDEV_LINK_1000), + }, + { + .mode = 8, + .rules = 0, + }, +}; + +static const struct marvell_led_rules marvell_led1[] = { + { + .mode = 1, + .rules = (BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 2, + .rules = (BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_RX)), + }, + { + .mode = 3, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 4, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 6, + .rules = (BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_1000)), + }, + { + .mode = 7, + .rules = BIT(TRIGGER_NETDEV_LINK_100), + }, + { + .mode = 8, + .rules = 0, + }, +}; + +static const struct marvell_led_rules marvell_led2[] = { + { + .mode = 0, + .rules = BIT(TRIGGER_NETDEV_LINK), + }, + { + .mode = 1, + .rules = (BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 3, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 4, + .rules = (BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)), + }, + { + .mode = 5, + .rules = BIT(TRIGGER_NETDEV_TX), + }, + { + .mode = 6, + .rules = (BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK_1000)), + }, + { + .mode = 7, + .rules = BIT(TRIGGER_NETDEV_LINK_10), + }, + { + .mode = 8, + .rules = 0, + }, +}; + +static int marvell_find_led_mode(unsigned long rules, + const struct marvell_led_rules *marvell_rules, + int count, + int *mode) +{ + int i; + + for (i = 0; i < count; i++) { + if (marvell_rules[i].rules == rules) { + *mode = marvell_rules[i].mode; + return 0; + } + } + return -EOPNOTSUPP; +} + +static int marvell_get_led_mode(u8 index, unsigned long rules, int *mode) +{ + int ret; + + switch (index) { + case 0: + ret = marvell_find_led_mode(rules, marvell_led0, + ARRAY_SIZE(marvell_led0), mode); + break; + case 1: + ret = marvell_find_led_mode(rules, marvell_led1, + ARRAY_SIZE(marvell_led1), mode); + break; + case 2: + ret = marvell_find_led_mode(rules, marvell_led2, + ARRAY_SIZE(marvell_led2), mode); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int marvell_find_led_rules(unsigned long *rules, + const struct marvell_led_rules *marvell_rules, + int count, + int mode) +{ + int i; + + for (i = 0; i < count; i++) { + if (marvell_rules[i].mode == mode) { + *rules = marvell_rules[i].rules; + return 0; + } + } + return -EOPNOTSUPP; +} + +static int marvell_get_led_rules(u8 index, unsigned long *rules, int mode) +{ + int ret; + + switch (index) { + case 0: + ret = marvell_find_led_rules(rules, marvell_led0, + ARRAY_SIZE(marvell_led0), mode); + break; + case 1: + ret = marvell_find_led_rules(rules, marvell_led1, + ARRAY_SIZE(marvell_led1), mode); + break; + case 2: + ret = marvell_find_led_rules(rules, marvell_led2, + ARRAY_SIZE(marvell_led2), mode); + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int m88e1318_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + int mode, ret; + + switch (index) { + case 0: + case 1: + case 2: + ret = marvell_get_led_mode(index, rules, &mode); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int m88e1318_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + int mode, ret, reg; + + switch (index) { + case 0: + case 1: + case 2: + ret = marvell_get_led_mode(index, rules, &mode); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, + MII_88E1318S_PHY_LED_FUNC); + if (reg < 0) + return reg; + + reg &= ~(0xf << (4 * index)); + reg |= mode << (4 * index); + return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, + MII_88E1318S_PHY_LED_FUNC, reg); +} + +static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + int mode, reg; + + if (index > 2) + return -EINVAL; + + reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, + MII_88E1318S_PHY_LED_FUNC); + if (reg < 0) + return reg; + + mode = (reg >> (4 * index)) & 0xf; + + return marvell_get_led_rules(index, rules, mode); +} + static int marvell_probe(struct phy_device *phydev) { struct marvell_priv *priv; @@ -3144,6 +3410,9 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, .led_brightness_set = m88e1318_led_brightness_set, .led_blink_set = m88e1318_led_blink_set, + .led_hw_is_supported = m88e1318_led_hw_is_supported, + .led_hw_control_set = m88e1318_led_hw_control_set, + .led_hw_control_get = m88e1318_led_hw_control_get, }, { .phy_id = MARVELL_PHY_ID_88E1145, @@ -3252,6 +3521,9 @@ static struct phy_driver marvell_drivers[] = { .cable_test_get_status = marvell_vct7_cable_test_get_status, .led_brightness_set = m88e1318_led_brightness_set, .led_blink_set = m88e1318_led_blink_set, + .led_hw_is_supported = m88e1318_led_hw_is_supported, + .led_hw_control_set = m88e1318_led_hw_control_set, + .led_hw_control_get = m88e1318_led_hw_control_get, }, { .phy_id = MARVELL_PHY_ID_88E1540, @@ -3280,6 +3552,9 @@ static struct phy_driver marvell_drivers[] = { .cable_test_get_status = marvell_vct7_cable_test_get_status, .led_brightness_set = m88e1318_led_brightness_set, .led_blink_set = m88e1318_led_blink_set, + .led_hw_is_supported = m88e1318_led_hw_is_supported, + .led_hw_control_set = m88e1318_led_hw_control_set, + .led_hw_control_get = m88e1318_led_hw_control_get, }, { .phy_id = MARVELL_PHY_ID_88E1545, @@ -3308,6 +3583,9 @@ static struct phy_driver marvell_drivers[] = { .cable_test_get_status = marvell_vct7_cable_test_get_status, .led_brightness_set = m88e1318_led_brightness_set, .led_blink_set = m88e1318_led_blink_set, + .led_hw_is_supported = m88e1318_led_hw_is_supported, + .led_hw_control_set = m88e1318_led_hw_control_set, + .led_hw_control_get = m88e1318_led_hw_control_get, }, { .phy_id = MARVELL_PHY_ID_88E3016, @@ -3451,6 +3729,9 @@ static struct phy_driver marvell_drivers[] = { .set_tunable = m88e1540_set_tunable, .led_brightness_set = m88e1318_led_brightness_set, .led_blink_set = m88e1318_led_blink_set, + .led_hw_is_supported = m88e1318_led_hw_is_supported, + .led_hw_control_set = m88e1318_led_hw_control_set, + .led_hw_control_get = m88e1318_led_hw_control_get, }, }; -- cgit From 0c2910ae7fa0caa0f1adc6fed73c23e5593b307b Mon Sep 17 00:00:00 2001 From: Furong Xu <0x1207@gmail.com> Date: Wed, 9 Aug 2023 10:02:38 +0800 Subject: net: stmmac: xgmac: RX queue routing configuration Commit abe80fdc6ee6 ("net: stmmac: RX queue routing configuration") introduced RX queue routing to DWMAC4 core. This patch extend the support to XGMAC2 core. Signed-off-by: Furong Xu <0x1207@gmail.com> Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230809020238.1136732-1-0x1207@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 12 ++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 34 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 153321fe42c3..ce67b178c2d5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -74,8 +74,20 @@ #define XGMAC_RXQEN(x) GENMASK((x) * 2 + 1, (x) * 2) #define XGMAC_RXQEN_SHIFT(x) ((x) * 2) #define XGMAC_RXQ_CTRL1 0x000000a4 +#define XGMAC_AVCPQ GENMASK(31, 28) +#define XGMAC_AVCPQ_SHIFT 28 +#define XGMAC_PTPQ GENMASK(27, 24) +#define XGMAC_PTPQ_SHIFT 24 +#define XGMAC_TACPQE BIT(23) +#define XGMAC_DCBCPQ GENMASK(19, 16) +#define XGMAC_DCBCPQ_SHIFT 16 +#define XGMAC_MCBCQEN BIT(15) +#define XGMAC_MCBCQ GENMASK(11, 8) +#define XGMAC_MCBCQ_SHIFT 8 #define XGMAC_RQ GENMASK(7, 4) #define XGMAC_RQ_SHIFT 4 +#define XGMAC_UPQ GENMASK(3, 0) +#define XGMAC_UPQ_SHIFT 0 #define XGMAC_RXQ_CTRL2 0x000000a8 #define XGMAC_RXQ_CTRL3 0x000000ac #define XGMAC_PSRQ(x) GENMASK((x) * 8 + 7, (x) * 8) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index a0c2ef8bb0ac..38782662ff98 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -127,6 +127,36 @@ static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio, writel(value, ioaddr + reg); } +static void dwxgmac2_rx_queue_routing(struct mac_device_info *hw, + u8 packet, u32 queue) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + + static const struct stmmac_rx_routing dwxgmac2_route_possibilities[] = { + { XGMAC_AVCPQ, XGMAC_AVCPQ_SHIFT }, + { XGMAC_PTPQ, XGMAC_PTPQ_SHIFT }, + { XGMAC_DCBCPQ, XGMAC_DCBCPQ_SHIFT }, + { XGMAC_UPQ, XGMAC_UPQ_SHIFT }, + { XGMAC_MCBCQ, XGMAC_MCBCQ_SHIFT }, + }; + + value = readl(ioaddr + XGMAC_RXQ_CTRL1); + + /* routing configuration */ + value &= ~dwxgmac2_route_possibilities[packet - 1].reg_mask; + value |= (queue << dwxgmac2_route_possibilities[packet - 1].reg_shift) & + dwxgmac2_route_possibilities[packet - 1].reg_mask; + + /* some packets require extra ops */ + if (packet == PACKET_AVCPQ) + value |= FIELD_PREP(XGMAC_TACPQE, 1); + else if (packet == PACKET_MCBCQ) + value |= FIELD_PREP(XGMAC_MCBCQEN, 1); + + writel(value, ioaddr + XGMAC_RXQ_CTRL1); +} + static void dwxgmac2_prog_mtl_rx_algorithms(struct mac_device_info *hw, u32 rx_alg) { @@ -1463,7 +1493,7 @@ const struct stmmac_ops dwxgmac210_ops = { .rx_queue_enable = dwxgmac2_rx_queue_enable, .rx_queue_prio = dwxgmac2_rx_queue_prio, .tx_queue_prio = dwxgmac2_tx_queue_prio, - .rx_queue_routing = NULL, + .rx_queue_routing = dwxgmac2_rx_queue_routing, .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms, .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms, .set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight, @@ -1524,7 +1554,7 @@ const struct stmmac_ops dwxlgmac2_ops = { .rx_queue_enable = dwxlgmac2_rx_queue_enable, .rx_queue_prio = dwxgmac2_rx_queue_prio, .tx_queue_prio = dwxgmac2_tx_queue_prio, - .rx_queue_routing = NULL, + .rx_queue_routing = dwxgmac2_rx_queue_routing, .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms, .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms, .set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight, -- cgit From 5604ac35cb6ec34ad608008ba851568c385fd3f4 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 10 Aug 2023 09:46:33 +0800 Subject: net: ethernet: 8390: ne2k-pci: use module_pci_driver() macro The driver init/exit() function don't do anything special, it can use the module_pci_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Reviewed-by: Pavan Chebbi Link: https://lore.kernel.org/r/20230810014633.3084355-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/8390/ne2k-pci.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 2c6bd36d2f31..65f56a98c0a0 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -731,18 +731,4 @@ static struct pci_driver ne2k_driver = { .id_table = ne2k_pci_tbl, .driver.pm = &ne2k_pci_pm_ops, }; - - -static int __init ne2k_pci_init(void) -{ - return pci_register_driver(&ne2k_driver); -} - - -static void __exit ne2k_pci_cleanup(void) -{ - pci_unregister_driver(&ne2k_driver); -} - -module_init(ne2k_pci_init); -module_exit(ne2k_pci_cleanup); +module_pci_driver(ne2k_driver); -- cgit From 6231e47b6fadf42da2e7a45b8272e80aed53c444 Mon Sep 17 00:00:00 2001 From: Tahsin Erdogan Date: Wed, 9 Aug 2023 09:47:52 -0700 Subject: tun: avoid high-order page allocation for packet header When gso.hdr_len is zero and a packet is transmitted via write() or writev(), all payload is treated as header which requires a contiguous memory allocation. This allocation request is harder to satisfy, and may even fail if there is enough fragmentation. Note that sendmsg() code path limits the linear copy length, so this change makes write()/writev() and sendmsg() paths more consistent. Signed-off-by: Tahsin Erdogan Acked-by: Jason Wang Reviewed-by: Eric Dumazet Reviewed-by: Willem de Bruijn Link: https://lore.kernel.org/r/20230809164753.2247594-1-trdgn@amazon.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a05765448803..d4bd76297a2a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1523,7 +1523,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, int err; /* Under a page? Don't bother with paged skb. */ - if (prepad + len < PAGE_SIZE || !linear) + if (prepad + len < PAGE_SIZE) linear = len; if (len - linear > MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) @@ -1840,6 +1840,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, */ zerocopy = false; } else { + if (!linear) + linear = min_t(size_t, good_linear, copylen); + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); } -- cgit From 7a1c38215820edfcd7c3a2523f4fd385f4e482d6 Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Tue, 8 Aug 2023 15:43:07 +0300 Subject: net: ftmac100: add multicast filtering possibility If netdev_mc_count() is not zero and not IFF_ALLMULTI, filter incoming multicast packets. The chip has a Multicast Address Hash Table for allowed multicast addresses, so we fill it. Implement .ndo_set_rx_mode and recalculate multicast hash table. Also observe change of IFF_PROMISC and IFF_ALLMULTI netdev flags. Signed-off-by: Sergei Antonov Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/faraday/ftmac100.c | 50 +++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 139fe66f8bcd..183069581bc0 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -149,6 +149,40 @@ static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac) iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR); } +static void ftmac100_setup_mc_ht(struct ftmac100 *priv) +{ + struct netdev_hw_addr *ha; + u64 maht = 0; /* Multicast Address Hash Table */ + + netdev_for_each_mc_addr(ha, priv->netdev) { + u32 hash = ether_crc(ETH_ALEN, ha->addr) >> 26; + + maht |= BIT_ULL(hash); + } + + iowrite32(lower_32_bits(maht), priv->base + FTMAC100_OFFSET_MAHT0); + iowrite32(upper_32_bits(maht), priv->base + FTMAC100_OFFSET_MAHT1); +} + +static void ftmac100_set_rx_bits(struct ftmac100 *priv, unsigned int *maccr) +{ + struct net_device *netdev = priv->netdev; + + /* Clear all */ + *maccr &= ~(FTMAC100_MACCR_RCV_ALL | FTMAC100_MACCR_RX_MULTIPKT | + FTMAC100_MACCR_HT_MULTI_EN); + + /* Set the requested bits */ + if (netdev->flags & IFF_PROMISC) + *maccr |= FTMAC100_MACCR_RCV_ALL; + if (netdev->flags & IFF_ALLMULTI) + *maccr |= FTMAC100_MACCR_RX_MULTIPKT; + else if (netdev_mc_count(netdev)) { + *maccr |= FTMAC100_MACCR_HT_MULTI_EN; + ftmac100_setup_mc_ht(priv); + } +} + #define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \ FTMAC100_MACCR_RCV_EN | \ FTMAC100_MACCR_XDMA_EN | \ @@ -182,11 +216,7 @@ static int ftmac100_start_hw(struct ftmac100 *priv) if (netdev->mtu > ETH_DATA_LEN) maccr |= FTMAC100_MACCR_RX_FTL; - /* Add other bits as needed */ - if (netdev->flags & IFF_PROMISC) - maccr |= FTMAC100_MACCR_RCV_ALL; - if (netdev->flags & IFF_ALLMULTI) - maccr |= FTMAC100_MACCR_RX_MULTIPKT; + ftmac100_set_rx_bits(priv, &maccr); iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); return 0; @@ -1067,6 +1097,15 @@ static int ftmac100_change_mtu(struct net_device *netdev, int mtu) return 0; } +static void ftmac100_set_rx_mode(struct net_device *netdev) +{ + struct ftmac100 *priv = netdev_priv(netdev); + unsigned int maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR); + + ftmac100_set_rx_bits(priv, &maccr); + iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR); +} + static const struct net_device_ops ftmac100_netdev_ops = { .ndo_open = ftmac100_open, .ndo_stop = ftmac100_stop, @@ -1075,6 +1114,7 @@ static const struct net_device_ops ftmac100_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_eth_ioctl = ftmac100_do_ioctl, .ndo_change_mtu = ftmac100_change_mtu, + .ndo_set_rx_mode = ftmac100_set_rx_mode, }; /****************************************************************************** -- cgit From 12aa0a3b93f3adf61b6f7937c3aac8585ced3fca Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Wed, 9 Aug 2023 12:10:39 +0530 Subject: octeontx2-af: Harden rule validation. Accept TC offload classifier rule only if SPI field can be extracted by HW. Signed-off-by: Ratheesh Kannoth Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 5c8f9fc15ff8..237f82082ebe 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -580,7 +580,9 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf) if (!npc_check_field(rvu, blkaddr, NPC_LB, intf)) *features &= ~BIT_ULL(NPC_OUTER_VID); - if (*features & (BIT_ULL(NPC_IPPROTO_AH) | BIT_ULL(NPC_IPPROTO_ESP))) + /* Set SPI flag only if AH/ESP and IPSEC_SPI are in the key */ + if (npc_check_field(rvu, blkaddr, NPC_IPSEC_SPI, intf) && + (*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH)))) *features |= BIT_ULL(NPC_IPSEC_SPI); /* for vlan ethertypes corresponding layer type should be in the key */ -- cgit From a20b4c5f3a0ed257b9c0642bb935e3de2e23bce8 Mon Sep 17 00:00:00 2001 From: Sathesh Edara Date: Wed, 9 Aug 2023 04:29:33 -0700 Subject: octeon_ep: Add control plane host and firmware versions. Implement control plane mailbox versions for host and firmware. Versions are published in info area of control mailbox bar4 memory structure.Firmware will publish minimum and maximum supported versions.Control plane mailbox apis will check for firmware version before sending any control commands to firmware. Notifications from firmware will similarly be checked for host version compatibility. Signed-off-by: Sathesh Edara Signed-off-by: David S. Miller --- .../ethernet/marvell/octeon_ep/octep_cp_version.h | 11 +++++++ .../ethernet/marvell/octeon_ep/octep_ctrl_mbox.c | 9 +++++- .../ethernet/marvell/octeon_ep/octep_ctrl_mbox.h | 6 ++++ .../ethernet/marvell/octeon_ep/octep_ctrl_net.c | 37 ++++++++++++++++++++-- .../ethernet/marvell/octeon_ep/octep_ctrl_net.h | 4 +++ 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_cp_version.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cp_version.h b/drivers/net/ethernet/marvell/octeon_ep/octep_cp_version.h new file mode 100644 index 000000000000..0c741e752db6 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cp_version.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2022 Marvell. + */ +#ifndef __OCTEP_CP_VERSION_H__ +#define __OCTEP_CP_VERSION_H__ + +#define OCTEP_CP_VERSION(a, b, c) ((((a) & 0xff) << 16) + \ + (((b) & 0xff) << 8) + \ + ((c) & 0xff)) + +#endif /* __OCTEP_CP_VERSION_H__ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c index dab61cc1acb5..9d53c1402cb4 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c @@ -37,7 +37,9 @@ #define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM(m) (m) #define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(m) ((m) + 8) +#define OCTEP_CTRL_MBOX_INFO_HOST_VERSION(m) ((m) + 16) #define OCTEP_CTRL_MBOX_INFO_HOST_STATUS(m) ((m) + 24) +#define OCTEP_CTRL_MBOX_INFO_FW_VERSION(m) ((m) + 136) #define OCTEP_CTRL_MBOX_INFO_FW_STATUS(m) ((m) + 144) #define OCTEP_CTRL_MBOX_H2FQ_INFO(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ) @@ -71,7 +73,7 @@ static u32 octep_ctrl_mbox_circq_depth(u32 pi, u32 ci, u32 sz) int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox) { - u64 magic_num, status; + u64 magic_num, status, fw_versions; if (!mbox) return -EINVAL; @@ -93,6 +95,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox) return -EINVAL; } + fw_versions = readq(OCTEP_CTRL_MBOX_INFO_FW_VERSION(mbox->barmem)); + mbox->min_fw_version = ((fw_versions & 0xffffffff00000000ull) >> 32); + mbox->max_fw_version = (fw_versions & 0xffffffff); mbox->barmem_sz = readl(OCTEP_CTRL_MBOX_INFO_BARMEM_SZ(mbox->barmem)); writeq(OCTEP_CTRL_MBOX_STATUS_INIT, @@ -113,6 +118,7 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox) OCTEP_CTRL_MBOX_TOTAL_INFO_SZ + mbox->h2fq.sz; + writeq(mbox->version, OCTEP_CTRL_MBOX_INFO_HOST_VERSION(mbox->barmem)); /* ensure ready state is seen after everything is initialized */ wmb(); writeq(OCTEP_CTRL_MBOX_STATUS_READY, @@ -258,6 +264,7 @@ int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox) if (!mbox->barmem) return -EINVAL; + writeq(0, OCTEP_CTRL_MBOX_INFO_HOST_VERSION(mbox->barmem)); writeq(OCTEP_CTRL_MBOX_STATUS_INVALID, OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem)); /* ensure uninit state is written before uninitialization */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h index 9c4ff0fba6a0..7f8135788efc 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h @@ -121,6 +121,8 @@ struct octep_ctrl_mbox_q { }; struct octep_ctrl_mbox { + /* control plane version */ + u64 version; /* size of bar memory */ u32 barmem_sz; /* pointer to BAR memory */ @@ -133,6 +135,10 @@ struct octep_ctrl_mbox { struct mutex h2fq_lock; /* lock for f2hq */ struct mutex f2hq_lock; + /* Min control plane version supported by firmware */ + u32 min_fw_version; + /* Max control plane version supported by firmware */ + u32 max_fw_version; }; /* Initialize control mbox. diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c index 1cc6af2feb38..4c6d91a8c83e 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c @@ -14,6 +14,9 @@ #include "octep_main.h" #include "octep_ctrl_net.h" +/* Control plane version */ +#define OCTEP_CP_VERSION_CURRENT OCTEP_CP_VERSION(1, 0, 0) + static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr); static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu); static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac); @@ -21,6 +24,18 @@ static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state); static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info); static atomic_t ctrl_net_msg_id; +/* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */ +static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = { + [OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_LINK_INFO] = + OCTEP_CP_VERSION(1, 0, 0) +}; + +/* Control plane version in which OCTEP_CTRL_NET_F2H_CMD was added */ +static const u32 octep_ctrl_net_f2h_cmd_versions[OCTEP_CTRL_NET_F2H_CMD_MAX] = { + [OCTEP_CTRL_NET_F2H_CMD_INVALID ... OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS] = + OCTEP_CP_VERSION(1, 0, 0) +}; + static void init_send_req(struct octep_ctrl_mbox_msg *msg, void *buf, u16 sz, int vfid) { @@ -41,7 +56,13 @@ static int octep_send_mbox_req(struct octep_device *oct, struct octep_ctrl_net_wait_data *d, bool wait_for_response) { - int err, ret; + int err, ret, cmd; + + /* check if firmware is compatible for this request */ + cmd = d->data.req.hdr.s.cmd; + if (octep_ctrl_net_h2f_cmd_versions[cmd] > oct->ctrl_mbox.max_fw_version || + octep_ctrl_net_h2f_cmd_versions[cmd] < oct->ctrl_mbox.min_fw_version) + return -EOPNOTSUPP; err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &d->msg); if (err < 0) @@ -84,12 +105,16 @@ int octep_ctrl_net_init(struct octep_device *oct) /* Initialize control mbox */ ctrl_mbox = &oct->ctrl_mbox; + ctrl_mbox->version = OCTEP_CP_VERSION_CURRENT; ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf); ret = octep_ctrl_mbox_init(ctrl_mbox); if (ret) { dev_err(&pdev->dev, "Failed to initialize control mbox\n"); return ret; } + dev_info(&pdev->dev, "Control plane versions host: %llx, firmware: %x:%x\n", + ctrl_mbox->version, ctrl_mbox->min_fw_version, + ctrl_mbox->max_fw_version); oct->ctrl_mbox_ifstats_offset = ctrl_mbox->barmem_sz; return 0; @@ -273,9 +298,17 @@ static int process_mbox_notify(struct octep_device *oct, { struct net_device *netdev = oct->netdev; struct octep_ctrl_net_f2h_req *req; + int cmd; req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg; - switch (req->hdr.s.cmd) { + cmd = req->hdr.s.cmd; + + /* check if we support this command */ + if (octep_ctrl_net_f2h_cmd_versions[cmd] > OCTEP_CP_VERSION_CURRENT || + octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT) + return -EOPNOTSUPP; + + switch (cmd) { case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: if (netif_running(netdev)) { if (req->link.state) { diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h index 37880dd79116..1c2ef4ee31d9 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h @@ -7,6 +7,8 @@ #ifndef __OCTEP_CTRL_NET_H__ #define __OCTEP_CTRL_NET_H__ +#include "octep_cp_version.h" + #define OCTEP_CTRL_NET_INVALID_VFID (-1) /* Supported commands */ @@ -39,12 +41,14 @@ enum octep_ctrl_net_h2f_cmd { OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS, OCTEP_CTRL_NET_H2F_CMD_RX_STATE, OCTEP_CTRL_NET_H2F_CMD_LINK_INFO, + OCTEP_CTRL_NET_H2F_CMD_MAX }; /* Supported fw to host commands */ enum octep_ctrl_net_f2h_cmd { OCTEP_CTRL_NET_F2H_CMD_INVALID = 0, OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS, + OCTEP_CTRL_NET_F2H_CMD_MAX }; union octep_ctrl_net_req_hdr { -- cgit From ac3899c6229649737b9d5cb86e417c98243883dc Mon Sep 17 00:00:00 2001 From: Shradha Gupta Date: Wed, 9 Aug 2023 21:15:22 -0700 Subject: net: mana: Add gdma stats to ethtool output for mana Extended performance counter stats in 'ethtool -S ' for MANA VF to include GDMA tx LSO packets and bytes count. Tested-on: Ubuntu22 Testcases: 1. LISA testcase: PERF-NETWORK-TCP-THROUGHPUT-MULTICONNECTION-NTTTCP-Synthetic 2. LISA testcase: PERF-NETWORK-TCP-THROUGHPUT-MULTICONNECTION-NTTTCP-SRIOV 3. Validated the GDMA stat packets and byte counters Signed-off-by: Shradha Gupta Reviewed-by: Pavan Chebbi Signed-off-by: David S. Miller --- drivers/net/ethernet/microsoft/mana/mana_en.c | 40 ++++++++++++++++++++++ drivers/net/ethernet/microsoft/mana/mana_ethtool.c | 15 ++++++++ 2 files changed, 55 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 48f330d59284..4a16ebff3d1d 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -2295,6 +2295,46 @@ int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx, return 0; } +void mana_query_gf_stats(struct mana_port_context *apc) +{ + struct mana_query_gf_stat_resp resp = {}; + struct mana_query_gf_stat_req req = {}; + struct net_device *ndev = apc->ndev; + int err; + + mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_GF_STAT, + sizeof(req), sizeof(resp)); + req.req_stats = STATISTICS_FLAGS_HC_TX_BYTES | + STATISTICS_FLAGS_HC_TX_UCAST_PACKETS | + STATISTICS_FLAGS_HC_TX_UCAST_BYTES | + STATISTICS_FLAGS_HC_TX_MCAST_PACKETS | + STATISTICS_FLAGS_HC_TX_MCAST_BYTES | + STATISTICS_FLAGS_HC_TX_BCAST_PACKETS | + STATISTICS_FLAGS_HC_TX_BCAST_BYTES; + + err = mana_send_request(apc->ac, &req, sizeof(req), &resp, + sizeof(resp)); + if (err) { + netdev_err(ndev, "Failed to query GF stats: %d\n", err); + return; + } + err = mana_verify_resp_hdr(&resp.hdr, MANA_QUERY_GF_STAT, + sizeof(resp)); + if (err || resp.hdr.status) { + netdev_err(ndev, "Failed to query GF stats: %d, 0x%x\n", err, + resp.hdr.status); + return; + } + + apc->eth_stats.hc_tx_bytes = resp.hc_tx_bytes; + apc->eth_stats.hc_tx_ucast_pkts = resp.hc_tx_ucast_pkts; + apc->eth_stats.hc_tx_ucast_bytes = resp.hc_tx_ucast_bytes; + apc->eth_stats.hc_tx_bcast_pkts = resp.hc_tx_bcast_pkts; + apc->eth_stats.hc_tx_bcast_bytes = resp.hc_tx_bcast_bytes; + apc->eth_stats.hc_tx_mcast_pkts = resp.hc_tx_mcast_pkts; + apc->eth_stats.hc_tx_mcast_bytes = resp.hc_tx_mcast_bytes; +} + static int mana_init_port(struct net_device *ndev) { struct mana_port_context *apc = netdev_priv(ndev); diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c index 0dc78679f620..607150165ab4 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c @@ -13,6 +13,19 @@ static const struct { } mana_eth_stats[] = { {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)}, {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)}, + {"hc_tx_bytes", offsetof(struct mana_ethtool_stats, hc_tx_bytes)}, + {"hc_tx_ucast_pkts", offsetof(struct mana_ethtool_stats, + hc_tx_ucast_pkts)}, + {"hc_tx_ucast_bytes", offsetof(struct mana_ethtool_stats, + hc_tx_ucast_bytes)}, + {"hc_tx_bcast_pkts", offsetof(struct mana_ethtool_stats, + hc_tx_bcast_pkts)}, + {"hc_tx_bcast_bytes", offsetof(struct mana_ethtool_stats, + hc_tx_bcast_bytes)}, + {"hc_tx_mcast_pkts", offsetof(struct mana_ethtool_stats, + hc_tx_mcast_pkts)}, + {"hc_tx_mcast_bytes", offsetof(struct mana_ethtool_stats, + hc_tx_mcast_bytes)}, {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)}, {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats, tx_cqe_unknown_type)}, @@ -114,6 +127,8 @@ static void mana_get_ethtool_stats(struct net_device *ndev, if (!apc->port_is_up) return; + /* we call mana function to update stats from GDMA */ + mana_query_gf_stats(apc); for (q = 0; q < ARRAY_SIZE(mana_eth_stats); q++) data[i++] = *(u64 *)(eth_stats + mana_eth_stats[q].offset); -- cgit From c5b0c34fae1ef234982d55445b8aa482f0b05ba6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 10 Aug 2023 12:39:22 +0200 Subject: net/xgene: fix Wvoid-pointer-to-enum-cast warning 'enet_id' is an enum, thus cast of pointer on 64-bit compile test with W=1 causes: xgene_enet_main.c:2044:20: error: cast to smaller integer type 'enum xgene_enet_id' from 'const void *' [-Werror,-Wvoid-pointer-to-enum-cast] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Tested-by: Simon Horman # build-tested Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 41d96f4b23d8..4d4140b7c450 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -2041,7 +2041,7 @@ static int xgene_enet_probe(struct platform_device *pdev) of_id = of_match_device(xgene_enet_of_match, &pdev->dev); if (of_id) { - pdata->enet_id = (enum xgene_enet_id)of_id->data; + pdata->enet_id = (uintptr_t)of_id->data; } #ifdef CONFIG_ACPI else { -- cgit From e5cd429e79286a17b345f9f9153d3970a46359f2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 10 Aug 2023 12:39:23 +0200 Subject: net/marvell: fix Wvoid-pointer-to-enum-cast warning 'type' is an enum, thus cast of pointer on 64-bit compile test with W=1 causes: mvmdio.c:272:9: error: cast to smaller integer type 'enum orion_mdio_bus_type' from 'const void *' [-Werror,-Wvoid-pointer-to-enum-cast] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Tested-by: Simon Horman # build-tested Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvmdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index a1a80f13b1e8..674913184ebf 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -269,7 +269,7 @@ static int orion_mdio_probe(struct platform_device *pdev) struct orion_mdio_dev *dev; int i, ret; - type = (enum orion_mdio_bus_type)device_get_match_data(&pdev->dev); + type = (uintptr_t)device_get_match_data(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { -- cgit From e08190ef514fd3c7e45826cd0d427d4133361192 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 10 Aug 2023 21:50:03 +0800 Subject: bonding: add modifier to initialization function and exit function Some functions are only used in initialization and exit functions, so add the __init/__net_init and __net_exit modifiers to these functions. Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/bonding/bond_debugfs.c | 4 ++-- drivers/net/bonding/bond_main.c | 2 +- drivers/net/bonding/bond_sysfs.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 594094526648..94c2f35e3bfc 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -84,7 +84,7 @@ void bond_debug_reregister(struct bonding *bond) } } -void bond_create_debugfs(void) +void __init bond_create_debugfs(void) { bonding_debug_root = debugfs_create_dir("bonding", NULL); @@ -113,7 +113,7 @@ void bond_debug_reregister(struct bonding *bond) { } -void bond_create_debugfs(void) +void __init bond_create_debugfs(void) { } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d26c69d84c1e..6636638f5d97 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5981,7 +5981,7 @@ static void bond_uninit(struct net_device *bond_dev) /*------------------------- Module initialization ---------------------------*/ -static int bond_check_params(struct bond_params *params) +static int __init bond_check_params(struct bond_params *params) { int arp_validate_value, fail_over_mac_value, primary_reselect_value, i; struct bond_opt_value newval; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 0bb59da24922..2805135a7205 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -803,7 +803,7 @@ static const struct attribute_group bonding_group = { /* Initialize sysfs. This sets up the bonding_masters file in * /sys/class/net. */ -int bond_create_sysfs(struct bond_net *bn) +int __net_init bond_create_sysfs(struct bond_net *bn) { int ret; @@ -836,7 +836,7 @@ int bond_create_sysfs(struct bond_net *bn) } /* Remove /sys/class/net/bonding_masters. */ -void bond_destroy_sysfs(struct bond_net *bn) +void __net_exit bond_destroy_sysfs(struct bond_net *bn) { netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net); } -- cgit From 57647e6fdf174e3c84072a39d901036f867e4192 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 10 Aug 2023 21:50:04 +0800 Subject: bonding: use IS_ERR instead of NULL check in bond_create_debugfs Because debugfs_create_dir returns ERR_PTR, so IS_ERR should be used to check whether the directory is successfully created. Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/bonding/bond_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 94c2f35e3bfc..50e48136c697 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -88,7 +88,7 @@ void __init bond_create_debugfs(void) { bonding_debug_root = debugfs_create_dir("bonding", NULL); - if (!bonding_debug_root) + if (IS_ERR(bonding_debug_root)) pr_warn("Warning: Cannot create bonding directory in debugfs\n"); } -- cgit From cc317ea3d9272fab4f6fef527c865f30ca479394 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 10 Aug 2023 21:50:05 +0800 Subject: bonding: remove redundant NULL check in debugfs function Because debugfs_create_dir returns ERR_PTR, so bonding_debug_root will never be NULL. Remove redundant NULL check for bonding_debug_root in debugfs function. The later debugfs_create_dir/debugfs_remove_recursive /debugfs_remove_recursive functions will check the dentry with IS_ERR(). Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/bonding/bond_debugfs.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 50e48136c697..b19492a7f6ad 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -49,9 +49,6 @@ DEFINE_SHOW_ATTRIBUTE(bond_debug_rlb_hash); void bond_debug_register(struct bonding *bond) { - if (!bonding_debug_root) - return; - bond->debug_dir = debugfs_create_dir(bond->dev->name, bonding_debug_root); @@ -61,9 +58,6 @@ void bond_debug_register(struct bonding *bond) void bond_debug_unregister(struct bonding *bond) { - if (!bonding_debug_root) - return; - debugfs_remove_recursive(bond->debug_dir); } @@ -71,9 +65,6 @@ void bond_debug_reregister(struct bonding *bond) { struct dentry *d; - if (!bonding_debug_root) - return; - d = debugfs_rename(bonding_debug_root, bond->debug_dir, bonding_debug_root, bond->dev->name); if (!IS_ERR(d)) { -- cgit From a8f3f4b448458a117465b9404d18994469c01957 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 10 Aug 2023 21:50:06 +0800 Subject: bonding: use bond_set_slave_arr to simplify code In bond_reset_slave_arr(), values are assigned and memory is released only when the variables "usable" and "all" are not NULL. But even if the "usable" and "all" variables are NULL, they can still work, because value will be checked in kfree_rcu. Therefore, use bond_set_slave_arr() and set the input parameters "usable_slaves" and "all_slaves" to NULL to simplify the code in bond_reset_slave_arr(). And the same to bond_uninit(). Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6636638f5d97..de3ae9c57da0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5046,19 +5046,7 @@ static void bond_set_slave_arr(struct bonding *bond, static void bond_reset_slave_arr(struct bonding *bond) { - struct bond_up_slave *usable, *all; - - usable = rtnl_dereference(bond->usable_slaves); - if (usable) { - RCU_INIT_POINTER(bond->usable_slaves, NULL); - kfree_rcu(usable, rcu); - } - - all = rtnl_dereference(bond->all_slaves); - if (all) { - RCU_INIT_POINTER(bond->all_slaves, NULL); - kfree_rcu(all, rcu); - } + bond_set_slave_arr(bond, NULL, NULL); } /* Build the usable slaves array in control path for modes that use xmit-hash @@ -5951,7 +5939,6 @@ void bond_setup(struct net_device *bond_dev) static void bond_uninit(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct bond_up_slave *usable, *all; struct list_head *iter; struct slave *slave; @@ -5962,17 +5949,7 @@ static void bond_uninit(struct net_device *bond_dev) __bond_release_one(bond_dev, slave->dev, true, true); netdev_info(bond_dev, "Released all slaves\n"); - usable = rtnl_dereference(bond->usable_slaves); - if (usable) { - RCU_INIT_POINTER(bond->usable_slaves, NULL); - kfree_rcu(usable, rcu); - } - - all = rtnl_dereference(bond->all_slaves); - if (all) { - RCU_INIT_POINTER(bond->all_slaves, NULL); - kfree_rcu(all, rcu); - } + bond_set_slave_arr(bond, NULL, NULL); list_del(&bond->bond_list); -- cgit From f5370ba3590d1e141c288eed2c0e53618b91356d Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Thu, 10 Aug 2023 21:50:07 +0800 Subject: bonding: remove unnecessary NULL check in bond_destructor The free_percpu function also could check whether "rr_tx_counter" parameter is NULL. Therefore, remove NULL check in bond_destructor. Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index de3ae9c57da0..f398bec78457 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5863,8 +5863,7 @@ static void bond_destructor(struct net_device *bond_dev) if (bond->wq) destroy_workqueue(bond->wq); - if (bond->rr_tx_counter) - free_percpu(bond->rr_tx_counter); + free_percpu(bond->rr_tx_counter); } void bond_setup(struct net_device *bond_dev) -- cgit From 61f98da4698407d042128396297d7f724cfa1424 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Thu, 10 Aug 2023 22:41:19 +0530 Subject: octeontx2-pf: Allow both ntuple and TC features on the interface The current implementation does not allow the user to enable both hw-tc-offload and ntuple features on the interface. These checks are added as TC flower offload and ntuple features internally configures the same hardware resource MCAM. But TC HTB offload configures the transmit scheduler which can be safely enabled on the interface with ntuple feature. This patch adds the same and ensures only TC flower offload and ntuple features are mutually exclusive. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../ethernet/marvell/octeontx2/nic/otx2_common.c | 21 +++------------------ .../ethernet/marvell/octeontx2/nic/otx2_common.h | 9 +++++++++ 2 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 8336cea16aff..dce3cea00032 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -1905,31 +1905,16 @@ int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t } } - if ((changed & NETIF_F_HW_TC) && tc) { - if (!pfvf->flow_cfg->max_flows) { - netdev_err(netdev, - "Can't enable TC, MCAM entries not allocated\n"); - return -EINVAL; - } - } - if ((changed & NETIF_F_HW_TC) && !tc && - pfvf->flow_cfg && pfvf->flow_cfg->nr_flows) { + otx2_tc_flower_rule_cnt(pfvf)) { netdev_err(netdev, "Can't disable TC hardware offload while flows are active\n"); return -EBUSY; } if ((changed & NETIF_F_NTUPLE) && ntuple && - (netdev->features & NETIF_F_HW_TC) && !(changed & NETIF_F_HW_TC)) { - netdev_err(netdev, - "Can't enable NTUPLE when TC is active, disable TC and retry\n"); - return -EINVAL; - } - - if ((changed & NETIF_F_HW_TC) && tc && - (netdev->features & NETIF_F_NTUPLE) && !(changed & NETIF_F_NTUPLE)) { + otx2_tc_flower_rule_cnt(pfvf) && !(changed & NETIF_F_HW_TC)) { netdev_err(netdev, - "Can't enable TC when NTUPLE is active, disable NTUPLE and retry\n"); + "Can't enable NTUPLE when TC flower offload is active, disable TC rules and retry\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 25e99fd2e3fd..5fd05d94de7c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -940,6 +940,15 @@ static inline u64 otx2_convert_rate(u64 rate) return converted_rate; } +static inline int otx2_tc_flower_rule_cnt(struct otx2_nic *pfvf) +{ + /* return here if MCAM entries not allocated */ + if (!pfvf->flow_cfg) + return 0; + + return pfvf->flow_cfg->nr_flows; +} + /* MSI-X APIs */ void otx2_free_cints(struct otx2_nic *pfvf, int n); void otx2_set_cints_affinity(struct otx2_nic *pfvf); -- cgit From 6cf30fdd7b06515db9188ace84d2497f390f4c37 Mon Sep 17 00:00:00 2001 From: Clément Léger Date: Thu, 10 Aug 2023 11:36:49 +0200 Subject: net: dsa: rzn1-a5psw: use a5psw_reg_rmw() to modify flooding resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .port_bridge_flags will be added and allows to modify the flood mask independently for each port. Keeping the existing bridged_ports write in a5psw_flooding_set_resolution() would potentially messed up this. Use a read-modify-write to set that value and move bridged_ports handling in bridge_port_join/leave. Signed-off-by: Clément Léger Reviewed-by: Florian Fainelli Signed-off-by: Alexis Lothoré Signed-off-by: David S. Miller --- drivers/net/dsa/rzn1_a5psw.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index c37d2e537230..302529edb4e0 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -331,13 +331,9 @@ static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port, A5PSW_MCAST_DEF_MASK}; int i; - if (set) - a5psw->bridged_ports |= BIT(port); - else - a5psw->bridged_ports &= ~BIT(port); - for (i = 0; i < ARRAY_SIZE(offsets); i++) - a5psw_reg_writel(a5psw, offsets[i], a5psw->bridged_ports); + a5psw_reg_rmw(a5psw, offsets[i], BIT(port), + set ? BIT(port) : 0); } static void a5psw_port_set_standalone(struct a5psw *a5psw, int port, @@ -365,6 +361,8 @@ static int a5psw_port_bridge_join(struct dsa_switch *ds, int port, a5psw->br_dev = bridge.dev; a5psw_port_set_standalone(a5psw, port, false); + a5psw->bridged_ports |= BIT(port); + return 0; } @@ -373,6 +371,8 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port, { struct a5psw *a5psw = ds->priv; + a5psw->bridged_ports &= ~BIT(port); + a5psw_port_set_standalone(a5psw, port, true); /* No more ports bridged */ @@ -992,6 +992,8 @@ static int a5psw_probe(struct platform_device *pdev) if (IS_ERR(a5psw->base)) return PTR_ERR(a5psw->base); + a5psw->bridged_ports = BIT(A5PSW_CPU_PORT); + ret = a5psw_pcs_get(a5psw); if (ret) return ret; -- cgit From 0d37f839836b4f61493ff3ff0397abd19f540494 Mon Sep 17 00:00:00 2001 From: Clément Léger Date: Thu, 10 Aug 2023 11:36:50 +0200 Subject: net: dsa: rzn1-a5psw: add support for .port_bridge_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running vlan test (bridge_vlan_aware/unaware.sh), there were some failure due to the lack .port_bridge_flag function to disable port flooding. Implement this operation for BR_LEARNING, BR_FLOOD, BR_MCAST_FLOOD and BR_BCAST_FLOOD. Since .port_bridge_flags affects the bits disabling learning for a port, ensure that any other modification on the same register done by a5psw_port_stp_state_set is in sync by using the port learning state to enable/disable learning on the port. Signed-off-by: Clément Léger Signed-off-by: Alexis Lothoré Signed-off-by: David S. Miller --- drivers/net/dsa/rzn1_a5psw.c | 60 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 302529edb4e0..e4a93dad1d58 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -380,9 +380,63 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port, a5psw->br_dev = NULL; } +static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | + BR_BCAST_FLOOD)) + return -EINVAL; + + return 0; +} + +static int +a5psw_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + struct a5psw *a5psw = ds->priv; + u32 val; + + /* If a port is set as standalone, we do not want to be able to + * configure flooding nor learning which would result in joining the + * unique bridge. This can happen when a port leaves the bridge, in + * which case the DSA core will try to "clear" all flags for the + * standalone port (ie enable flooding, disable learning). In that case + * do not fail but do not apply the flags. + */ + if (!(a5psw->bridged_ports & BIT(port))) + return 0; + + if (flags.mask & BR_LEARNING) { + val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port); + a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, + A5PSW_INPUT_LEARN_DIS(port), val); + } + + if (flags.mask & BR_FLOOD) { + val = flags.val & BR_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); + } + + if (flags.mask & BR_MCAST_FLOOD) { + val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); + } + + if (flags.mask & BR_BCAST_FLOOD) { + val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); + } + + return 0; +} + static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { bool learning_enabled, rx_enabled, tx_enabled; + struct dsa_port *dp = dsa_to_port(ds, port); struct a5psw *a5psw = ds->priv; switch (state) { @@ -396,12 +450,12 @@ static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) case BR_STATE_LEARNING: rx_enabled = false; tx_enabled = false; - learning_enabled = true; + learning_enabled = dp->learning; break; case BR_STATE_FORWARDING: rx_enabled = true; tx_enabled = true; - learning_enabled = true; + learning_enabled = dp->learning; break; default: dev_err(ds->dev, "invalid STP state: %d\n", state); @@ -801,6 +855,8 @@ static const struct dsa_switch_ops a5psw_switch_ops = { .set_ageing_time = a5psw_set_ageing_time, .port_bridge_join = a5psw_port_bridge_join, .port_bridge_leave = a5psw_port_bridge_leave, + .port_pre_bridge_flags = a5psw_port_pre_bridge_flags, + .port_bridge_flags = a5psw_port_bridge_flags, .port_stp_state_set = a5psw_port_stp_state_set, .port_fast_age = a5psw_port_fast_age, .port_fdb_add = a5psw_port_fdb_add, -- cgit From 7b3f77c428ad7d3ae66ed8c98b072a0cdca2f0ba Mon Sep 17 00:00:00 2001 From: Clément Léger Date: Thu, 10 Aug 2023 11:36:51 +0200 Subject: net: dsa: rzn1-a5psw: add vlan support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for vlan operation (add, del, filtering) on the RZN1 driver. The a5psw switch supports up to 32 VLAN IDs with filtering, tagged/untagged VLANs and PVID for each ports. Signed-off-by: Clément Léger Signed-off-by: Alexis Lothoré Signed-off-by: David S. Miller --- drivers/net/dsa/rzn1_a5psw.c | 166 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/rzn1_a5psw.h | 8 ++- 2 files changed, 171 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index e4a93dad1d58..2bb458f2c1f8 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -639,6 +639,146 @@ out_unlock: return ret; } +static int a5psw_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering, + struct netlink_ext_ack *extack) +{ + u32 mask = BIT(port + A5PSW_VLAN_VERI_SHIFT) | + BIT(port + A5PSW_VLAN_DISC_SHIFT); + u32 val = vlan_filtering ? mask : 0; + struct a5psw *a5psw = ds->priv; + + /* Disable/enable vlan tagging */ + a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE_ENA, BIT(port), + vlan_filtering ? BIT(port) : 0); + + /* Disable/enable vlan input filtering */ + a5psw_reg_rmw(a5psw, A5PSW_VLAN_VERIFY, mask, val); + + return 0; +} + +static int a5psw_find_vlan_entry(struct a5psw *a5psw, u16 vid) +{ + u32 vlan_res; + int i; + + /* Find vlan for this port */ + for (i = 0; i < A5PSW_VLAN_COUNT; i++) { + vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); + if (FIELD_GET(A5PSW_VLAN_RES_VLANID, vlan_res) == vid) + return i; + } + + return -1; +} + +static int a5psw_new_vlan_res_entry(struct a5psw *a5psw, u16 newvid) +{ + u32 vlan_res; + int i; + + /* Find a free VLAN entry */ + for (i = 0; i < A5PSW_VLAN_COUNT; i++) { + vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); + if (!(FIELD_GET(A5PSW_VLAN_RES_PORTMASK, vlan_res))) { + vlan_res = FIELD_PREP(A5PSW_VLAN_RES_VLANID, newvid); + a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(i), vlan_res); + return i; + } + } + + return -1; +} + +static void a5psw_port_vlan_tagged_cfg(struct a5psw *a5psw, + unsigned int vlan_res_id, int port, + bool set) +{ + u32 mask = A5PSW_VLAN_RES_WR_PORTMASK | A5PSW_VLAN_RES_RD_TAGMASK | + BIT(port); + u32 vlan_res_off = A5PSW_VLAN_RES(vlan_res_id); + u32 val = A5PSW_VLAN_RES_WR_TAGMASK, reg; + + if (set) + val |= BIT(port); + + /* Toggle tag mask read */ + a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); + reg = a5psw_reg_readl(a5psw, vlan_res_off); + a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); + + reg &= ~mask; + reg |= val; + a5psw_reg_writel(a5psw, vlan_res_off, reg); +} + +static void a5psw_port_vlan_cfg(struct a5psw *a5psw, unsigned int vlan_res_id, + int port, bool set) +{ + u32 mask = A5PSW_VLAN_RES_WR_TAGMASK | BIT(port); + u32 reg = A5PSW_VLAN_RES_WR_PORTMASK; + + if (set) + reg |= BIT(port); + + a5psw_reg_rmw(a5psw, A5PSW_VLAN_RES(vlan_res_id), mask, reg); +} + +static int a5psw_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) +{ + bool tagged = !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct a5psw *a5psw = ds->priv; + u16 vid = vlan->vid; + int vlan_res_id; + + dev_dbg(a5psw->dev, "Add VLAN %d on port %d, %s, %s\n", + vid, port, tagged ? "tagged" : "untagged", + pvid ? "PVID" : "no PVID"); + + vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); + if (vlan_res_id < 0) { + vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid); + if (vlan_res_id < 0) + return -ENOSPC; + } + + a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, true); + if (tagged) + a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, true); + + /* Configure port to tag with corresponding VID, but do not enable it + * yet: wait for vlan filtering to be enabled to enable vlan port + * tagging + */ + if (pvid) + a5psw_reg_writel(a5psw, A5PSW_SYSTEM_TAGINFO(port), vid); + + return 0; +} + +static int a5psw_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct a5psw *a5psw = ds->priv; + u16 vid = vlan->vid; + int vlan_res_id; + + dev_dbg(a5psw->dev, "Removing VLAN %d on port %d\n", vid, port); + + vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); + if (vlan_res_id < 0) + return -EINVAL; + + a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, false); + a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, false); + + return 0; +} + static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port) { u32 reg_lo, reg_hi; @@ -756,6 +896,27 @@ static void a5psw_get_eth_ctrl_stats(struct dsa_switch *ds, int port, ctrl_stats->MACControlFramesReceived = stat; } +static void a5psw_vlan_setup(struct a5psw *a5psw, int port) +{ + u32 reg; + + /* Enable TAG always mode for the port, this is actually controlled + * by VLAN_IN_MODE_ENA field which will be used for PVID insertion + */ + reg = A5PSW_VLAN_IN_MODE_TAG_ALWAYS; + reg <<= A5PSW_VLAN_IN_MODE_PORT_SHIFT(port); + a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE, A5PSW_VLAN_IN_MODE_PORT(port), + reg); + + /* Set transparent mode for output frame manipulation, this will depend + * on the VLAN_RES configuration mode + */ + reg = A5PSW_VLAN_OUT_MODE_TRANSPARENT; + reg <<= A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port); + a5psw_reg_rmw(a5psw, A5PSW_VLAN_OUT_MODE, + A5PSW_VLAN_OUT_MODE_PORT(port), reg); +} + static int a5psw_setup(struct dsa_switch *ds) { struct a5psw *a5psw = ds->priv; @@ -830,6 +991,8 @@ static int a5psw_setup(struct dsa_switch *ds) /* Enable standalone mode for user ports */ if (dsa_port_is_user(dp)) a5psw_port_set_standalone(a5psw, port, true); + + a5psw_vlan_setup(a5psw, port); } return 0; @@ -859,6 +1022,9 @@ static const struct dsa_switch_ops a5psw_switch_ops = { .port_bridge_flags = a5psw_port_bridge_flags, .port_stp_state_set = a5psw_port_stp_state_set, .port_fast_age = a5psw_port_fast_age, + .port_vlan_filtering = a5psw_port_vlan_filtering, + .port_vlan_add = a5psw_port_vlan_add, + .port_vlan_del = a5psw_port_vlan_del, .port_fdb_add = a5psw_port_fdb_add, .port_fdb_del = a5psw_port_fdb_del, .port_fdb_dump = a5psw_port_fdb_dump, diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h index b869192eef3f..d54acedac194 100644 --- a/drivers/net/dsa/rzn1_a5psw.h +++ b/drivers/net/dsa/rzn1_a5psw.h @@ -51,7 +51,9 @@ #define A5PSW_VLAN_IN_MODE_TAG_ALWAYS 0x2 #define A5PSW_VLAN_OUT_MODE 0x2C -#define A5PSW_VLAN_OUT_MODE_PORT(port) (GENMASK(1, 0) << ((port) * 2)) +#define A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port) ((port) * 2) +#define A5PSW_VLAN_OUT_MODE_PORT(port) (GENMASK(1, 0) << \ + A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port)) #define A5PSW_VLAN_OUT_MODE_DIS 0x0 #define A5PSW_VLAN_OUT_MODE_STRIP 0x1 #define A5PSW_VLAN_OUT_MODE_TAG_THROUGH 0x2 @@ -60,7 +62,7 @@ #define A5PSW_VLAN_IN_MODE_ENA 0x30 #define A5PSW_VLAN_TAG_ID 0x34 -#define A5PSW_SYSTEM_TAGINFO(port) (0x200 + A5PSW_PORT_OFFSET(port)) +#define A5PSW_SYSTEM_TAGINFO(port) (0x200 + 4 * (port)) #define A5PSW_AUTH_PORT(port) (0x240 + 4 * (port)) #define A5PSW_AUTH_PORT_AUTHORIZED BIT(0) @@ -69,7 +71,7 @@ #define A5PSW_VLAN_RES_WR_PORTMASK BIT(30) #define A5PSW_VLAN_RES_WR_TAGMASK BIT(29) #define A5PSW_VLAN_RES_RD_TAGMASK BIT(28) -#define A5PSW_VLAN_RES_ID GENMASK(16, 5) +#define A5PSW_VLAN_RES_VLANID GENMASK(16, 5) #define A5PSW_VLAN_RES_PORTMASK GENMASK(4, 0) #define A5PSW_RXMATCH_CONFIG(port) (0x3e80 + 4 * (port)) -- cgit From ea6f782fe5841249456c4b64c38b9c4508e05529 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 10 Aug 2023 14:25:15 +0200 Subject: ethernet: ldmvsw: mark ldmvsw_open() static The function is exported for no reason and should just be static: drivers/net/ethernet/sun/ldmvsw.c:127:5: error: no previous prototype for 'ldmvsw_open' [-Werror=missing-prototypes] Signed-off-by: Arnd Bergmann Reviewed-by: Simon Horman Tested-by: Simon Horman # build-tested Link: https://lore.kernel.org/r/20230810122528.1220434-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sun/ldmvsw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 734a817d3c94..a9a6670b5ff1 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -124,7 +124,7 @@ static void vsw_set_rx_mode(struct net_device *dev) return sunvnet_set_rx_mode_common(dev, port->vp); } -int ldmvsw_open(struct net_device *dev) +static int ldmvsw_open(struct net_device *dev) { struct vnet_port *port = netdev_priv(dev); struct vio_driver_state *vio = &port->vio; @@ -136,7 +136,6 @@ int ldmvsw_open(struct net_device *dev) return 0; } -EXPORT_SYMBOL_GPL(ldmvsw_open); #ifdef CONFIG_NET_POLL_CONTROLLER static void vsw_poll_controller(struct net_device *dev) -- cgit From 7191c140faa2631dd28d382ec53fb94d47c170cc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 10 Aug 2023 14:25:16 +0200 Subject: ethernet: atarilance: mark init function static The init function is only referenced locally, so it should be static to avoid this warning: drivers/net/ethernet/amd/atarilance.c:370:28: error: no previous prototype for 'atarilance_probe' [-Werror=missing-prototypes] Signed-off-by: Arnd Bergmann Reviewed-by: Yang Yingliang Link: https://lore.kernel.org/r/20230810122528.1220434-2-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/atarilance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c index ec704222925d..751454d305c6 100644 --- a/drivers/net/ethernet/amd/atarilance.c +++ b/drivers/net/ethernet/amd/atarilance.c @@ -367,7 +367,7 @@ static void *slow_memcpy( void *dst, const void *src, size_t len ) } -struct net_device * __init atarilance_probe(void) +static struct net_device * __init atarilance_probe(void) { int i; static int found; -- cgit From 2045b3938ffad5bc986f68b9bb44acb188c73792 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 11 Aug 2023 18:50:05 +0800 Subject: net: e1000: Remove unused declarations Commit 675ad47375c7 ("e1000: Use netdev_, pr_ and dev_") declared but never implemented e1000_get_hw_dev_name(). Commit 1532ecea1deb ("e1000: drop dead pcie code from e1000") removed e1000_check_mng_mode()/e1000_blink_led_start() but not the declarations. Commit c46b59b241ec ("e1000: Remove unused function e1000_mta_set.") removed e1000_mta_set() but not its declaration. Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000/e1000.h | 1 - drivers/net/ethernet/intel/e1000/e1000_hw.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 4817eb13ca6f..75f3fd1d8d6e 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -347,6 +347,5 @@ bool e1000_has_link(struct e1000_adapter *adapter); void e1000_power_up_phy(struct e1000_adapter *); void e1000_set_ethtool_ops(struct net_device *netdev); void e1000_check_options(struct e1000_adapter *adapter); -char *e1000_get_hw_dev_name(struct e1000_hw *hw); #endif /* _E1000_H_ */ diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.h b/drivers/net/ethernet/intel/e1000/e1000_hw.h index b57a04954ccf..95cdd17134e5 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_hw.h +++ b/drivers/net/ethernet/intel/e1000/e1000_hw.h @@ -343,7 +343,6 @@ struct e1000_host_mng_dhcp_cookie { }; #endif -bool e1000_check_mng_mode(struct e1000_hw *hw); s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data); s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw); s32 e1000_update_eeprom_checksum(struct e1000_hw *hw); @@ -352,7 +351,6 @@ s32 e1000_read_mac_addr(struct e1000_hw *hw); /* Filters (multicast, vlan, receive) */ u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr); -void e1000_mta_set(struct e1000_hw *hw, u32 hash_value); void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index); void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); @@ -361,7 +359,6 @@ s32 e1000_setup_led(struct e1000_hw *hw); s32 e1000_cleanup_led(struct e1000_hw *hw); s32 e1000_led_on(struct e1000_hw *hw); s32 e1000_led_off(struct e1000_hw *hw); -s32 e1000_blink_led_start(struct e1000_hw *hw); /* Adaptive IFS Functions */ -- cgit From fcbb797458e123b3f304606199ded27b042118b1 Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Fri, 11 Aug 2023 19:06:58 +0800 Subject: et131x: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Zheng Zengkai Signed-off-by: David S. Miller --- drivers/net/ethernet/agere/et131x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index 5fab589b3ddf..3d9220f9c9fe 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c @@ -3982,8 +3982,7 @@ static int et131x_pci_setup(struct pci_dev *pdev, } adapter->mii_bus->name = "et131x_eth_mii"; - snprintf(adapter->mii_bus->id, MII_BUS_ID_SIZE, "%x", - (adapter->pdev->bus->number << 8) | adapter->pdev->devfn); + snprintf(adapter->mii_bus->id, MII_BUS_ID_SIZE, "%x", pci_dev_id(adapter->pdev)); adapter->mii_bus->priv = netdev; adapter->mii_bus->read = et131x_mdio_read; adapter->mii_bus->write = et131x_mdio_write; -- cgit From 6ecb2ced346f6d2209428ef86cae83269af2d744 Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Fri, 11 Aug 2023 19:06:59 +0800 Subject: tg3: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Zheng Zengkai Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 5ef073a79ce9..7f956cf36337 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1539,8 +1539,7 @@ static int tg3_mdio_init(struct tg3 *tp) return -ENOMEM; tp->mdio_bus->name = "tg3 mdio bus"; - snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x", - (tp->pdev->bus->number << 8) | tp->pdev->devfn); + snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x", pci_dev_id(tp->pdev)); tp->mdio_bus->priv = tp; tp->mdio_bus->parent = &tp->pdev->dev; tp->mdio_bus->read = &tg3_mdio_read; -- cgit From adc4d18538ec5e7ae44323130257c2ba47da2d57 Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Fri, 11 Aug 2023 19:07:00 +0800 Subject: net: smsc: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Zheng Zengkai Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smsc9420.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index 3b26f1d86beb..e1c4a11c1f18 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -1144,8 +1144,7 @@ static int smsc9420_mii_init(struct net_device *dev) goto err_out_1; } pd->mii_bus->name = DRV_MDIONAME; - snprintf(pd->mii_bus->id, MII_BUS_ID_SIZE, "%x", - (pd->pdev->bus->number << 8) | pd->pdev->devfn); + snprintf(pd->mii_bus->id, MII_BUS_ID_SIZE, "%x", pci_dev_id(pd->pdev)); pd->mii_bus->priv = pd; pd->mii_bus->read = smsc9420_mii_read; pd->mii_bus->write = smsc9420_mii_write; -- cgit From ca51d1356071e40d48169a308e996be779be56d4 Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Fri, 11 Aug 2023 19:07:01 +0800 Subject: net: tc35815: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Zheng Zengkai Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/tc35815.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index b50be67b398b..14cf6ecf6d0d 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -667,8 +667,7 @@ static int tc_mii_init(struct net_device *dev) lp->mii_bus->name = "tc35815_mii_bus"; lp->mii_bus->read = tc_mdio_read; lp->mii_bus->write = tc_mdio_write; - snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", - (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn); + snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", pci_dev_id(lp->pci_dev)); lp->mii_bus->priv = dev; lp->mii_bus->parent = &lp->pci_dev->dev; err = mdiobus_register(lp->mii_bus); -- cgit From cf9b107f5fdddcd73b77169c30949d5e12e56eae Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Fri, 11 Aug 2023 19:07:02 +0800 Subject: net: ngbe: use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Zheng Zengkai Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c index cc2f325a52f7..fe20f02ecb3a 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c @@ -266,8 +266,7 @@ int ngbe_mdio_init(struct wx *wx) mii_bus->write_c45 = ngbe_phy_write_reg_mdi_c45; } - snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", - (pdev->bus->number << 8) | pdev->devfn); + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", pci_dev_id(pdev)); ret = devm_mdiobus_register(&pdev->dev, mii_bus); if (ret) return ret; -- cgit From 2f4503f94c5d81d1589842bfb457be466c8c670b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 11 Aug 2023 14:53:52 +0300 Subject: net: pcs: lynx: fix lynx_pcs_link_up_sgmii() not doing anything in fixed-link mode lynx_pcs_link_up_sgmii() is supposed to update the PCS speed and duplex for the non-inband operating modes, and prior to the blamed commit, it did just that, but a mistake sneaked into the conversion and reversed the condition. It is easy for this to go undetected on platforms that also initialize the PCS in the bootloader, because Linux doesn't reset it (although maybe it should). The nature of the bug is that phylink will not touch the IF_MODE_HALF_DUPLEX | IF_MODE_SPEED_MSK fields when it should, and it will apparently keep working if the previous values set by the bootloader were correct. Fixes: c689a6528c22 ("net: pcs: lynx: update PCS driver to use neg_mode") Signed-off-by: Vladimir Oltean Reviewed-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/pcs/pcs-lynx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 9021b96d4f9d..dc3962b2aa6b 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c @@ -216,7 +216,7 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, /* The PCS needs to be configured manually only * when not operating on in-band mode */ - if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) return; if (duplex == DUPLEX_HALF) -- cgit From 54f00cce11786742bd11e5e68c3bf85e6dc048c9 Mon Sep 17 00:00:00 2001 From: William Tu Date: Wed, 9 Aug 2023 21:13:04 -0700 Subject: vmxnet3: Add XDP support. The patch adds native-mode XDP support: XDP DROP, PASS, TX, and REDIRECT. Background: The vmxnet3 rx consists of three rings: ring0, ring1, and dataring. For r0 and r1, buffers at r0 are allocated using alloc_skb APIs and dma mapped to the ring's descriptor. If LRO is enabled and packet size larger than 3K, VMXNET3_MAX_SKB_BUF_SIZE, then r1 is used to mapped the rest of the buffer larger than VMXNET3_MAX_SKB_BUF_SIZE. Each buffer in r1 is allocated using alloc_page. So for LRO packets, the payload will be in one buffer from r0 and multiple from r1, for non-LRO packets, only one descriptor in r0 is used for packet size less than 3k. When receiving a packet, the first descriptor will have the sop (start of packet) bit set, and the last descriptor will have the eop (end of packet) bit set. Non-LRO packets will have only one descriptor with both sop and eop set. Other than r0 and r1, vmxnet3 dataring is specifically designed for handling packets with small size, usually 128 bytes, defined in VMXNET3_DEF_RXDATA_DESC_SIZE, by simply copying the packet from the backend driver in ESXi to the ring's memory region at front-end vmxnet3 driver, in order to avoid memory mapping/unmapping overhead. In summary, packet size: A. < 128B: use dataring B. 128B - 3K: use ring0 (VMXNET3_RX_BUF_SKB) C. > 3K: use ring0 and ring1 (VMXNET3_RX_BUF_SKB + VMXNET3_RX_BUF_PAGE) As a result, the patch adds XDP support for packets using dataring and r0 (case A and B), not the large packet size when LRO is enabled. XDP Implementation: When user loads and XDP prog, vmxnet3 driver checks configurations, such as mtu, lro, and re-allocate the rx buffer size for reserving the extra headroom, XDP_PACKET_HEADROOM, for XDP frame. The XDP prog will then be associated with every rx queue of the device. Note that when using dataring for small packet size, vmxnet3 (front-end driver) doesn't control the buffer allocation, as a result we allocate a new page and copy packet from the dataring to XDP frame. The receive side of XDP is implemented for case A and B, by invoking the bpf program at vmxnet3_rq_rx_complete and handle its returned action. The vmxnet3_process_xdp(), vmxnet3_process_xdp_small() function handles the ring0 and dataring case separately, and decides the next journey of the packet afterward. For TX, vmxnet3 has split header design. Outgoing packets are parsed first and protocol headers (L2/L3/L4) are copied to the backend. The rest of the payload are dma mapped. Since XDP_TX does not parse the packet protocol, the entire XDP frame is dma mapped for transmission and transmitted in a batch. Later on, the frame is freed and recycled back to the memory pool. Performance: Tested using two VMs inside one ESXi vSphere 7.0 machine, using single core on each vmxnet3 device, sender using DPDK testpmd tx-mode attached to vmxnet3 device, sending 64B or 512B UDP packet. VM1 txgen: $ dpdk-testpmd -l 0-3 -n 1 -- -i --nb-cores=3 \ --forward-mode=txonly --eth-peer=0, option: add "--txonly-multi-flow" option: use --txpkts=512 or 64 byte VM2 running XDP: $ ./samples/bpf/xdp_rxq_info -d ens160 -a --skb-mode $ ./samples/bpf/xdp_rxq_info -d ens160 -a options: XDP_DROP, XDP_PASS, XDP_TX To test REDIRECT to cpu 0, use $ ./samples/bpf/xdp_redirect_cpu -d ens160 -c 0 -e drop Single core performance comparison with skb-mode. 64B: skb-mode -> native-mode XDP_DROP: 1.6Mpps -> 2.4Mpps XDP_PASS: 338Kpps -> 367Kpps XDP_TX: 1.1Mpps -> 2.3Mpps REDIRECT-drop: 1.3Mpps -> 2.3Mpps 512B: skb-mode -> native-mode XDP_DROP: 863Kpps -> 1.3Mpps XDP_PASS: 275Kpps -> 376Kpps XDP_TX: 554Kpps -> 1.2Mpps REDIRECT-drop: 659Kpps -> 1.2Mpps Demo: https://youtu.be/4lm1CSCi78Q Future work: - XDP frag support - use napi_consume_skb() instead of dev_kfree_skb_any at unmap - stats using u64_stats_t - using bitfield macro BIT() - optimization for DMA synchronization using actual frame length, instead of always max_len Signed-off-by: William Tu Reviewed-by: Alexander Duyck Reviewed-by: Alexander Lobakin Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/vmxnet3/Makefile | 2 +- drivers/net/vmxnet3/vmxnet3_drv.c | 236 ++++++++++++++++--- drivers/net/vmxnet3/vmxnet3_ethtool.c | 23 ++ drivers/net/vmxnet3/vmxnet3_int.h | 43 +++- drivers/net/vmxnet3/vmxnet3_xdp.c | 419 ++++++++++++++++++++++++++++++++++ drivers/net/vmxnet3/vmxnet3_xdp.h | 47 ++++ 7 files changed, 729 insertions(+), 42 deletions(-) create mode 100644 drivers/net/vmxnet3/vmxnet3_xdp.c create mode 100644 drivers/net/vmxnet3/vmxnet3_xdp.h (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4953c1494723..be43cd08027b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -571,6 +571,7 @@ config VMXNET3 tristate "VMware VMXNET3 ethernet driver" depends on PCI && INET depends on PAGE_SIZE_LESS_THAN_64KB + select PAGE_POOL help This driver supports VMware's vmxnet3 virtual ethernet NIC. To compile this driver as a module, choose M here: the diff --git a/drivers/net/vmxnet3/Makefile b/drivers/net/vmxnet3/Makefile index a666a88ac1ff..f82870c10205 100644 --- a/drivers/net/vmxnet3/Makefile +++ b/drivers/net/vmxnet3/Makefile @@ -32,4 +32,4 @@ obj-$(CONFIG_VMXNET3) += vmxnet3.o -vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o +vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o vmxnet3_xdp.o diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 7fa74b8b2100..0578864792b6 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -28,6 +28,7 @@ #include #include "vmxnet3_int.h" +#include "vmxnet3_xdp.h" char vmxnet3_driver_name[] = "vmxnet3"; #define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver" @@ -338,14 +339,16 @@ static void vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi, struct pci_dev *pdev) { - if (tbi->map_type == VMXNET3_MAP_SINGLE) + u32 map_type = tbi->map_type; + + if (map_type & VMXNET3_MAP_SINGLE) dma_unmap_single(&pdev->dev, tbi->dma_addr, tbi->len, DMA_TO_DEVICE); - else if (tbi->map_type == VMXNET3_MAP_PAGE) + else if (map_type & VMXNET3_MAP_PAGE) dma_unmap_page(&pdev->dev, tbi->dma_addr, tbi->len, DMA_TO_DEVICE); else - BUG_ON(tbi->map_type != VMXNET3_MAP_NONE); + BUG_ON(map_type & ~VMXNET3_MAP_XDP); tbi->map_type = VMXNET3_MAP_NONE; /* to help debugging */ } @@ -353,19 +356,20 @@ vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi, static int vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq, - struct pci_dev *pdev, struct vmxnet3_adapter *adapter) + struct pci_dev *pdev, struct vmxnet3_adapter *adapter, + struct xdp_frame_bulk *bq) { - struct sk_buff *skb; + struct vmxnet3_tx_buf_info *tbi; int entries = 0; + u32 map_type; /* no out of order completion */ BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp); BUG_ON(VMXNET3_TXDESC_GET_EOP(&(tq->tx_ring.base[eop_idx].txd)) != 1); - skb = tq->buf_info[eop_idx].skb; - BUG_ON(skb == NULL); - tq->buf_info[eop_idx].skb = NULL; - + tbi = &tq->buf_info[eop_idx]; + BUG_ON(!tbi->skb); + map_type = tbi->map_type; VMXNET3_INC_RING_IDX_ONLY(eop_idx, tq->tx_ring.size); while (tq->tx_ring.next2comp != eop_idx) { @@ -381,7 +385,14 @@ vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq, entries++; } - dev_kfree_skb_any(skb); + if (map_type & VMXNET3_MAP_XDP) + xdp_return_frame_bulk(tbi->xdpf, bq); + else + dev_kfree_skb_any(tbi->skb); + + /* xdpf and skb are in an anonymous union. */ + tbi->skb = NULL; + return entries; } @@ -390,8 +401,12 @@ static int vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { - int completed = 0; union Vmxnet3_GenericDesc *gdesc; + struct xdp_frame_bulk bq; + int completed = 0; + + xdp_frame_bulk_init(&bq); + rcu_read_lock(); gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) { @@ -402,11 +417,13 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq, completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX( &gdesc->tcd), tq, adapter->pdev, - adapter); + adapter, &bq); vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring); gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; } + xdp_flush_frame_bulk(&bq); + rcu_read_unlock(); if (completed) { spin_lock(&tq->tx_lock); @@ -426,26 +443,36 @@ static void vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { + struct xdp_frame_bulk bq; + u32 map_type; int i; + xdp_frame_bulk_init(&bq); + rcu_read_lock(); + while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) { struct vmxnet3_tx_buf_info *tbi; tbi = tq->buf_info + tq->tx_ring.next2comp; + map_type = tbi->map_type; vmxnet3_unmap_tx_buf(tbi, adapter->pdev); if (tbi->skb) { - dev_kfree_skb_any(tbi->skb); + if (map_type & VMXNET3_MAP_XDP) + xdp_return_frame_bulk(tbi->xdpf, &bq); + else + dev_kfree_skb_any(tbi->skb); tbi->skb = NULL; } vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring); } - /* sanity check, verify all buffers are indeed unmapped and freed */ - for (i = 0; i < tq->tx_ring.size; i++) { - BUG_ON(tq->buf_info[i].skb != NULL || - tq->buf_info[i].map_type != VMXNET3_MAP_NONE); - } + xdp_flush_frame_bulk(&bq); + rcu_read_unlock(); + + /* sanity check, verify all buffers are indeed unmapped */ + for (i = 0; i < tq->tx_ring.size; i++) + BUG_ON(tq->buf_info[i].map_type != VMXNET3_MAP_NONE); tq->tx_ring.gen = VMXNET3_INIT_GEN; tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0; @@ -599,7 +626,17 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, gd = ring->base + ring->next2fill; rbi->comp_state = VMXNET3_RXD_COMP_PENDING; - if (rbi->buf_type == VMXNET3_RX_BUF_SKB) { + if (rbi->buf_type == VMXNET3_RX_BUF_XDP) { + void *data = vmxnet3_pp_get_buff(rq->page_pool, + &rbi->dma_addr, + GFP_KERNEL); + if (!data) { + rq->stats.rx_buf_alloc_failure++; + break; + } + rbi->page = virt_to_page(data); + val = VMXNET3_RXD_BTYPE_HEAD << VMXNET3_RXD_BTYPE_SHIFT; + } else if (rbi->buf_type == VMXNET3_RX_BUF_SKB) { if (rbi->skb == NULL) { rbi->skb = __netdev_alloc_skb_ip_align(adapter->netdev, rbi->len, @@ -1263,6 +1300,63 @@ drop_pkt: return NETDEV_TX_OK; } +static int +vmxnet3_create_pp(struct vmxnet3_adapter *adapter, + struct vmxnet3_rx_queue *rq, int size) +{ + bool xdp_prog = vmxnet3_xdp_enabled(adapter); + const struct page_pool_params pp_params = { + .order = 0, + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .pool_size = size, + .nid = NUMA_NO_NODE, + .dev = &adapter->pdev->dev, + .offset = VMXNET3_XDP_RX_OFFSET, + .max_len = VMXNET3_XDP_MAX_FRSIZE, + .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, + }; + struct page_pool *pp; + int err; + + pp = page_pool_create(&pp_params); + if (IS_ERR(pp)) + return PTR_ERR(pp); + + err = xdp_rxq_info_reg(&rq->xdp_rxq, adapter->netdev, rq->qid, + rq->napi.napi_id); + if (err < 0) + goto err_free_pp; + + err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq, MEM_TYPE_PAGE_POOL, pp); + if (err) + goto err_unregister_rxq; + + rq->page_pool = pp; + + return 0; + +err_unregister_rxq: + xdp_rxq_info_unreg(&rq->xdp_rxq); +err_free_pp: + page_pool_destroy(pp); + + return err; +} + +void * +vmxnet3_pp_get_buff(struct page_pool *pp, dma_addr_t *dma_addr, + gfp_t gfp_mask) +{ + struct page *page; + + page = page_pool_alloc_pages(pp, gfp_mask | __GFP_NOWARN); + if (unlikely(!page)) + return NULL; + + *dma_addr = page_pool_get_dma_addr(page) + pp->p.offset; + + return page_address(page); +} static netdev_tx_t vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -1423,6 +1517,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, struct Vmxnet3_RxDesc rxCmdDesc; struct Vmxnet3_RxCompDesc rxComp; #endif + bool need_flush = false; + vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp); while (rcd->gen == rq->comp_ring.gen) { @@ -1463,6 +1559,31 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, goto rcd_done; } + if (rcd->sop && rcd->eop && vmxnet3_xdp_enabled(adapter)) { + struct sk_buff *skb_xdp_pass; + int act; + + if (VMXNET3_RX_DATA_RING(adapter, rcd->rqID)) { + ctx->skb = NULL; + goto skip_xdp; /* Handle it later. */ + } + + if (rbi->buf_type != VMXNET3_RX_BUF_XDP) + goto rcd_done; + + act = vmxnet3_process_xdp(adapter, rq, rcd, rbi, rxd, + &skb_xdp_pass); + if (act == XDP_PASS) { + ctx->skb = skb_xdp_pass; + goto sop_done; + } + ctx->skb = NULL; + need_flush |= act == XDP_REDIRECT; + + goto rcd_done; + } +skip_xdp: + if (rcd->sop) { /* first buf of the pkt */ bool rxDataRingUsed; u16 len; @@ -1471,7 +1592,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, (rcd->rqID != rq->qid && rcd->rqID != rq->dataRingQid)); - BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB); + BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB && + rbi->buf_type != VMXNET3_RX_BUF_XDP); BUG_ON(ctx->skb != NULL || rbi->skb == NULL); if (unlikely(rcd->len == 0)) { @@ -1489,6 +1611,25 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, rxDataRingUsed = VMXNET3_RX_DATA_RING(adapter, rcd->rqID); len = rxDataRingUsed ? rcd->len : rbi->len; + + if (rxDataRingUsed && vmxnet3_xdp_enabled(adapter)) { + struct sk_buff *skb_xdp_pass; + size_t sz; + int act; + + sz = rcd->rxdIdx * rq->data_ring.desc_size; + act = vmxnet3_process_xdp_small(adapter, rq, + &rq->data_ring.base[sz], + rcd->len, + &skb_xdp_pass); + if (act == XDP_PASS) { + ctx->skb = skb_xdp_pass; + goto sop_done; + } + need_flush |= act == XDP_REDIRECT; + + goto rcd_done; + } new_skb = netdev_alloc_skb_ip_align(adapter->netdev, len); if (new_skb == NULL) { @@ -1621,6 +1762,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, } +sop_done: skb = ctx->skb; if (rcd->eop) { u32 mtu = adapter->netdev->mtu; @@ -1757,6 +1899,8 @@ refill_buf: vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp); } + if (need_flush) + xdp_do_flush(); return num_pkts; } @@ -1775,24 +1919,32 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq, for (ring_idx = 0; ring_idx < 2; ring_idx++) { for (i = 0; i < rq->rx_ring[ring_idx].size; i++) { + struct vmxnet3_rx_buf_info *rbi; #ifdef __BIG_ENDIAN_BITFIELD struct Vmxnet3_RxDesc rxDesc; #endif + + rbi = &rq->buf_info[ring_idx][i]; vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[i].rxd, &rxDesc); if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD && - rq->buf_info[ring_idx][i].skb) { + rbi->page && rbi->buf_type == VMXNET3_RX_BUF_XDP) { + page_pool_recycle_direct(rq->page_pool, + rbi->page); + rbi->page = NULL; + } else if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD && + rbi->skb) { dma_unmap_single(&adapter->pdev->dev, rxd->addr, rxd->len, DMA_FROM_DEVICE); - dev_kfree_skb(rq->buf_info[ring_idx][i].skb); - rq->buf_info[ring_idx][i].skb = NULL; + dev_kfree_skb(rbi->skb); + rbi->skb = NULL; } else if (rxd->btype == VMXNET3_RXD_BTYPE_BODY && - rq->buf_info[ring_idx][i].page) { + rbi->page) { dma_unmap_page(&adapter->pdev->dev, rxd->addr, rxd->len, DMA_FROM_DEVICE); - put_page(rq->buf_info[ring_idx][i].page); - rq->buf_info[ring_idx][i].page = NULL; + put_page(rbi->page); + rbi->page = NULL; } } @@ -1813,6 +1965,7 @@ vmxnet3_rq_cleanup_all(struct vmxnet3_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) vmxnet3_rq_cleanup(&adapter->rx_queue[i], adapter); + rcu_assign_pointer(adapter->xdp_bpf_prog, NULL); } @@ -1842,6 +1995,11 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, } } + if (xdp_rxq_info_is_reg(&rq->xdp_rxq)) + xdp_rxq_info_unreg(&rq->xdp_rxq); + page_pool_destroy(rq->page_pool); + rq->page_pool = NULL; + if (rq->data_ring.base) { dma_free_coherent(&adapter->pdev->dev, rq->rx_ring[0].size * rq->data_ring.desc_size, @@ -1885,14 +2043,16 @@ static int vmxnet3_rq_init(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter) { - int i; + int i, err; /* initialize buf_info */ for (i = 0; i < rq->rx_ring[0].size; i++) { - /* 1st buf for a pkt is skbuff */ + /* 1st buf for a pkt is skbuff or xdp page */ if (i % adapter->rx_buf_per_pkt == 0) { - rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_SKB; + rq->buf_info[0][i].buf_type = vmxnet3_xdp_enabled(adapter) ? + VMXNET3_RX_BUF_XDP : + VMXNET3_RX_BUF_SKB; rq->buf_info[0][i].len = adapter->skb_buf_size; } else { /* subsequent bufs for a pkt is frag */ rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_PAGE; @@ -1913,8 +2073,18 @@ vmxnet3_rq_init(struct vmxnet3_rx_queue *rq, rq->rx_ring[i].gen = VMXNET3_INIT_GEN; rq->rx_ring[i].isOutOfOrder = 0; } + + err = vmxnet3_create_pp(adapter, rq, + rq->rx_ring[0].size + rq->rx_ring[1].size); + if (err) + return err; + if (vmxnet3_rq_alloc_rx_buf(rq, 0, rq->rx_ring[0].size - 1, adapter) == 0) { + xdp_rxq_info_unreg(&rq->xdp_rxq); + page_pool_destroy(rq->page_pool); + rq->page_pool = NULL; + /* at least has 1 rx buffer for the 1st ring */ return -ENOMEM; } @@ -2016,7 +2186,7 @@ err: } -static int +int vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter) { int i, err = 0; @@ -3053,7 +3223,7 @@ vmxnet3_free_pci_resources(struct vmxnet3_adapter *adapter) } -static void +void vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter) { size_t sz, i, ring0_size, ring1_size, comp_size; @@ -3612,6 +3782,8 @@ vmxnet3_probe_device(struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = vmxnet3_netpoll, #endif + .ndo_bpf = vmxnet3_xdp, + .ndo_xdp_xmit = vmxnet3_xdp_xmit, }; int err; u32 ver; @@ -3864,6 +4036,8 @@ vmxnet3_probe_device(struct pci_dev *pdev, SET_NETDEV_DEV(netdev, &pdev->dev); vmxnet3_declare_features(adapter); + netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_NDO_XMIT; adapter->rxdata_desc_size = VMXNET3_VERSION_GE_3(adapter) ? VMXNET3_DEF_RXDATA_DESC_SIZE : 0; diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 18cf7c723201..98c22d7d87a2 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -28,6 +28,7 @@ #include "vmxnet3_int.h" #include #include +#include "vmxnet3_xdp.h" #define VXLAN_UDP_PORT 8472 @@ -76,6 +77,10 @@ vmxnet3_tq_driver_stats[] = { copy_skb_header) }, { " giant hdr", offsetof(struct vmxnet3_tq_driver_stats, oversized_hdr) }, + { " xdp xmit", offsetof(struct vmxnet3_tq_driver_stats, + xdp_xmit) }, + { " xdp xmit err", offsetof(struct vmxnet3_tq_driver_stats, + xdp_xmit_err) }, }; /* per rq stats maintained by the device */ @@ -106,6 +111,16 @@ vmxnet3_rq_driver_stats[] = { drop_fcs) }, { " rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats, rx_buf_alloc_failure) }, + { " xdp packets", offsetof(struct vmxnet3_rq_driver_stats, + xdp_packets) }, + { " xdp tx", offsetof(struct vmxnet3_rq_driver_stats, + xdp_tx) }, + { " xdp redirects", offsetof(struct vmxnet3_rq_driver_stats, + xdp_redirects) }, + { " xdp drops", offsetof(struct vmxnet3_rq_driver_stats, + xdp_drops) }, + { " xdp aborted", offsetof(struct vmxnet3_rq_driver_stats, + xdp_aborted) }, }; /* global stats maintained by the driver */ @@ -249,10 +264,18 @@ vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) netdev_features_t vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features) { + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + /* If Rx checksum is disabled, then LRO should also be disabled */ if (!(features & NETIF_F_RXCSUM)) features &= ~NETIF_F_LRO; + /* If XDP is enabled, then LRO should not be enabled */ + if (vmxnet3_xdp_enabled(adapter) && (features & NETIF_F_LRO)) { + netdev_err(netdev, "LRO is not supported with XDP"); + features &= ~NETIF_F_LRO; + } + return features; } diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 3367db23aa13..915aaf18c409 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -56,6 +56,9 @@ #include #include #include +#include +#include +#include #include "vmxnet3_defs.h" @@ -188,19 +191,20 @@ struct vmxnet3_tx_data_ring { dma_addr_t basePA; }; -enum vmxnet3_buf_map_type { - VMXNET3_MAP_INVALID = 0, - VMXNET3_MAP_NONE, - VMXNET3_MAP_SINGLE, - VMXNET3_MAP_PAGE, -}; +#define VMXNET3_MAP_NONE 0 +#define VMXNET3_MAP_SINGLE BIT(0) +#define VMXNET3_MAP_PAGE BIT(1) +#define VMXNET3_MAP_XDP BIT(2) struct vmxnet3_tx_buf_info { u32 map_type; u16 len; u16 sop_idx; dma_addr_t dma_addr; - struct sk_buff *skb; + union { + struct sk_buff *skb; + struct xdp_frame *xdpf; + }; }; struct vmxnet3_tq_driver_stats { @@ -217,6 +221,9 @@ struct vmxnet3_tq_driver_stats { u64 linearized; /* # of pkts linearized */ u64 copy_skb_header; /* # of times we have to copy skb header */ u64 oversized_hdr; + + u64 xdp_xmit; + u64 xdp_xmit_err; }; struct vmxnet3_tx_ctx { @@ -253,12 +260,13 @@ struct vmxnet3_tx_queue { * stopped */ int qid; u16 txdata_desc_size; -} __attribute__((__aligned__(SMP_CACHE_BYTES))); +} ____cacheline_aligned; enum vmxnet3_rx_buf_type { VMXNET3_RX_BUF_NONE = 0, VMXNET3_RX_BUF_SKB = 1, - VMXNET3_RX_BUF_PAGE = 2 + VMXNET3_RX_BUF_PAGE = 2, + VMXNET3_RX_BUF_XDP = 3, }; #define VMXNET3_RXD_COMP_PENDING 0 @@ -285,6 +293,12 @@ struct vmxnet3_rq_driver_stats { u64 drop_err; u64 drop_fcs; u64 rx_buf_alloc_failure; + + u64 xdp_packets; /* Total packets processed by XDP. */ + u64 xdp_tx; + u64 xdp_redirects; + u64 xdp_drops; + u64 xdp_aborted; }; struct vmxnet3_rx_data_ring { @@ -307,7 +321,9 @@ struct vmxnet3_rx_queue { struct vmxnet3_rx_buf_info *buf_info[2]; struct Vmxnet3_RxQueueCtrl *shared; struct vmxnet3_rq_driver_stats stats; -} __attribute__((__aligned__(SMP_CACHE_BYTES))); + struct page_pool *page_pool; + struct xdp_rxq_info xdp_rxq; +} ____cacheline_aligned; #define VMXNET3_DEVICE_MAX_TX_QUEUES 32 #define VMXNET3_DEVICE_MAX_RX_QUEUES 32 /* Keep this value as a power of 2 */ @@ -415,6 +431,7 @@ struct vmxnet3_adapter { u16 tx_prod_offset; u16 rx_prod_offset; u16 rx_prod2_offset; + struct bpf_prog __rcu *xdp_bpf_prog; }; #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ @@ -490,6 +507,12 @@ vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter); void vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter); +int +vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter); + +void +vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter); + netdev_features_t vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features); diff --git a/drivers/net/vmxnet3/vmxnet3_xdp.c b/drivers/net/vmxnet3/vmxnet3_xdp.c new file mode 100644 index 000000000000..80ddaff759d4 --- /dev/null +++ b/drivers/net/vmxnet3/vmxnet3_xdp.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Linux driver for VMware's vmxnet3 ethernet NIC. + * Copyright (C) 2008-2023, VMware, Inc. All Rights Reserved. + * Maintained by: pv-drivers@vmware.com + * + */ + +#include "vmxnet3_int.h" +#include "vmxnet3_xdp.h" + +static void +vmxnet3_xdp_exchange_program(struct vmxnet3_adapter *adapter, + struct bpf_prog *prog) +{ + rcu_assign_pointer(adapter->xdp_bpf_prog, prog); +} + +static inline struct vmxnet3_tx_queue * +vmxnet3_xdp_get_tq(struct vmxnet3_adapter *adapter) +{ + struct vmxnet3_tx_queue *tq; + int tq_number; + int cpu; + + tq_number = adapter->num_tx_queues; + cpu = smp_processor_id(); + if (likely(cpu < tq_number)) + tq = &adapter->tx_queue[cpu]; + else + tq = &adapter->tx_queue[reciprocal_scale(cpu, tq_number)]; + + return tq; +} + +static int +vmxnet3_xdp_set(struct net_device *netdev, struct netdev_bpf *bpf, + struct netlink_ext_ack *extack) +{ + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + struct bpf_prog *new_bpf_prog = bpf->prog; + struct bpf_prog *old_bpf_prog; + bool need_update; + bool running; + int err; + + if (new_bpf_prog && netdev->mtu > VMXNET3_XDP_MAX_MTU) { + NL_SET_ERR_MSG_FMT_MOD(extack, "MTU %u too large for XDP", + netdev->mtu); + return -EOPNOTSUPP; + } + + if (adapter->netdev->features & NETIF_F_LRO) { + NL_SET_ERR_MSG_MOD(extack, "LRO is not supported with XDP"); + adapter->netdev->features &= ~NETIF_F_LRO; + } + + old_bpf_prog = rcu_dereference(adapter->xdp_bpf_prog); + if (!new_bpf_prog && !old_bpf_prog) + return 0; + + running = netif_running(netdev); + need_update = !!old_bpf_prog != !!new_bpf_prog; + + if (running && need_update) + vmxnet3_quiesce_dev(adapter); + + vmxnet3_xdp_exchange_program(adapter, new_bpf_prog); + if (old_bpf_prog) + bpf_prog_put(old_bpf_prog); + + if (!running || !need_update) + return 0; + + if (new_bpf_prog) + xdp_features_set_redirect_target(netdev, false); + else + xdp_features_clear_redirect_target(netdev); + + vmxnet3_reset_dev(adapter); + vmxnet3_rq_destroy_all(adapter); + vmxnet3_adjust_rx_ring_size(adapter); + err = vmxnet3_rq_create_all(adapter); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "failed to re-create rx queues for XDP."); + return -EOPNOTSUPP; + } + err = vmxnet3_activate_dev(adapter); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "failed to activate device for XDP."); + return -EOPNOTSUPP; + } + clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state); + + return 0; +} + +/* This is the main xdp call used by kernel to set/unset eBPF program. */ +int +vmxnet3_xdp(struct net_device *netdev, struct netdev_bpf *bpf) +{ + switch (bpf->command) { + case XDP_SETUP_PROG: + return vmxnet3_xdp_set(netdev, bpf, bpf->extack); + default: + return -EINVAL; + } + + return 0; +} + +static int +vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, + struct xdp_frame *xdpf, + struct vmxnet3_tx_queue *tq, bool dma_map) +{ + struct vmxnet3_tx_buf_info *tbi = NULL; + union Vmxnet3_GenericDesc *gdesc; + struct vmxnet3_tx_ctx ctx; + int tx_num_deferred; + struct page *page; + u32 buf_size; + u32 dw2; + + dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; + dw2 |= xdpf->len; + ctx.sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill; + gdesc = ctx.sop_txd; + + buf_size = xdpf->len; + tbi = tq->buf_info + tq->tx_ring.next2fill; + + if (vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) == 0) { + tq->stats.tx_ring_full++; + return -ENOSPC; + } + + tbi->map_type = VMXNET3_MAP_XDP; + if (dma_map) { /* ndo_xdp_xmit */ + tbi->dma_addr = dma_map_single(&adapter->pdev->dev, + xdpf->data, buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) + return -EFAULT; + tbi->map_type |= VMXNET3_MAP_SINGLE; + } else { /* XDP buffer from page pool */ + page = virt_to_page(xdpf->data); + tbi->dma_addr = page_pool_get_dma_addr(page) + + VMXNET3_XDP_HEADROOM; + dma_sync_single_for_device(&adapter->pdev->dev, + tbi->dma_addr, buf_size, + DMA_TO_DEVICE); + } + tbi->xdpf = xdpf; + tbi->len = buf_size; + + gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; + WARN_ON_ONCE(gdesc->txd.gen == tq->tx_ring.gen); + + gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); + gdesc->dword[2] = cpu_to_le32(dw2); + + /* Setup the EOP desc */ + gdesc->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP); + + gdesc->txd.om = 0; + gdesc->txd.msscof = 0; + gdesc->txd.hlen = 0; + gdesc->txd.ti = 0; + + tx_num_deferred = le32_to_cpu(tq->shared->txNumDeferred); + le32_add_cpu(&tq->shared->txNumDeferred, 1); + tx_num_deferred++; + + vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); + + /* set the last buf_info for the pkt */ + tbi->sop_idx = ctx.sop_txd - tq->tx_ring.base; + + dma_wmb(); + gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^ + VMXNET3_TXD_GEN); + + /* No need to handle the case when tx_num_deferred doesn't reach + * threshold. Backend driver at hypervisor side will poll and reset + * tq->shared->txNumDeferred to 0. + */ + if (tx_num_deferred >= le32_to_cpu(tq->shared->txThreshold)) { + tq->shared->txNumDeferred = 0; + VMXNET3_WRITE_BAR0_REG(adapter, + VMXNET3_REG_TXPROD + tq->qid * 8, + tq->tx_ring.next2fill); + } + + return 0; +} + +static int +vmxnet3_xdp_xmit_back(struct vmxnet3_adapter *adapter, + struct xdp_frame *xdpf) +{ + struct vmxnet3_tx_queue *tq; + struct netdev_queue *nq; + int err; + + tq = vmxnet3_xdp_get_tq(adapter); + if (tq->stopped) + return -ENETDOWN; + + nq = netdev_get_tx_queue(adapter->netdev, tq->qid); + + __netif_tx_lock(nq, smp_processor_id()); + err = vmxnet3_xdp_xmit_frame(adapter, xdpf, tq, false); + __netif_tx_unlock(nq); + + return err; +} + +/* ndo_xdp_xmit */ +int +vmxnet3_xdp_xmit(struct net_device *dev, + int n, struct xdp_frame **frames, u32 flags) +{ + struct vmxnet3_adapter *adapter = netdev_priv(dev); + struct vmxnet3_tx_queue *tq; + int i; + + if (unlikely(test_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))) + return -ENETDOWN; + if (unlikely(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))) + return -EINVAL; + + tq = vmxnet3_xdp_get_tq(adapter); + if (tq->stopped) + return -ENETDOWN; + + for (i = 0; i < n; i++) { + if (vmxnet3_xdp_xmit_frame(adapter, frames[i], tq, true)) { + tq->stats.xdp_xmit_err++; + break; + } + } + tq->stats.xdp_xmit += i; + + return i; +} + +static int +vmxnet3_run_xdp(struct vmxnet3_rx_queue *rq, struct xdp_buff *xdp, + struct bpf_prog *prog) +{ + struct xdp_frame *xdpf; + struct page *page; + int err; + u32 act; + + rq->stats.xdp_packets++; + act = bpf_prog_run_xdp(prog, xdp); + page = virt_to_page(xdp->data_hard_start); + + switch (act) { + case XDP_PASS: + return act; + case XDP_REDIRECT: + err = xdp_do_redirect(rq->adapter->netdev, xdp, prog); + if (!err) { + rq->stats.xdp_redirects++; + } else { + rq->stats.xdp_drops++; + page_pool_recycle_direct(rq->page_pool, page); + } + return act; + case XDP_TX: + xdpf = xdp_convert_buff_to_frame(xdp); + if (unlikely(!xdpf || + vmxnet3_xdp_xmit_back(rq->adapter, xdpf))) { + rq->stats.xdp_drops++; + page_pool_recycle_direct(rq->page_pool, page); + } else { + rq->stats.xdp_tx++; + } + return act; + default: + bpf_warn_invalid_xdp_action(rq->adapter->netdev, prog, act); + fallthrough; + case XDP_ABORTED: + trace_xdp_exception(rq->adapter->netdev, prog, act); + rq->stats.xdp_aborted++; + break; + case XDP_DROP: + rq->stats.xdp_drops++; + break; + } + + page_pool_recycle_direct(rq->page_pool, page); + + return act; +} + +static struct sk_buff * +vmxnet3_build_skb(struct vmxnet3_rx_queue *rq, struct page *page, + const struct xdp_buff *xdp) +{ + struct sk_buff *skb; + + skb = build_skb(page_address(page), PAGE_SIZE); + if (unlikely(!skb)) { + page_pool_recycle_direct(rq->page_pool, page); + rq->stats.rx_buf_alloc_failure++; + return NULL; + } + + /* bpf prog might change len and data position. */ + skb_reserve(skb, xdp->data - xdp->data_hard_start); + skb_put(skb, xdp->data_end - xdp->data); + skb_mark_for_recycle(skb); + + return skb; +} + +/* Handle packets from DataRing. */ +int +vmxnet3_process_xdp_small(struct vmxnet3_adapter *adapter, + struct vmxnet3_rx_queue *rq, + void *data, int len, + struct sk_buff **skb_xdp_pass) +{ + struct bpf_prog *xdp_prog; + struct xdp_buff xdp; + struct page *page; + int act; + + page = page_pool_alloc_pages(rq->page_pool, GFP_ATOMIC); + if (unlikely(!page)) { + rq->stats.rx_buf_alloc_failure++; + return XDP_DROP; + } + + xdp_init_buff(&xdp, PAGE_SIZE, &rq->xdp_rxq); + xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, + len, false); + xdp_buff_clear_frags_flag(&xdp); + + /* Must copy the data because it's at dataring. */ + memcpy(xdp.data, data, len); + + xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); + if (!xdp_prog) { + act = XDP_PASS; + goto out_skb; + } + act = vmxnet3_run_xdp(rq, &xdp, xdp_prog); + if (act != XDP_PASS) + return act; + +out_skb: + *skb_xdp_pass = vmxnet3_build_skb(rq, page, &xdp); + if (!*skb_xdp_pass) + return XDP_DROP; + + /* No need to refill. */ + return likely(*skb_xdp_pass) ? act : XDP_DROP; +} + +int +vmxnet3_process_xdp(struct vmxnet3_adapter *adapter, + struct vmxnet3_rx_queue *rq, + struct Vmxnet3_RxCompDesc *rcd, + struct vmxnet3_rx_buf_info *rbi, + struct Vmxnet3_RxDesc *rxd, + struct sk_buff **skb_xdp_pass) +{ + struct bpf_prog *xdp_prog; + dma_addr_t new_dma_addr; + struct xdp_buff xdp; + struct page *page; + void *new_data; + int act; + + page = rbi->page; + dma_sync_single_for_cpu(&adapter->pdev->dev, + page_pool_get_dma_addr(page) + + rq->page_pool->p.offset, rcd->len, + page_pool_get_dma_dir(rq->page_pool)); + + xdp_init_buff(&xdp, rbi->len, &rq->xdp_rxq); + xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, + rcd->len, false); + xdp_buff_clear_frags_flag(&xdp); + + xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); + if (!xdp_prog) { + act = XDP_PASS; + goto out_skb; + } + act = vmxnet3_run_xdp(rq, &xdp, xdp_prog); + + if (act == XDP_PASS) { +out_skb: + *skb_xdp_pass = vmxnet3_build_skb(rq, page, &xdp); + if (!*skb_xdp_pass) + act = XDP_DROP; + } + + new_data = vmxnet3_pp_get_buff(rq->page_pool, &new_dma_addr, + GFP_ATOMIC); + if (!new_data) { + rq->stats.rx_buf_alloc_failure++; + return XDP_DROP; + } + rbi->page = virt_to_page(new_data); + rbi->dma_addr = new_dma_addr; + rxd->addr = cpu_to_le64(rbi->dma_addr); + rxd->len = rbi->len; + + return act; +} diff --git a/drivers/net/vmxnet3/vmxnet3_xdp.h b/drivers/net/vmxnet3/vmxnet3_xdp.h new file mode 100644 index 000000000000..f9d843e060a3 --- /dev/null +++ b/drivers/net/vmxnet3/vmxnet3_xdp.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * Linux driver for VMware's vmxnet3 ethernet NIC. + * Copyright (C) 2008-2023, VMware, Inc. All Rights Reserved. + * Maintained by: pv-drivers@vmware.com + * + */ + +#ifndef _VMXNET3_XDP_H +#define _VMXNET3_XDP_H + +#include +#include +#include + +#include "vmxnet3_int.h" + +#define VMXNET3_XDP_HEADROOM (XDP_PACKET_HEADROOM + NET_IP_ALIGN) +#define VMXNET3_XDP_RX_TAILROOM SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +#define VMXNET3_XDP_RX_OFFSET VMXNET3_XDP_HEADROOM +#define VMXNET3_XDP_MAX_FRSIZE (PAGE_SIZE - VMXNET3_XDP_HEADROOM - \ + VMXNET3_XDP_RX_TAILROOM) +#define VMXNET3_XDP_MAX_MTU (VMXNET3_XDP_MAX_FRSIZE - ETH_HLEN - \ + 2 * VLAN_HLEN - ETH_FCS_LEN) + +int vmxnet3_xdp(struct net_device *netdev, struct netdev_bpf *bpf); +int vmxnet3_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, + u32 flags); +int vmxnet3_process_xdp(struct vmxnet3_adapter *adapter, + struct vmxnet3_rx_queue *rq, + struct Vmxnet3_RxCompDesc *rcd, + struct vmxnet3_rx_buf_info *rbi, + struct Vmxnet3_RxDesc *rxd, + struct sk_buff **skb_xdp_pass); +int vmxnet3_process_xdp_small(struct vmxnet3_adapter *adapter, + struct vmxnet3_rx_queue *rq, + void *data, int len, + struct sk_buff **skb_xdp_pass); +void *vmxnet3_pp_get_buff(struct page_pool *pp, dma_addr_t *dma_addr, + gfp_t gfp_mask); + +static inline bool vmxnet3_xdp_enabled(struct vmxnet3_adapter *adapter) +{ + return !!rcu_access_pointer(adapter->xdp_bpf_prog); +} + +#endif -- cgit From bf98bbe985539ffb61898bd4d855df727b1a80c7 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Thu, 10 Aug 2023 16:56:41 +0800 Subject: net: macsec: Use helper functions to update stats Use the helper functions dev_sw_netstats_rx_add() and dev_sw_netstats_tx_add() to update stats, which helps to provide code readability. Signed-off-by: Li Zetao Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/macsec.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 144ec756c796..ae60817ec5c2 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -518,14 +518,8 @@ static void macsec_count_tx(struct sk_buff *skb, struct macsec_tx_sc *tx_sc, static void count_tx(struct net_device *dev, int ret, int len) { - if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { - struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats); - - u64_stats_update_begin(&stats->syncp); - u64_stats_inc(&stats->tx_packets); - u64_stats_add(&stats->tx_bytes, len); - u64_stats_update_end(&stats->syncp); - } + if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) + dev_sw_netstats_tx_add(dev, 1, len); } static void macsec_encrypt_done(void *data, int err) @@ -827,12 +821,7 @@ static void macsec_finalize_skb(struct sk_buff *skb, u8 icv_len, u8 hdr_len) static void count_rx(struct net_device *dev, int len) { - struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats); - - u64_stats_update_begin(&stats->syncp); - u64_stats_inc(&stats->rx_packets); - u64_stats_add(&stats->rx_bytes, len); - u64_stats_update_end(&stats->syncp); + dev_sw_netstats_rx_add(dev, len); } static void macsec_decrypt_done(void *data, int err) -- cgit From 3c0930b491f8995de974f459648e4aad4ca996ff Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Thu, 10 Aug 2023 16:56:42 +0800 Subject: vxlan: Use helper functions to update stats Use the helper functions dev_sw_netstats_rx_add() and dev_sw_netstats_tx_add() to update stats, which helps to provide code readability. Signed-off-by: Li Zetao Reviewed-by: Ido Schimmel Reviewed-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/vxlan/vxlan_core.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 2bddcdf482a7..e463f59e95c2 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2328,14 +2328,11 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, struct vxlan_dev *dst_vxlan, __be32 vni, bool snoop) { - struct pcpu_sw_netstats *tx_stats, *rx_stats; union vxlan_addr loopback; union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; struct net_device *dev; int len = skb->len; - tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); - rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); skb->pkt_type = PACKET_HOST; skb->encapsulation = 0; skb->dev = dst_vxlan->dev; @@ -2361,17 +2358,11 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, if ((dst_vxlan->cfg.flags & VXLAN_F_LEARN) && snoop) vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni); - u64_stats_update_begin(&tx_stats->syncp); - u64_stats_inc(&tx_stats->tx_packets); - u64_stats_add(&tx_stats->tx_bytes, len); - u64_stats_update_end(&tx_stats->syncp); + dev_sw_netstats_tx_add(src_vxlan->dev, 1, len); vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len); if (__netif_rx(skb) == NET_RX_SUCCESS) { - u64_stats_update_begin(&rx_stats->syncp); - u64_stats_inc(&rx_stats->rx_packets); - u64_stats_add(&rx_stats->rx_bytes, len); - u64_stats_update_end(&rx_stats->syncp); + dev_sw_netstats_rx_add(dst_vxlan->dev, len); vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX, len); } else { -- cgit From 58c1e0bace590715fe22489c06dd4610c1ba50ba Mon Sep 17 00:00:00 2001 From: Furong Xu <0x1207@gmail.com> Date: Fri, 11 Aug 2023 20:51:39 +0800 Subject: net: stmmac: xgmac: show more MAC HW features in debugfs 1. Show TSSTSSEL(Timestamp System Time Source), ADDMACADRSEL(additional MAC addresses), SMASEL(SMA/MDIO Interface), HDSEL(Half-duplex Support) in debugfs. 2. Show exact number of additional MAC address registers for XGMAC2 core. 3. XGMAC2 core does not have different IP checksum offload types, so just show rx_coe instead of rx_coe_type1 or rx_coe_type2. 4. XGMAC2 core does not have rxfifo_over_2048 definition, skip it. Signed-off-by: Furong Xu <0x1207@gmail.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 4 ++++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 6 +++++- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 25 +++++++++++++++++----- 4 files changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index c67171975d5c..1f5293c8cc04 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -438,6 +438,8 @@ struct dma_features { unsigned int tbssel; /* Numbers of Auxiliary Snapshot Inputs */ unsigned int aux_snapshot_n; + /* Timestamp System Time Source */ + unsigned int tssrc; }; /* RX Buffer size must be multiple of 4/8/16 bytes */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index ce67b178c2d5..7f68bef456b7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -123,6 +123,8 @@ #define XGMAC_LPI_TIMER_CTRL 0x000000d4 #define XGMAC_HW_FEATURE0 0x0000011c #define XGMAC_HWFEAT_SAVLANINS BIT(27) +#define XGMAC_HWFEAT_TSSTSSEL GENMASK(26, 25) +#define XGMAC_HWFEAT_ADDMACADRSEL GENMASK(22, 18) #define XGMAC_HWFEAT_RXCOESEL BIT(16) #define XGMAC_HWFEAT_TXCOESEL BIT(14) #define XGMAC_HWFEAT_EEESEL BIT(13) @@ -133,7 +135,9 @@ #define XGMAC_HWFEAT_MMCSEL BIT(8) #define XGMAC_HWFEAT_MGKSEL BIT(7) #define XGMAC_HWFEAT_RWKSEL BIT(6) +#define XGMAC_HWFEAT_SMASEL BIT(5) #define XGMAC_HWFEAT_VLHASH BIT(4) +#define XGMAC_HWFEAT_HDSEL BIT(3) #define XGMAC_HWFEAT_GMIISEL BIT(1) #define XGMAC_HW_FEATURE1 0x00000120 #define XGMAC_HWFEAT_L3L4FNUM GENMASK(30, 27) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index b09395f5edcb..3aacf791efeb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -391,9 +391,11 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, { u32 hw_cap; - /* MAC HW feature 0 */ + /* MAC HW feature 0 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); dma_cap->vlins = (hw_cap & XGMAC_HWFEAT_SAVLANINS) >> 27; + dma_cap->tssrc = (hw_cap & XGMAC_HWFEAT_TSSTSSEL) >> 25; + dma_cap->multi_addr = (hw_cap & XGMAC_HWFEAT_ADDMACADRSEL) >> 18; dma_cap->rx_coe = (hw_cap & XGMAC_HWFEAT_RXCOESEL) >> 16; dma_cap->tx_coe = (hw_cap & XGMAC_HWFEAT_TXCOESEL) >> 14; dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13; @@ -404,7 +406,9 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8; dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7; dma_cap->pmt_remote_wake_up = (hw_cap & XGMAC_HWFEAT_RWKSEL) >> 6; + dma_cap->sma_mdio = (hw_cap & XGMAC_HWFEAT_SMASEL) >> 5; dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; + dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; /* MAC HW feature 1 */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 351eca6109e0..733b5e900817 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6237,6 +6237,12 @@ DEFINE_SHOW_ATTRIBUTE(stmmac_rings_status); static int stmmac_dma_cap_show(struct seq_file *seq, void *v) { + static const char * const dwxgmac_timestamp_source[] = { + "None", + "Internal", + "External", + "Both", + }; struct net_device *dev = seq->private; struct stmmac_priv *priv = netdev_priv(dev); @@ -6257,8 +6263,13 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) (priv->dma_cap.half_duplex) ? "Y" : "N"); seq_printf(seq, "\tHash Filter: %s\n", (priv->dma_cap.hash_filter) ? "Y" : "N"); - seq_printf(seq, "\tMultiple MAC address registers: %s\n", - (priv->dma_cap.multi_addr) ? "Y" : "N"); + if (priv->plat->has_xgmac) + seq_printf(seq, + "\tNumber of Additional MAC address registers: %d\n", + priv->dma_cap.multi_addr); + else + seq_printf(seq, "\tMultiple MAC address registers: %s\n", + (priv->dma_cap.multi_addr) ? "Y" : "N"); seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n", (priv->dma_cap.pcs) ? "Y" : "N"); seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", @@ -6273,12 +6284,16 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) (priv->dma_cap.time_stamp) ? "Y" : "N"); seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n", (priv->dma_cap.atime_stamp) ? "Y" : "N"); + if (priv->plat->has_xgmac) + seq_printf(seq, "\tTimestamp System Time Source: %s\n", + dwxgmac_timestamp_source[priv->dma_cap.tssrc]); seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n", (priv->dma_cap.eee) ? "Y" : "N"); seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); seq_printf(seq, "\tChecksum Offload in TX: %s\n", (priv->dma_cap.tx_coe) ? "Y" : "N"); - if (priv->synopsys_id >= DWMAC_CORE_4_00) { + if (priv->synopsys_id >= DWMAC_CORE_4_00 || + priv->plat->has_xgmac) { seq_printf(seq, "\tIP Checksum Offload in RX: %s\n", (priv->dma_cap.rx_coe) ? "Y" : "N"); } else { @@ -6286,9 +6301,9 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); + seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", + (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); } - seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", - (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); seq_printf(seq, "\tNumber of Additional RX channel: %d\n", priv->dma_cap.number_rx_channel); seq_printf(seq, "\tNumber of Additional TX channel: %d\n", -- cgit From d0d449c747649dd38e7a1fb66a5e29f10284e287 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 11 Aug 2023 17:13:55 +0200 Subject: mlxsw: core_acl_flex_actions: Add IGNORE_ACTION Add the IGNORE_ACTION which is used to ignore basic switching functions such as learning on a per-packet basis. The action will be prepended to the FORWARDING_ACTION in subsequent patches. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../mellanox/mlxsw/core_acl_flex_actions.c | 40 ++++++++++++++++++++++ .../mellanox/mlxsw/core_acl_flex_actions.h | 2 ++ 2 files changed, 42 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c index 9dfe7148199f..faa63ea9b83e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c @@ -1887,6 +1887,46 @@ int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid, } EXPORT_SYMBOL(mlxsw_afa_block_append_fid_set); +/* Ignore Action + * ------------- + * The ignore action is used to ignore basic switching functions such as + * learning on a per-packet basis. + */ + +#define MLXSW_AFA_IGNORE_CODE 0x0F +#define MLXSW_AFA_IGNORE_SIZE 1 + +/* afa_ignore_disable_learning + * Disable learning on ingress. + */ +MLXSW_ITEM32(afa, ignore, disable_learning, 0x00, 29, 1); + +/* afa_ignore_disable_security + * Disable security lookup on ingress. + * Reserved when Spectrum-1. + */ +MLXSW_ITEM32(afa, ignore, disable_security, 0x00, 28, 1); + +static void mlxsw_afa_ignore_pack(char *payload, bool disable_learning, + bool disable_security) +{ + mlxsw_afa_ignore_disable_learning_set(payload, disable_learning); + mlxsw_afa_ignore_disable_security_set(payload, disable_security); +} + +int mlxsw_afa_block_append_ignore(struct mlxsw_afa_block *block, + bool disable_learning, bool disable_security) +{ + char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_IGNORE_CODE, + MLXSW_AFA_IGNORE_SIZE); + + if (IS_ERR(act)) + return PTR_ERR(act); + mlxsw_afa_ignore_pack(act, disable_learning, disable_security); + return 0; +} +EXPORT_SYMBOL(mlxsw_afa_block_append_ignore); + /* MC Routing Action * ----------------- * The Multicast router action. Can be used by RMFT_V2 - Router Multicast diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h index db58037be46e..0ead3a212de8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h @@ -89,6 +89,8 @@ int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block, struct netlink_ext_ack *extack); int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid, struct netlink_ext_ack *extack); +int mlxsw_afa_block_append_ignore(struct mlxsw_afa_block *block, + bool disable_learning, bool disable_security); int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block, u16 expected_irif, u16 min_mtu, bool rmid_valid, u32 kvdl_index); -- cgit From 0433670e136ad879d2d52b3e05ee342a9bb052d8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 11 Aug 2023 17:13:56 +0200 Subject: mlxsw: spectrum_flower: Disable learning and security lookup when redirecting It is possible to add a filter that redirects traffic from the ingress of a bridge port that is locked (i.e., performs security / SMAC lookup) and has learning enabled. For example: # ip link add name br0 type bridge # ip link set dev swp1 master br0 # bridge link set dev swp1 learning on locked on mab on # tc qdisc add dev swp1 clsact # tc filter add dev swp1 ingress pref 1 proto ip flower skip_sw src_ip 192.0.2.1 action mirred egress redirect dev swp2 In the kernel's Rx path, this filter is evaluated before the Rx handler of the bridge, which means that redirected traffic should not be affected by bridge port configuration such as learning. However, the hardware data path is a bit different and the redirect action (FORWARDING_ACTION in hardware) merely attaches a pointer to the packet, which is later used by the L2 lookup stage to understand how to forward the packet. Between both stages - ingress ACL and L2 lookup - learning and security lookup are performed, which means that redirected traffic is affected by bridge port configuration, unlike in the kernel's data path. The learning discrepancy was handled in commit 577fa14d2100 ("mlxsw: spectrum: Do not process learned records with a dummy FID") by simply ignoring learning notifications generated by the redirected traffic. A similar solution is not possible for the security / SMAC lookup since - unlike learning - the CPU is not involved and packets that failed the lookup are dropped by the device. Instead, solve this by prepending the ignore action to the redirect action and use it to instruct the device to disable both learning and the security / SMAC lookup for redirected traffic. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 +++ drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 9 +++++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 10 ++++++++++ 3 files changed, 22 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 8da7bb04fc3a..2fed55bcfd63 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -1050,6 +1050,9 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, u16 fid, struct netlink_ext_ack *extack); +int mlxsw_sp_acl_rulei_act_ignore(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei, + bool disable_learning, bool disable_security); int mlxsw_sp_acl_rulei_act_sample(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, struct mlxsw_sp_flow_block *block, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 186161a3459d..7c59c8a13584 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -775,6 +775,15 @@ int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp, return mlxsw_afa_block_append_fid_set(rulei->act_block, fid, extack); } +int mlxsw_sp_acl_rulei_act_ignore(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei, + bool disable_learning, bool disable_security) +{ + return mlxsw_afa_block_append_ignore(rulei->act_block, + disable_learning, + disable_security); +} + int mlxsw_sp_acl_rulei_act_sample(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, struct mlxsw_sp_flow_block *block, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index af3f57d017ec..9fd1ca079258 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -160,6 +160,16 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, */ rulei->egress_bind_blocker = 1; + /* Ignore learning and security lookup as redirection + * using ingress filters happens before the bridge. + */ + err = mlxsw_sp_acl_rulei_act_ignore(mlxsw_sp, rulei, + true, true); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Cannot append ignore action"); + return err; + } + fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); fid_index = mlxsw_sp_fid_index(fid); err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, -- cgit From 9793a5a9c493a66871de4c6f27e26e9ca90699cc Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 11 Aug 2023 17:13:57 +0200 Subject: mlxsw: spectrum: Stop ignoring learning notifications from redirected traffic As explained in the previous patch, with the ignore action prepended to the redirect action, it is not longer possible for redirected traffic to generate learning notifications. Therefore, remove the workaround that was added in commit 577fa14d2100 ("mlxsw: spectrum: Do not process learned records with a dummy FID") as it is no longer needed. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 - drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 10 ---------- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ------ 3 files changed, 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 2fed55bcfd63..02ca2871b6f9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -1271,7 +1271,6 @@ int mlxsw_sp_setup_tc_block_qevent_mark(struct mlxsw_sp_port *mlxsw_sp_port, struct flow_block_offload *f); /* spectrum_fid.c */ -bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index); struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, u16 fid_index); int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index b6ee2d658b0c..9df098474743 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -137,16 +137,6 @@ static const int *mlxsw_sp_packet_type_sfgc_types[] = { [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, }; -bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index) -{ - enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY; - struct mlxsw_sp_fid_family *fid_family; - - fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type]; - - return fid_family->start_index == fid_index; -} - struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, u16 fid_index) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 3662b9da5489..6c749c148148 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3066,9 +3066,6 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, goto just_remove; } - if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid)) - goto just_remove; - mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid); if (!mlxsw_sp_port_vlan) { netdev_err(mlxsw_sp_port->dev, "Failed to find a matching {Port, VID} following FDB notification\n"); @@ -3136,9 +3133,6 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, goto just_remove; } - if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid)) - goto just_remove; - mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid); if (!mlxsw_sp_port_vlan) { netdev_err(mlxsw_sp_port->dev, "Failed to find a matching {Port, VID} following FDB notification\n"); -- cgit From 83b5f0253b1ef352f4333c4fb2d24eff23045f6b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 11 Aug 2023 13:10:07 +0200 Subject: net: phy: Introduce PSGMII PHY interface mode The PSGMII interface is similar to QSGMII. The main difference is that the PSGMII interface combines five SGMII lines into a single link while in QSGMII only four lines are combined. Similarly to the QSGMII, this interface mode might also needs special handling within the MAC driver. It is commonly used by Qualcomm with their QCA807x PHY series and modern WiSoC-s. Add definitions for the PHY layer to allow to express this type of connection between the MAC and PHY. Signed-off-by: Gabor Juhos Signed-off-by: Robert Marko Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 2 ++ drivers/net/phy/phylink.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index a64186dc53f8..966c93cbe616 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -142,6 +142,8 @@ int phy_interface_num_ports(phy_interface_t interface) case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: return 4; + case PHY_INTERFACE_MODE_PSGMII: + return 5; case PHY_INTERFACE_MODE_MAX: WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); return 0; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 4f1c8bb199e9..160bce608c34 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -210,6 +210,7 @@ static int phylink_interface_max_speed(phy_interface_t interface) case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_PSGMII: case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: case PHY_INTERFACE_MODE_SGMII: @@ -475,6 +476,7 @@ unsigned long phylink_get_capabilities(phy_interface_t interface, case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_PSGMII: case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: case PHY_INTERFACE_MODE_SGMII: @@ -868,6 +870,7 @@ static int phylink_parse_mode(struct phylink *pl, switch (pl->link_config.interface) { case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_PSGMII: case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: case PHY_INTERFACE_MODE_RGMII: -- cgit From 3178308ad4ca38955cad684d235153d4939f1fcd Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 2 May 2023 16:31:40 -0700 Subject: net/mlx5e: Make tx_port_ts logic resilient to out-of-order CQEs Use a map structure for associating CQEs containing port timestamping information with the appropriate skb. Track order of WQEs submitted using a FIFO. Check if the corresponding port timestamping CQEs from the lookup values in the FIFO are considered dropped due to time elapsed. Return the lookup value to a freelist after consuming the skb. Reuse the freed lookup in future WQE submission iterations. The map structure uses an integer identifier for the key and returns an skb corresponding to that identifier. Embed the integer identifier in the WQE submitted to the WQ for the transmit path when the SQ is a PTP (port timestamping) SQ. The embedded identifier can then be queried using a field in the CQE of the corresponding port timestamping CQ. In the port timestamping napi_poll context, the identifier is queried from the CQE polled from CQ and used to lookup the corresponding skb from the WQE submit path. The skb reference is removed from map and then embedded with the port HW timestamp information from the CQE and eventually consumed. The metadata freelist FIFO is an array containing integer identifiers that can be pushed and popped in the FIFO. The purpose of this structure is bookkeeping what identifier values can safely be used in a subsequent WQE submission and should not contain identifiers that have still not been reaped by processing a corresponding CQE completion on the port timestamping CQ. The ts_cqe_pending_list structure is a combination of an array and linked list. The array is pre-populated with the nodes that will be added and removed from the head of the linked list. Each node contains the unique identifier value associated with the values submitted in the WQEs and retrieved in the port timestamping CQEs. When a WQE is submitted, the node in the array corresponding to the identifier popped from the metadata freelist is added to the end of the CQE pending list and is marked as "in-use". The node is removed from the linked list under two conditions. The first condition is that the corresponding port timestamping CQE is polled in the PTP napi_poll context. The second condition is that more than a second has elapsed since the DMA timestamp value corresponding to the WQE submission. When the first condition occurs, the "in-use" bit in the linked list node is cleared, and the resources corresponding to the WQE submission are then released. The second condition, however, indicates that the port timestamping CQE will likely never be delivered. It's not impossible for the device to post a CQE after an infinite amount of time though highly improbable. In order to be resilient to this improbable case, resources related to the corresponding WQE submission are still kept, the identifier value is not returned to the freelist, and the "in-use" bit is cleared on the node to indicate that it's no longer part of the linked list of "likely to be delivered" port timestamping CQE identifiers. A count for the number of port timestamping CQEs considered highly likely to never be delivered by the device is maintained. This count gets decremented in the unlikely event a port timestamping CQE considered unlikely to ever be delivered is polled in the PTP napi_poll context. Signed-off-by: Rahul Rameshbabu Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 215 +++++++++++++++------ drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 57 +++++- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | 4 +- drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 4 +- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 28 ++- 6 files changed, 230 insertions(+), 81 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index b0b429a0321e..8680d21f3e7b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -5,6 +5,8 @@ #include "en/txrx.h" #include "en/params.h" #include "en/fs_tt_redirect.h" +#include +#include struct mlx5e_ptp_fs { struct mlx5_flow_handle *l2_rule; @@ -19,6 +21,48 @@ struct mlx5e_ptp_params { struct mlx5e_rq_param rq_param; }; +struct mlx5e_ptp_port_ts_cqe_tracker { + u8 metadata_id; + bool inuse : 1; + struct list_head entry; +}; + +struct mlx5e_ptp_port_ts_cqe_list { + struct mlx5e_ptp_port_ts_cqe_tracker *nodes; + struct list_head tracker_list_head; + /* Sync list operations in xmit and napi_poll contexts */ + spinlock_t tracker_list_lock; +}; + +static inline void +mlx5e_ptp_port_ts_cqe_list_add(struct mlx5e_ptp_port_ts_cqe_list *list, u8 metadata) +{ + struct mlx5e_ptp_port_ts_cqe_tracker *tracker = &list->nodes[metadata]; + + WARN_ON_ONCE(tracker->inuse); + tracker->inuse = true; + spin_lock(&list->tracker_list_lock); + list_add_tail(&tracker->entry, &list->tracker_list_head); + spin_unlock(&list->tracker_list_lock); +} + +static void +mlx5e_ptp_port_ts_cqe_list_remove(struct mlx5e_ptp_port_ts_cqe_list *list, u8 metadata) +{ + struct mlx5e_ptp_port_ts_cqe_tracker *tracker = &list->nodes[metadata]; + + WARN_ON_ONCE(!tracker->inuse); + tracker->inuse = false; + spin_lock(&list->tracker_list_lock); + list_del(&tracker->entry); + spin_unlock(&list->tracker_list_lock); +} + +void mlx5e_ptpsq_track_metadata(struct mlx5e_ptpsq *ptpsq, u8 metadata) +{ + mlx5e_ptp_port_ts_cqe_list_add(ptpsq->ts_cqe_pending_list, metadata); +} + struct mlx5e_skb_cb_hwtstamp { ktime_t cqe_hwtstamp; ktime_t port_hwtstamp; @@ -79,75 +123,88 @@ void mlx5e_skb_cb_hwtstamp_handler(struct sk_buff *skb, int hwtstamp_type, memset(skb->cb, 0, sizeof(struct mlx5e_skb_cb_hwtstamp)); } -#define PTP_WQE_CTR2IDX(val) ((val) & ptpsq->ts_cqe_ctr_mask) - -static bool mlx5e_ptp_ts_cqe_drop(struct mlx5e_ptpsq *ptpsq, u16 skb_ci, u16 skb_id) +static struct sk_buff * +mlx5e_ptp_metadata_map_lookup(struct mlx5e_ptp_metadata_map *map, u16 metadata) { - return (ptpsq->ts_cqe_ctr_mask && (skb_ci != skb_id)); + return map->data[metadata]; } -static bool mlx5e_ptp_ts_cqe_ooo(struct mlx5e_ptpsq *ptpsq, u16 skb_id) +static struct sk_buff * +mlx5e_ptp_metadata_map_remove(struct mlx5e_ptp_metadata_map *map, u16 metadata) { - u16 skb_ci = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_cc); - u16 skb_pi = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_pc); + struct sk_buff *skb; - if (PTP_WQE_CTR2IDX(skb_id - skb_ci) >= PTP_WQE_CTR2IDX(skb_pi - skb_ci)) - return true; + skb = map->data[metadata]; + map->data[metadata] = NULL; - return false; + return skb; } -static void mlx5e_ptp_skb_fifo_ts_cqe_resync(struct mlx5e_ptpsq *ptpsq, u16 skb_ci, - u16 skb_id, int budget) +static void mlx5e_ptpsq_mark_ts_cqes_undelivered(struct mlx5e_ptpsq *ptpsq, + ktime_t port_tstamp) { - struct skb_shared_hwtstamps hwts = {}; - struct sk_buff *skb; + struct mlx5e_ptp_port_ts_cqe_list *cqe_list = ptpsq->ts_cqe_pending_list; + ktime_t timeout = ns_to_ktime(MLX5E_PTP_TS_CQE_UNDELIVERED_TIMEOUT); + struct mlx5e_ptp_metadata_map *metadata_map = &ptpsq->metadata_map; + struct mlx5e_ptp_port_ts_cqe_tracker *pos, *n; + + spin_lock(&cqe_list->tracker_list_lock); + list_for_each_entry_safe(pos, n, &cqe_list->tracker_list_head, entry) { + struct sk_buff *skb = + mlx5e_ptp_metadata_map_lookup(metadata_map, pos->metadata_id); + ktime_t dma_tstamp = mlx5e_skb_cb_get_hwts(skb)->cqe_hwtstamp; - ptpsq->cq_stats->resync_event++; + if (!dma_tstamp || + ktime_after(ktime_add(dma_tstamp, timeout), port_tstamp)) + break; - while (skb_ci != skb_id) { - skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); - hwts.hwtstamp = mlx5e_skb_cb_get_hwts(skb)->cqe_hwtstamp; - skb_tstamp_tx(skb, &hwts); - ptpsq->cq_stats->resync_cqe++; - napi_consume_skb(skb, budget); - skb_ci = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_cc); + metadata_map->undelivered_counter++; + WARN_ON_ONCE(!pos->inuse); + pos->inuse = false; + list_del(&pos->entry); } + spin_unlock(&cqe_list->tracker_list_lock); } +#define PTP_WQE_CTR2IDX(val) ((val) & ptpsq->ts_cqe_ctr_mask) + static void mlx5e_ptp_handle_ts_cqe(struct mlx5e_ptpsq *ptpsq, struct mlx5_cqe64 *cqe, int budget) { - u16 skb_id = PTP_WQE_CTR2IDX(be16_to_cpu(cqe->wqe_counter)); - u16 skb_ci = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_cc); + struct mlx5e_ptp_port_ts_cqe_list *pending_cqe_list = ptpsq->ts_cqe_pending_list; + u8 metadata_id = PTP_WQE_CTR2IDX(be16_to_cpu(cqe->wqe_counter)); + bool is_err_cqe = !!MLX5E_RX_ERR_CQE(cqe); struct mlx5e_txqsq *sq = &ptpsq->txqsq; struct sk_buff *skb; ktime_t hwtstamp; - if (unlikely(MLX5E_RX_ERR_CQE(cqe))) { - skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); - ptpsq->cq_stats->err_cqe++; - goto out; + if (likely(pending_cqe_list->nodes[metadata_id].inuse)) { + mlx5e_ptp_port_ts_cqe_list_remove(pending_cqe_list, metadata_id); + } else { + /* Reclaim space in the unlikely event CQE was delivered after + * marking it late. + */ + ptpsq->metadata_map.undelivered_counter--; + ptpsq->cq_stats->late_cqe++; } - if (mlx5e_ptp_ts_cqe_drop(ptpsq, skb_ci, skb_id)) { - if (mlx5e_ptp_ts_cqe_ooo(ptpsq, skb_id)) { - /* already handled by a previous resync */ - ptpsq->cq_stats->ooo_cqe_drop++; - return; - } - mlx5e_ptp_skb_fifo_ts_cqe_resync(ptpsq, skb_ci, skb_id, budget); + skb = mlx5e_ptp_metadata_map_remove(&ptpsq->metadata_map, metadata_id); + + if (unlikely(is_err_cqe)) { + ptpsq->cq_stats->err_cqe++; + goto out; } - skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); hwtstamp = mlx5e_cqe_ts_to_ns(sq->ptp_cyc2time, sq->clock, get_cqe_ts(cqe)); mlx5e_skb_cb_hwtstamp_handler(skb, MLX5E_SKB_CB_PORT_HWTSTAMP, hwtstamp, ptpsq->cq_stats); ptpsq->cq_stats->cqe++; + mlx5e_ptpsq_mark_ts_cqes_undelivered(ptpsq, hwtstamp); out: napi_consume_skb(skb, budget); + mlx5e_ptp_metadata_fifo_push(&ptpsq->metadata_freelist, metadata_id); } static bool mlx5e_ptp_poll_ts_cq(struct mlx5e_cq *cq, int budget) @@ -291,36 +348,78 @@ static void mlx5e_ptp_destroy_sq(struct mlx5_core_dev *mdev, u32 sqn) static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptpsq *ptpsq, int numa) { - int wq_sz = mlx5_wq_cyc_get_size(&ptpsq->txqsq.wq); - struct mlx5_core_dev *mdev = ptpsq->txqsq.mdev; + struct mlx5e_ptp_metadata_fifo *metadata_freelist = &ptpsq->metadata_freelist; + struct mlx5e_ptp_metadata_map *metadata_map = &ptpsq->metadata_map; + struct mlx5e_ptp_port_ts_cqe_list *cqe_list; + int db_sz; + int md; - ptpsq->skb_fifo.fifo = kvzalloc_node(array_size(wq_sz, sizeof(*ptpsq->skb_fifo.fifo)), - GFP_KERNEL, numa); - if (!ptpsq->skb_fifo.fifo) + cqe_list = kvzalloc_node(sizeof(*ptpsq->ts_cqe_pending_list), GFP_KERNEL, numa); + if (!cqe_list) return -ENOMEM; + ptpsq->ts_cqe_pending_list = cqe_list; + + db_sz = min_t(u32, mlx5_wq_cyc_get_size(&ptpsq->txqsq.wq), + 1 << MLX5_CAP_GEN_2(ptpsq->txqsq.mdev, + ts_cqe_metadata_size2wqe_counter)); + ptpsq->ts_cqe_ctr_mask = db_sz - 1; + + cqe_list->nodes = kvzalloc_node(array_size(db_sz, sizeof(*cqe_list->nodes)), + GFP_KERNEL, numa); + if (!cqe_list->nodes) + goto free_cqe_list; + INIT_LIST_HEAD(&cqe_list->tracker_list_head); + spin_lock_init(&cqe_list->tracker_list_lock); + + metadata_freelist->data = + kvzalloc_node(array_size(db_sz, sizeof(*metadata_freelist->data)), + GFP_KERNEL, numa); + if (!metadata_freelist->data) + goto free_cqe_list_nodes; + metadata_freelist->mask = ptpsq->ts_cqe_ctr_mask; + + for (md = 0; md < db_sz; ++md) { + cqe_list->nodes[md].metadata_id = md; + metadata_freelist->data[md] = md; + } + metadata_freelist->pc = db_sz; + + metadata_map->data = + kvzalloc_node(array_size(db_sz, sizeof(*metadata_map->data)), + GFP_KERNEL, numa); + if (!metadata_map->data) + goto free_metadata_freelist; + metadata_map->capacity = db_sz; - ptpsq->skb_fifo.pc = &ptpsq->skb_fifo_pc; - ptpsq->skb_fifo.cc = &ptpsq->skb_fifo_cc; - ptpsq->skb_fifo.mask = wq_sz - 1; - if (MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter)) - ptpsq->ts_cqe_ctr_mask = - (1 << MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter)) - 1; return 0; + +free_metadata_freelist: + kvfree(metadata_freelist->data); +free_cqe_list_nodes: + kvfree(cqe_list->nodes); +free_cqe_list: + kvfree(cqe_list); + return -ENOMEM; } -static void mlx5e_ptp_drain_skb_fifo(struct mlx5e_skb_fifo *skb_fifo) +static void mlx5e_ptp_drain_metadata_map(struct mlx5e_ptp_metadata_map *map) { - while (*skb_fifo->pc != *skb_fifo->cc) { - struct sk_buff *skb = mlx5e_skb_fifo_pop(skb_fifo); + int idx; + + for (idx = 0; idx < map->capacity; ++idx) { + struct sk_buff *skb = map->data[idx]; dev_kfree_skb_any(skb); } } -static void mlx5e_ptp_free_traffic_db(struct mlx5e_skb_fifo *skb_fifo) +static void mlx5e_ptp_free_traffic_db(struct mlx5e_ptpsq *ptpsq) { - mlx5e_ptp_drain_skb_fifo(skb_fifo); - kvfree(skb_fifo->fifo); + mlx5e_ptp_drain_metadata_map(&ptpsq->metadata_map); + kvfree(ptpsq->metadata_map.data); + kvfree(ptpsq->metadata_freelist.data); + kvfree(ptpsq->ts_cqe_pending_list->nodes); + kvfree(ptpsq->ts_cqe_pending_list); } static int mlx5e_ptp_open_txqsq(struct mlx5e_ptp *c, u32 tisn, @@ -348,8 +447,7 @@ static int mlx5e_ptp_open_txqsq(struct mlx5e_ptp *c, u32 tisn, if (err) goto err_free_txqsq; - err = mlx5e_ptp_alloc_traffic_db(ptpsq, - dev_to_node(mlx5_core_dma_dev(c->mdev))); + err = mlx5e_ptp_alloc_traffic_db(ptpsq, dev_to_node(mlx5_core_dma_dev(c->mdev))); if (err) goto err_free_txqsq; @@ -366,7 +464,7 @@ static void mlx5e_ptp_close_txqsq(struct mlx5e_ptpsq *ptpsq) struct mlx5e_txqsq *sq = &ptpsq->txqsq; struct mlx5_core_dev *mdev = sq->mdev; - mlx5e_ptp_free_traffic_db(&ptpsq->skb_fifo); + mlx5e_ptp_free_traffic_db(ptpsq); cancel_work_sync(&sq->recover_work); mlx5e_ptp_destroy_sq(mdev, sq->sqn); mlx5e_free_txqsq_descs(sq); @@ -534,7 +632,10 @@ static void mlx5e_ptp_build_params(struct mlx5e_ptp *c, /* SQ */ if (test_bit(MLX5E_PTP_STATE_TX, c->state)) { - params->log_sq_size = orig->log_sq_size; + params->log_sq_size = + min(MLX5_CAP_GEN_2(c->mdev, ts_cqe_metadata_size2wqe_counter), + MLX5E_PTP_MAX_LOG_SQ_SIZE); + params->log_sq_size = min(params->log_sq_size, orig->log_sq_size); mlx5e_ptp_build_sq_param(c->mdev, params, &cparams->txq_sq_param); } /* RQ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index cc7efde88ac3..7c5597d4589d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -7,18 +7,36 @@ #include "en.h" #include "en_stats.h" #include "en/txrx.h" +#include #include +#include #define MLX5E_PTP_CHANNEL_IX 0 +#define MLX5E_PTP_MAX_LOG_SQ_SIZE (8U) +#define MLX5E_PTP_TS_CQE_UNDELIVERED_TIMEOUT (1 * NSEC_PER_SEC) + +struct mlx5e_ptp_metadata_fifo { + u8 cc; + u8 pc; + u8 mask; + u8 *data; +}; + +struct mlx5e_ptp_metadata_map { + u16 undelivered_counter; + u16 capacity; + struct sk_buff **data; +}; struct mlx5e_ptpsq { struct mlx5e_txqsq txqsq; struct mlx5e_cq ts_cq; - u16 skb_fifo_cc; - u16 skb_fifo_pc; - struct mlx5e_skb_fifo skb_fifo; struct mlx5e_ptp_cq_stats *cq_stats; u16 ts_cqe_ctr_mask; + + struct mlx5e_ptp_port_ts_cqe_list *ts_cqe_pending_list; + struct mlx5e_ptp_metadata_fifo metadata_freelist; + struct mlx5e_ptp_metadata_map metadata_map; }; enum { @@ -69,12 +87,35 @@ static inline bool mlx5e_use_ptpsq(struct sk_buff *skb) fk.ports.dst == htons(PTP_EV_PORT)); } -static inline bool mlx5e_ptpsq_fifo_has_room(struct mlx5e_txqsq *sq) +static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo *fifo, u8 metadata) { - if (!sq->ptpsq) - return true; + fifo->data[fifo->mask & fifo->pc++] = metadata; +} + +static inline u8 +mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo) +{ + return fifo->data[fifo->mask & fifo->cc++]; +} - return mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo); +static inline void +mlx5e_ptp_metadata_map_put(struct mlx5e_ptp_metadata_map *map, + struct sk_buff *skb, u8 metadata) +{ + WARN_ON_ONCE(map->data[metadata]); + map->data[metadata] = skb; +} + +static inline bool mlx5e_ptpsq_metadata_freelist_empty(struct mlx5e_ptpsq *ptpsq) +{ + struct mlx5e_ptp_metadata_fifo *freelist; + + if (likely(!ptpsq)) + return false; + + freelist = &ptpsq->metadata_freelist; + + return freelist->pc == freelist->cc; } int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, @@ -89,6 +130,8 @@ void mlx5e_ptp_free_rx_fs(struct mlx5e_flow_steering *fs, const struct mlx5e_profile *profile); int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set); +void mlx5e_ptpsq_track_metadata(struct mlx5e_ptpsq *ptpsq, u8 metadata); + enum { MLX5E_SKB_CB_CQE_HWTSTAMP = BIT(0), MLX5E_SKB_CB_PORT_HWTSTAMP = BIT(1), diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 04195a673a6b..dff02434ff45 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2061,7 +2061,8 @@ static int set_pflag_tx_port_ts(struct net_device *netdev, bool enable) struct mlx5e_params new_params; int err; - if (!MLX5_CAP_GEN(mdev, ts_cqe_to_dest_cqn)) + if (!MLX5_CAP_GEN(mdev, ts_cqe_to_dest_cqn) || + !MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter)) return -EOPNOTSUPP; /* Don't allow changing the PTP state if HTB offload is active, because diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 07b84d668fcc..52141729444e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -2142,9 +2142,7 @@ static const struct counter_desc ptp_cq_stats_desc[] = { { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, err_cqe) }, { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort) }, { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort_abs_diff_ns) }, - { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, resync_cqe) }, - { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, resync_event) }, - { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, ooo_cqe_drop) }, + { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, late_cqe) }, }; static const struct counter_desc ptp_rq_stats_desc[] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 1ff8a06027dc..409e9a47e433 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -449,9 +449,7 @@ struct mlx5e_ptp_cq_stats { u64 err_cqe; u64 abort; u64 abort_abs_diff_ns; - u64 resync_cqe; - u64 resync_event; - u64 ooo_cqe_drop; + u64 late_cqe; }; struct mlx5e_rep_stats { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index c7eb6b238c2b..d41435c22ce5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -372,7 +372,7 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, const struct mlx5e_tx_attr *attr, const struct mlx5e_tx_wqe_attr *wqe_attr, u8 num_dma, struct mlx5e_tx_wqe_info *wi, struct mlx5_wqe_ctrl_seg *cseg, - bool xmit_more) + struct mlx5_wqe_eth_seg *eseg, bool xmit_more) { struct mlx5_wq_cyc *wq = &sq->wq; bool send_doorbell; @@ -394,11 +394,16 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, mlx5e_tx_check_stop(sq); - if (unlikely(sq->ptpsq)) { + if (unlikely(sq->ptpsq && + (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) { + u8 metadata_index = be32_to_cpu(eseg->flow_table_metadata); + mlx5e_skb_cb_hwtstamp_init(skb); - mlx5e_skb_fifo_push(&sq->ptpsq->skb_fifo, skb); + mlx5e_ptpsq_track_metadata(sq->ptpsq, metadata_index); + mlx5e_ptp_metadata_map_put(&sq->ptpsq->metadata_map, skb, + metadata_index); if (!netif_tx_queue_stopped(sq->txq) && - !mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo)) { + mlx5e_ptpsq_metadata_freelist_empty(sq->ptpsq)) { netif_tx_stop_queue(sq->txq); sq->stats->stopped++; } @@ -483,13 +488,16 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, if (unlikely(num_dma < 0)) goto err_drop; - mlx5e_txwqe_complete(sq, skb, attr, wqe_attr, num_dma, wi, cseg, xmit_more); + mlx5e_txwqe_complete(sq, skb, attr, wqe_attr, num_dma, wi, cseg, eseg, xmit_more); return; err_drop: stats->dropped++; dev_kfree_skb_any(skb); + if (unlikely(sq->ptpsq && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) + mlx5e_ptp_metadata_fifo_push(&sq->ptpsq->metadata_freelist, + be32_to_cpu(eseg->flow_table_metadata)); mlx5e_tx_flush(sq); } @@ -645,9 +653,9 @@ void mlx5e_tx_mpwqe_ensure_complete(struct mlx5e_txqsq *sq) static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg) { - if (ptpsq->ts_cqe_ctr_mask && unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) - eseg->flow_table_metadata = cpu_to_be32(ptpsq->skb_fifo_pc & - ptpsq->ts_cqe_ctr_mask); + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) + eseg->flow_table_metadata = + cpu_to_be32(mlx5e_ptp_metadata_fifo_pop(&ptpsq->metadata_freelist)); } static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq, @@ -766,7 +774,7 @@ void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq) { if (netif_tx_queue_stopped(sq->txq) && mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) && - mlx5e_ptpsq_fifo_has_room(sq) && + !mlx5e_ptpsq_metadata_freelist_empty(sq->ptpsq) && !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) { netif_tx_wake_queue(sq->txq); sq->stats->wake++; @@ -1031,7 +1039,7 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, if (unlikely(num_dma < 0)) goto err_drop; - mlx5e_txwqe_complete(sq, skb, &attr, &wqe_attr, num_dma, wi, cseg, xmit_more); + mlx5e_txwqe_complete(sq, skb, &attr, &wqe_attr, num_dma, wi, cseg, eseg, xmit_more); return; -- cgit From 53b836a44db4259b94ffcfff321fb3d63f976b76 Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 8 Aug 2023 21:10:21 -0700 Subject: net/mlx5e: Add recovery flow for tx devlink health reporter for unhealthy PTP SQ A new check for the tx devlink health reporter is introduced for determining when the PTP port timestamping SQ is considered unhealthy. If there are enough CQEs considered never to be delivered, the space that can be utilized on the SQ decreases significantly, impacting performance and usability of the SQ. The health reporter is triggered when the number of likely never delivered port timestamping CQEs that utilize the space of the PTP SQ is greater than 93.75% of the total capacity of the SQ. A devlink health reporter recover method is also provided for this specific TX error context that restarts the PTP SQ. Signed-off-by: Rahul Rameshbabu Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/health.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 22 ++++++++ drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 2 + .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 65 ++++++++++++++++++++++ 4 files changed, 90 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h index 0107e4e73bb0..415840c3ef84 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h @@ -18,6 +18,7 @@ void mlx5e_reporter_tx_create(struct mlx5e_priv *priv); void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv); void mlx5e_reporter_tx_err_cqe(struct mlx5e_txqsq *sq); int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq); +void mlx5e_reporter_tx_ptpsq_unhealthy(struct mlx5e_ptpsq *ptpsq); int mlx5e_health_cq_diag_fmsg(struct mlx5e_cq *cq, struct devlink_fmsg *fmsg); int mlx5e_health_cq_common_diag_fmsg(struct mlx5e_cq *cq, struct devlink_fmsg *fmsg); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index 8680d21f3e7b..bb11e644d24f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -2,6 +2,7 @@ // Copyright (c) 2020 Mellanox Technologies #include "en/ptp.h" +#include "en/health.h" #include "en/txrx.h" #include "en/params.h" #include "en/fs_tt_redirect.h" @@ -140,6 +141,12 @@ mlx5e_ptp_metadata_map_remove(struct mlx5e_ptp_metadata_map *map, u16 metadata) return skb; } +static bool mlx5e_ptp_metadata_map_unhealthy(struct mlx5e_ptp_metadata_map *map) +{ + /* Considered beginning unhealthy state if size * 15 / 2^4 cannot be reclaimed. */ + return map->undelivered_counter > (map->capacity >> 4) * 15; +} + static void mlx5e_ptpsq_mark_ts_cqes_undelivered(struct mlx5e_ptpsq *ptpsq, ktime_t port_tstamp) { @@ -205,6 +212,9 @@ static void mlx5e_ptp_handle_ts_cqe(struct mlx5e_ptpsq *ptpsq, out: napi_consume_skb(skb, budget); mlx5e_ptp_metadata_fifo_push(&ptpsq->metadata_freelist, metadata_id); + if (unlikely(mlx5e_ptp_metadata_map_unhealthy(&ptpsq->metadata_map)) && + !test_and_set_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) + queue_work(ptpsq->txqsq.priv->wq, &ptpsq->report_unhealthy_work); } static bool mlx5e_ptp_poll_ts_cq(struct mlx5e_cq *cq, int budget) @@ -422,6 +432,14 @@ static void mlx5e_ptp_free_traffic_db(struct mlx5e_ptpsq *ptpsq) kvfree(ptpsq->ts_cqe_pending_list); } +static void mlx5e_ptpsq_unhealthy_work(struct work_struct *work) +{ + struct mlx5e_ptpsq *ptpsq = + container_of(work, struct mlx5e_ptpsq, report_unhealthy_work); + + mlx5e_reporter_tx_ptpsq_unhealthy(ptpsq); +} + static int mlx5e_ptp_open_txqsq(struct mlx5e_ptp *c, u32 tisn, int txq_ix, struct mlx5e_ptp_params *cparams, int tc, struct mlx5e_ptpsq *ptpsq) @@ -451,6 +469,8 @@ static int mlx5e_ptp_open_txqsq(struct mlx5e_ptp *c, u32 tisn, if (err) goto err_free_txqsq; + INIT_WORK(&ptpsq->report_unhealthy_work, mlx5e_ptpsq_unhealthy_work); + return 0; err_free_txqsq: @@ -464,6 +484,8 @@ static void mlx5e_ptp_close_txqsq(struct mlx5e_ptpsq *ptpsq) struct mlx5e_txqsq *sq = &ptpsq->txqsq; struct mlx5_core_dev *mdev = sq->mdev; + if (current_work() != &ptpsq->report_unhealthy_work) + cancel_work_sync(&ptpsq->report_unhealthy_work); mlx5e_ptp_free_traffic_db(ptpsq); cancel_work_sync(&sq->recover_work); mlx5e_ptp_destroy_sq(mdev, sq->sqn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index 7c5597d4589d..7b700d0f956a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -10,6 +10,7 @@ #include #include #include +#include #define MLX5E_PTP_CHANNEL_IX 0 #define MLX5E_PTP_MAX_LOG_SQ_SIZE (8U) @@ -34,6 +35,7 @@ struct mlx5e_ptpsq { struct mlx5e_ptp_cq_stats *cq_stats; u16 ts_cqe_ctr_mask; + struct work_struct report_unhealthy_work; struct mlx5e_ptp_port_ts_cqe_list *ts_cqe_pending_list; struct mlx5e_ptp_metadata_fifo metadata_freelist; struct mlx5e_ptp_metadata_map metadata_map; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index b35ff289af49..ff8242f67c54 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -164,6 +164,43 @@ static int mlx5e_tx_reporter_timeout_recover(void *ctx) return err; } +static int mlx5e_tx_reporter_ptpsq_unhealthy_recover(void *ctx) +{ + struct mlx5e_ptpsq *ptpsq = ctx; + struct mlx5e_channels *chs; + struct net_device *netdev; + struct mlx5e_priv *priv; + int carrier_ok; + int err; + + if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &ptpsq->txqsq.state)) + return 0; + + priv = ptpsq->txqsq.priv; + + mutex_lock(&priv->state_lock); + chs = &priv->channels; + netdev = priv->netdev; + + carrier_ok = netif_carrier_ok(netdev); + netif_carrier_off(netdev); + + mlx5e_deactivate_priv_channels(priv); + + mlx5e_ptp_close(chs->ptp); + err = mlx5e_ptp_open(priv, &chs->params, chs->c[0]->lag_port, &chs->ptp); + + mlx5e_activate_priv_channels(priv); + + /* return carrier back if needed */ + if (carrier_ok) + netif_carrier_on(netdev); + + mutex_unlock(&priv->state_lock); + + return err; +} + /* state lock cannot be grabbed within this function. * It can cause a dead lock or a read-after-free. */ @@ -516,6 +553,15 @@ static int mlx5e_tx_reporter_timeout_dump(struct mlx5e_priv *priv, struct devlin return mlx5e_tx_reporter_dump_sq(priv, fmsg, to_ctx->sq); } +static int mlx5e_tx_reporter_ptpsq_unhealthy_dump(struct mlx5e_priv *priv, + struct devlink_fmsg *fmsg, + void *ctx) +{ + struct mlx5e_ptpsq *ptpsq = ctx; + + return mlx5e_tx_reporter_dump_sq(priv, fmsg, &ptpsq->txqsq); +} + static int mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg) { @@ -621,6 +667,25 @@ int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq) return to_ctx.status; } +void mlx5e_reporter_tx_ptpsq_unhealthy(struct mlx5e_ptpsq *ptpsq) +{ + struct mlx5e_ptp_metadata_map *map = &ptpsq->metadata_map; + char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN]; + struct mlx5e_txqsq *txqsq = &ptpsq->txqsq; + struct mlx5e_cq *ts_cq = &ptpsq->ts_cq; + struct mlx5e_priv *priv = txqsq->priv; + struct mlx5e_err_ctx err_ctx = {}; + + err_ctx.ctx = ptpsq; + err_ctx.recover = mlx5e_tx_reporter_ptpsq_unhealthy_recover; + err_ctx.dump = mlx5e_tx_reporter_ptpsq_unhealthy_dump; + snprintf(err_str, sizeof(err_str), + "Unhealthy TX port TS queue: %d, SQ: 0x%x, CQ: 0x%x, Undelivered CQEs: %u Map Capacity: %u", + txqsq->ch_ix, txqsq->sqn, ts_cq->mcq.cqn, map->undelivered_counter, map->capacity); + + mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx); +} + static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { .name = "tx", .recover = mlx5e_tx_reporter_recover, -- cgit From 6486c0f44ed8e91073c1b08e83075e3832618ae5 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Thu, 13 Jul 2023 14:54:57 +0300 Subject: net/mlx5: Expose max possible SFs via devlink resource Introduce devlink resource for exposing max possible SFs on mlx5 devices. For example: $ devlink resource show pci/0000:00:0b.0 pci/0000:00:0b.0: name max_local_SFs size 5 unit entry dpipe_tables none name max_external_SFs size 0 unit entry dpipe_tables none Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Reviewed-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/devlink.h | 8 ++++ .../net/ethernet/mellanox/mlx5/core/sf/hw_table.c | 44 ++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.h b/drivers/net/ethernet/mellanox/mlx5/core/devlink.h index defba5bd91d9..961f75da6227 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.h @@ -6,6 +6,14 @@ #include +enum mlx5_devlink_resource_id { + MLX5_DL_RES_MAX_LOCAL_SFS = 1, + MLX5_DL_RES_MAX_EXTERNAL_SFS, + + __MLX5_ID_RES_MAX, + MLX5_ID_RES_MAX = __MLX5_ID_RES_MAX - 1, +}; + enum mlx5_devlink_param_id { MLX5_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c index 17aa348989cb..c4daeaaafead 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c @@ -9,6 +9,7 @@ #include "mlx5_core.h" #include "eswitch.h" #include "diag/sf_tracepoint.h" +#include "devlink.h" struct mlx5_sf_hw { u32 usr_sfnum; @@ -243,6 +244,32 @@ static void mlx5_sf_hw_table_hwc_cleanup(struct mlx5_sf_hwc_table *hwc) kfree(hwc->sfs); } +static void mlx5_sf_hw_table_res_unregister(struct mlx5_core_dev *dev) +{ + devl_resources_unregister(priv_to_devlink(dev)); +} + +static int mlx5_sf_hw_table_res_register(struct mlx5_core_dev *dev, u16 max_fn, + u16 max_ext_fn) +{ + struct devlink_resource_size_params size_params; + struct devlink *devlink = priv_to_devlink(dev); + int err; + + devlink_resource_size_params_init(&size_params, max_fn, max_fn, 1, + DEVLINK_RESOURCE_UNIT_ENTRY); + err = devl_resource_register(devlink, "max_local_SFs", max_fn, MLX5_DL_RES_MAX_LOCAL_SFS, + DEVLINK_RESOURCE_ID_PARENT_TOP, &size_params); + if (err) + return err; + + devlink_resource_size_params_init(&size_params, max_ext_fn, max_ext_fn, 1, + DEVLINK_RESOURCE_UNIT_ENTRY); + return devl_resource_register(devlink, "max_external_SFs", max_ext_fn, + MLX5_DL_RES_MAX_EXTERNAL_SFS, DEVLINK_RESOURCE_ID_PARENT_TOP, + &size_params); +} + int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev) { struct mlx5_sf_hw_table *table; @@ -262,12 +289,17 @@ int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev) if (err) return err; + if (mlx5_sf_hw_table_res_register(dev, max_fn, max_ext_fn)) + mlx5_core_dbg(dev, "failed to register max SFs resources"); + if (!max_fn && !max_ext_fn) return 0; table = kzalloc(sizeof(*table), GFP_KERNEL); - if (!table) - return -ENOMEM; + if (!table) { + err = -ENOMEM; + goto alloc_err; + } mutex_init(&table->table_lock); table->dev = dev; @@ -291,6 +323,8 @@ ext_err: table_err: mutex_destroy(&table->table_lock); kfree(table); +alloc_err: + mlx5_sf_hw_table_res_unregister(dev); return err; } @@ -299,12 +333,14 @@ void mlx5_sf_hw_table_cleanup(struct mlx5_core_dev *dev) struct mlx5_sf_hw_table *table = dev->priv.sf_hw_table; if (!table) - return; + goto res_unregister; - mutex_destroy(&table->table_lock); mlx5_sf_hw_table_hwc_cleanup(&table->hwc[MLX5_SF_HWC_EXTERNAL]); mlx5_sf_hw_table_hwc_cleanup(&table->hwc[MLX5_SF_HWC_LOCAL]); + mutex_destroy(&table->table_lock); kfree(table); +res_unregister: + mlx5_sf_hw_table_res_unregister(dev); } static int mlx5_sf_hw_vhca_event(struct notifier_block *nb, unsigned long opcode, void *data) -- cgit From a9f168e4c6e1f623dcf2640b9d76a4f61b9731e5 Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Wed, 31 May 2023 13:50:21 +0300 Subject: net/mlx5: Check with FW that sync reset completed successfully Even if the PF driver had no error on his part of the sync reset flow, the firmware can see wider picture as it syncs all the PFs in the flow. So add at end of sync reset flow check with firmware by reading MFRL register and initialization segment that the flow had no issue from firmware point of view too. Signed-off-by: Moshe Shemesh Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 3 ++ drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 39 ++++++++++++++++++---- drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h | 2 ++ 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 3d82ec890666..af8460bb257b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -212,6 +212,9 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a /* On fw_activate action, also driver is reloaded and reinit performed */ *actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); ret = mlx5_load_one_devl_locked(dev, true); + if (ret) + return ret; + ret = mlx5_fw_reset_verify_fw_complete(dev, extack); break; default: /* Unsupported action should not get to this function */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 4804990b7f22..e87766f91150 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -127,17 +127,23 @@ static int mlx5_fw_reset_get_reset_state_err(struct mlx5_core_dev *dev, if (mlx5_reg_mfrl_query(dev, NULL, NULL, &reset_state)) goto out; + if (!reset_state) + return 0; + switch (reset_state) { case MLX5_MFRL_REG_RESET_STATE_IN_NEGOTIATION: case MLX5_MFRL_REG_RESET_STATE_RESET_IN_PROGRESS: - NL_SET_ERR_MSG_MOD(extack, "Sync reset was already triggered"); + NL_SET_ERR_MSG_MOD(extack, "Sync reset still in progress"); return -EBUSY; - case MLX5_MFRL_REG_RESET_STATE_TIMEOUT: - NL_SET_ERR_MSG_MOD(extack, "Sync reset got timeout"); + case MLX5_MFRL_REG_RESET_STATE_NEG_TIMEOUT: + NL_SET_ERR_MSG_MOD(extack, "Sync reset negotiation timeout"); return -ETIMEDOUT; case MLX5_MFRL_REG_RESET_STATE_NACK: NL_SET_ERR_MSG_MOD(extack, "One of the hosts disabled reset"); return -EPERM; + case MLX5_MFRL_REG_RESET_STATE_UNLOAD_TIMEOUT: + NL_SET_ERR_MSG_MOD(extack, "Sync reset unload timeout"); + return -ETIMEDOUT; } out: @@ -151,7 +157,7 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; u32 out[MLX5_ST_SZ_DW(mfrl_reg)] = {}; u32 in[MLX5_ST_SZ_DW(mfrl_reg)] = {}; - int err; + int err, rst_res; set_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags); @@ -164,13 +170,34 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, return 0; clear_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags); - if (err == -EREMOTEIO && MLX5_CAP_MCAM_FEATURE(dev, reset_state)) - return mlx5_fw_reset_get_reset_state_err(dev, extack); + if (err == -EREMOTEIO && MLX5_CAP_MCAM_FEATURE(dev, reset_state)) { + rst_res = mlx5_fw_reset_get_reset_state_err(dev, extack); + return rst_res ? rst_res : err; + } NL_SET_ERR_MSG_MOD(extack, "Sync reset command failed"); return mlx5_cmd_check(dev, err, in, out); } +int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, + struct netlink_ext_ack *extack) +{ + u8 rst_state; + int err; + + err = mlx5_fw_reset_get_reset_state_err(dev, extack); + if (err) + return err; + + rst_state = mlx5_get_fw_rst_state(dev); + if (!rst_state) + return 0; + + mlx5_core_err(dev, "Sync reset did not complete, state=%d\n", rst_state); + NL_SET_ERR_MSG_MOD(extack, "Sync reset did not complete successfully"); + return rst_state; +} + int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) { return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h index c57465595f7c..ea527d06a85f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h @@ -12,6 +12,8 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); +int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, + struct netlink_ext_ack *extack); void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); void mlx5_fw_reset_events_stop(struct mlx5_core_dev *dev); void mlx5_drain_fw_reset(struct mlx5_core_dev *dev); -- cgit From e0e22d59b47a3306d448284a499169a361555099 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Wed, 19 Apr 2023 03:17:57 +0000 Subject: net/mlx5: E-switch, Add checking for flow rule destinations Firmware doesn't allow flow rules in FDB to do header rewrite and send packets to both internal and uplink vports. The following syndrome will be generated when trying to offload such kind of rules: mlx5_core 0000:08:00.0: mlx5_cmd_out_err:803:(pid 23569): SET_FLOW_TABLE_ENTRY(0x936) op_mod(0x0) failed, status bad parameter(0x3), syndrome (0x8c8f08), err(-22) To avoid this syndrome, add a checking before creating FTE. If a rule with header rewrite action forwards packets to both VF and PF, an error is returned directly. Signed-off-by: Jianbo Liu Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e391535e1ab1..46b8c60ac39a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -535,6 +535,28 @@ esw_src_port_rewrite_supported(struct mlx5_eswitch *esw) MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level); } +static bool +esw_dests_to_vf_pf_vports(struct mlx5_flow_destination *dests, int max_dest) +{ + bool vf_dest = false, pf_dest = false; + int i; + + for (i = 0; i < max_dest; i++) { + if (dests[i].type != MLX5_FLOW_DESTINATION_TYPE_VPORT) + continue; + + if (dests[i].vport.num == MLX5_VPORT_UPLINK) + pf_dest = true; + else + vf_dest = true; + + if (vf_dest && pf_dest) + return true; + } + + return false; +} + static int esw_setup_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, @@ -671,6 +693,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, rule = ERR_PTR(err); goto err_create_goto_table; } + + /* Header rewrite with combined wire+loopback in FDB is not allowed */ + if ((flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) && + esw_dests_to_vf_pf_vports(dest, i)) { + esw_warn(esw->dev, + "FDB: Header rewrite with forwarding to both PF and VF is not allowed\n"); + rule = ERR_PTR(-EINVAL); + goto err_esw_get; + } } if (esw_attr->decap_pkt_reformat) -- cgit From 2ad0160c02be2a56bd80aaeb5c40221250814c25 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Jun 2023 16:19:52 +0200 Subject: net/mlx5: Use auxiliary_device_uninit() instead of device_put() Instead of using device_put(), use auxiliary_device_uninit() for auxiliary device uninit which internally just calls device_put(). Signed-off-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c index 8e2abbab05f0..b2c849b8c0c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c @@ -129,7 +129,7 @@ static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u16 fn_id, err = auxiliary_device_add(&sf_dev->adev); if (err) { - put_device(&sf_dev->adev.dev); + auxiliary_device_uninit(&sf_dev->adev); goto add_err; } -- cgit From ae80d7a06fdb0b34a0f2842e1aac3da3bde93ccb Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 30 Jun 2023 09:32:14 +0200 Subject: net/mlx5: Remove redundant SF supported check from mlx5_sf_hw_table_init() Since mlx5_sf_supported() check is done as a first thing in mlx5_sf_max_functions(), remove the redundant check. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c index c4daeaaafead..1f613320fe07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c @@ -275,15 +275,14 @@ int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev) struct mlx5_sf_hw_table *table; u16 max_ext_fn = 0; u16 ext_base_id = 0; - u16 max_fn = 0; u16 base_id; + u16 max_fn; int err; if (!mlx5_vhca_event_supported(dev)) return 0; - if (mlx5_sf_supported(dev)) - max_fn = mlx5_sf_max_functions(dev); + max_fn = mlx5_sf_max_functions(dev); err = mlx5_esw_sf_max_hpf_functions(dev, &max_ext_fn, &ext_base_id); if (err) -- cgit From 88074d81e5fe8b76010ea3437330d5ab55535537 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 30 Jun 2023 09:37:04 +0200 Subject: net/mlx5: Use mlx5_sf_start_function_id() helper instead of directly calling MLX5_CAP_GEN() There is a helper called mlx5_sf_start_function_id() that wraps up a query to get base SF function id. Use that instead of calling MLX5_CAP_GEN() directly. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c index b2c849b8c0c9..39132a6cc68b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c @@ -167,7 +167,7 @@ mlx5_sf_dev_state_change_handler(struct notifier_block *nb, unsigned long event_ if (!max_functions) return 0; - base_id = MLX5_CAP_GEN(table->dev, sf_base_id); + base_id = mlx5_sf_start_function_id(table->dev); if (event->function_id < base_id || event->function_id >= (base_id + max_functions)) return 0; @@ -209,7 +209,7 @@ static int mlx5_sf_dev_vhca_arm_all(struct mlx5_sf_dev_table *table) int i; max_functions = mlx5_sf_max_functions(dev); - function_id = MLX5_CAP_GEN(dev, sf_base_id); + function_id = mlx5_sf_start_function_id(dev); /* Arm the vhca context as the vhca event notifier */ for (i = 0; i < max_functions; i++) { err = mlx5_vhca_event_arm(dev, function_id); @@ -234,7 +234,7 @@ static void mlx5_sf_dev_add_active_work(struct work_struct *work) int i; max_functions = mlx5_sf_max_functions(dev); - function_id = MLX5_CAP_GEN(dev, sf_base_id); + function_id = mlx5_sf_start_function_id(dev); for (i = 0; i < max_functions; i++, function_id++) { if (table->stop_active_wq) return; -- cgit From b63f8bde2fbadc8eca96b42dd281bf99bc853167 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 30 Jun 2023 09:41:14 +0200 Subject: net/mlx5: Remove redundant check of mlx5_vhca_event_supported() Since mlx5_vhca_event_supported() is called in mlx5_sf_dev_supported(), remove the redundant call. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c index 39132a6cc68b..e617a270d74a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c @@ -299,7 +299,7 @@ void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev) unsigned int max_sfs; int err; - if (!mlx5_sf_dev_supported(dev) || !mlx5_vhca_event_supported(dev)) + if (!mlx5_sf_dev_supported(dev)) return; table = kzalloc(sizeof(*table), GFP_KERNEL); -- cgit From 36e5a0efc81010dab29b17c66c58417a15851836 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 30 Jun 2023 12:45:39 +0200 Subject: net/mlx5: Fix error message in mlx5_sf_dev_state_change_handler() sw_function_id contains sfnum, so fix the error message to name the value properly. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c index e617a270d74a..05e148db9889 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c @@ -185,7 +185,7 @@ mlx5_sf_dev_state_change_handler(struct notifier_block *nb, unsigned long event_ mlx5_sf_dev_del(table->dev, sf_dev, sf_index); else mlx5_core_err(table->dev, - "SF DEV: teardown state for invalid dev index=%d fn_id=0x%x\n", + "SF DEV: teardown state for invalid dev index=%d sfnum=0x%x\n", sf_index, event->sw_function_id); break; case MLX5_VHCA_STATE_ACTIVE: -- cgit From 0b4eb603d635ca47c1c372f69b4b96672e4c2c05 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Sun, 2 Jan 2022 14:57:39 +0200 Subject: net/mlx5: Remove unused CAPs mlx5 driver queries the device for VECTOR_CALC and SHAMPO caps, but there isn't any user who requires them. As well as, MLX5_MCAM_REGS_0x9080_0x90FF is queried but not used. Thus, drop all usages and definitions of the mentioned caps above. Signed-off-by: Shay Drory Reviewed-by: Maher Sanalla Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 13 ------------- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 -- 2 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index fb2035a5ec99..c982ce06d7a3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -206,12 +206,6 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) return err; } - if (MLX5_CAP_GEN(dev, vector_calc)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_VECTOR_CALC); - if (err) - return err; - } - if (MLX5_CAP_GEN(dev, qos)) { err = mlx5_core_get_caps(dev, MLX5_CAP_QOS); if (err) @@ -226,7 +220,6 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) if (MLX5_CAP_GEN(dev, mcam_reg)) { mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_FIRST_128); - mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_0x9080_0x90FF); mlx5_get_mcam_access_reg_group(dev, MLX5_MCAM_REGS_0x9100_0x917F); } @@ -270,12 +263,6 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) return err; } - if (MLX5_CAP_GEN(dev, shampo)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_SHAMPO); - if (err) - return err; - } - if (MLX5_CAP_GEN_64(dev, general_obj_types) & MLX5_GENERAL_OBJ_TYPES_CAP_MACSEC_OFFLOAD) { err = mlx5_core_get_caps(dev, MLX5_CAP_MACSEC); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index f4fe06a5042e..cb77b5774aad 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1714,7 +1714,6 @@ static const int types[] = { MLX5_CAP_FLOW_TABLE, MLX5_CAP_ESWITCH_FLOW_TABLE, MLX5_CAP_ESWITCH, - MLX5_CAP_VECTOR_CALC, MLX5_CAP_QOS, MLX5_CAP_DEBUG, MLX5_CAP_DEV_MEM, @@ -1723,7 +1722,6 @@ static const int types[] = { MLX5_CAP_VDPA_EMULATION, MLX5_CAP_IPSEC, MLX5_CAP_PORT_SELECTION, - MLX5_CAP_DEV_SHAMPO, MLX5_CAP_MACSEC, MLX5_CAP_ADV_VIRTUALIZATION, MLX5_CAP_CRYPTO, -- cgit From a41cb59117fa12ee17cda5e5c781eecfcb15dc0f Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 11 Jul 2023 15:56:08 +0300 Subject: net/mlx5: Remove unused MAX HCA capabilities Each device cap has two modes: MAX and CUR. The driver maintains a cache of both modes of the capabilities. For most device caps, the MAX cap mode is never used. Hence, remove all driver queries of the MAX mode of the said caps as well as their helper MACROs. Signed-off-by: Shay Drory Reviewed-by: Maher Sanalla Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 34 ++++++++++++---------- drivers/net/ethernet/mellanox/mlx5/core/main.c | 14 +++++---- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 3 ++ 3 files changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index c982ce06d7a3..0e394408af75 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -160,13 +160,15 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) } if (MLX5_CAP_GEN(dev, eth_net_offloads)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ETHERNET_OFFLOADS, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_IPOIB_ENHANCED_OFFLOADS); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_IPOIB_ENHANCED_OFFLOADS, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } @@ -191,29 +193,30 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) if (MLX5_CAP_GEN(dev, nic_flow_table) || MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_FLOW_TABLE, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_ESWITCH_MANAGER(dev)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ESWITCH_FLOW_TABLE, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; - err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ESWITCH, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, qos)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_QOS); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_QOS, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, debug)) - mlx5_core_get_caps(dev, MLX5_CAP_DEBUG); + mlx5_core_get_caps_mode(dev, MLX5_CAP_DEBUG, HCA_CAP_OPMOD_GET_CUR); if (MLX5_CAP_GEN(dev, pcam_reg)) mlx5_get_pcam_reg(dev); @@ -227,51 +230,52 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) mlx5_get_qcam_reg(dev); if (MLX5_CAP_GEN(dev, device_memory)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_MEM); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_DEV_MEM, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, event_cap)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_EVENT); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_DEV_EVENT, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, tls_tx) || MLX5_CAP_GEN(dev, tls_rx)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_TLS); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_TLS, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN_64(dev, general_obj_types) & MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) { - err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_VDPA_EMULATION, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, ipsec_offload)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_IPSEC); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_IPSEC, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, crypto)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_CRYPTO); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_CRYPTO, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN_64(dev, general_obj_types) & MLX5_GENERAL_OBJ_TYPES_CAP_MACSEC_OFFLOAD) { - err = mlx5_core_get_caps(dev, MLX5_CAP_MACSEC); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_MACSEC, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, adv_virtualization)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ADV_VIRTUALIZATION); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ADV_VIRTUALIZATION, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index cb77b5774aad..15561965d2af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -361,9 +361,8 @@ void mlx5_core_uplink_netdev_event_replay(struct mlx5_core_dev *dev) } EXPORT_SYMBOL(mlx5_core_uplink_netdev_event_replay); -static int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, - enum mlx5_cap_type cap_type, - enum mlx5_cap_mode cap_mode) +int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type, + enum mlx5_cap_mode cap_mode) { u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)]; int out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); @@ -1620,21 +1619,24 @@ static int mlx5_query_hca_caps_light(struct mlx5_core_dev *dev) return err; if (MLX5_CAP_GEN(dev, eth_net_offloads)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ETHERNET_OFFLOADS, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, nic_flow_table) || MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_FLOW_TABLE, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN_64(dev, general_obj_types) & MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) { - err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_VDPA_EMULATION, + HCA_CAP_OPMOD_GET_CUR); if (err) return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 8e2028d20a9e..124352459c23 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -174,6 +174,9 @@ static inline int mlx5_flexible_inlen(struct mlx5_core_dev *dev, size_t fixed, #define MLX5_FLEXIBLE_INLEN(dev, fixed, item_size, num_items) \ mlx5_flexible_inlen(dev, fixed, item_size, num_items, __func__, __LINE__) +int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type); +int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type, + enum mlx5_cap_mode cap_mode); int mlx5_query_hca_caps(struct mlx5_core_dev *dev); int mlx5_query_board_id(struct mlx5_core_dev *dev); int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num); -- cgit From bd3a2f77809b84df5dc15edd72cf9955568e698e Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 11 Jul 2023 16:32:05 +0300 Subject: net/mlx5: Don't query MAX caps twice Whenever mlx5 driver is probed or reloaded, it queries some capabilities in MAX mode via set_hca_cap() API. Afterwards, the driver queries all capabilities in MAX mode via mlx5_query_hca_caps() API. Since MAX caps are read only caps, querying them twice is redundant. Hence, delete the second query. Signed-off-by: Shay Drory Reviewed-by: Maher Sanalla Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index 0e394408af75..58f4c0d0fafa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -143,18 +143,18 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) { int err; - err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_GENERAL, HCA_CAP_OPMOD_GET_CUR); if (err) return err; if (MLX5_CAP_GEN(dev, port_selection_cap)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_PORT_SELECTION); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_PORT_SELECTION, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, hca_cap_2)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL_2); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_GENERAL_2, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } @@ -174,19 +174,19 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) } if (MLX5_CAP_GEN(dev, pg)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ODP); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ODP, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, atomic)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ATOMIC); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ATOMIC, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } if (MLX5_CAP_GEN(dev, roce)) { - err = mlx5_core_get_caps(dev, MLX5_CAP_ROCE); + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_ROCE, HCA_CAP_OPMOD_GET_CUR); if (err) return err; } -- cgit From 479b322ee6feaff612285a0e7f22c022e8cd84eb Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 12 Aug 2023 10:30:33 +0100 Subject: net: dsa: mv88e6060: add phylink_get_caps implementation Add a phylink_get_caps implementation for Marvell 88e6060 DSA switch. This is a fast ethernet switch, with internal PHYs for ports 0 through 4. Port 4 also supports MII, REVMII, REVRMII and SNI. Port 5 supports MII, REVMII, REVRMII and SNI without an internal PHY. Reviewed-by: Andrew Lunn Signed-off-by: Russell King (Oracle) Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/E1qUkx7-003dMX-9b@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6060.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index fdda62d6eb16..294312b58e4f 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -247,11 +247,56 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) return reg_write(priv, addr, regnum, val); } +static void mv88e6060_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + unsigned long *interfaces = config->supported_interfaces; + struct mv88e6060_priv *priv = ds->priv; + int addr = REG_PORT(port); + int ret; + + ret = reg_read(priv, addr, PORT_STATUS); + if (ret < 0) { + dev_err(ds->dev, + "port %d: unable to read status register: %pe\n", + port, ERR_PTR(ret)); + return; + } + + /* If the port is configured in SNI mode (acts as a 10Mbps PHY), + * it should have phy-mode = "sni", but that doesn't yet exist, so + * forcibly fail validation until the need arises to introduce it. + */ + if (!(ret & PORT_STATUS_PORTMODE)) { + dev_warn(ds->dev, "port %d: SNI mode not supported\n", port); + return; + } + + config->mac_capabilities = MAC_100 | MAC_10 | MAC_SYM_PAUSE; + + if (port >= 4) { + /* Ports 4 and 5 can support MII, REVMII and REVRMII modes */ + __set_bit(PHY_INTERFACE_MODE_MII, interfaces); + __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); + __set_bit(PHY_INTERFACE_MODE_REVRMII, interfaces); + } + if (port <= 4) { + /* Ports 0 to 3 have internal PHYs, and port 4 can optionally + * use an internal PHY. + */ + /* Internal PHY */ + __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); + /* Default phylib interface mode */ + __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); + } +} + static const struct dsa_switch_ops mv88e6060_switch_ops = { .get_tag_protocol = mv88e6060_get_tag_protocol, .setup = mv88e6060_setup, .phy_read = mv88e6060_phy_read, .phy_write = mv88e6060_phy_write, + .phylink_get_caps = mv88e6060_phylink_get_caps, }; static int mv88e6060_probe(struct mdio_device *mdiodev) -- cgit From 7288dd2fd4888c85c687f8ded69c280938d1a7b6 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 14 Aug 2023 14:47:18 -0700 Subject: genetlink: use attrs from struct genl_info Since dumps carry struct genl_info now, use the attrs pointer from genl_info and remove the one in struct genl_dumpit_info. Reviewed-by: Johannes Berg Reviewed-by: Miquel Raynal Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20230814214723.2924989-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/wireguard/netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index 6d1bd9f52d02..dc09b75a3248 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -200,7 +200,7 @@ static int wg_get_device_start(struct netlink_callback *cb) { struct wg_device *wg; - wg = lookup_interface(genl_dumpit_info(cb)->attrs, cb->skb); + wg = lookup_interface(genl_info_dump(cb)->attrs, cb->skb); if (IS_ERR(wg)) return PTR_ERR(wg); DUMP_CTX(cb)->wg = wg; -- cgit From c66937b0f8dbb4c6c043663c702b1053fb47fab2 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 14 Aug 2023 02:58:14 +0100 Subject: net: phy: mediatek-ge-soc: support PHY LEDs Implement netdev trigger and primitive bliking offloading as well as simple set_brigthness function for both PHY LEDs of the in-SoC PHYs found in MT7981 and MT7988. For MT7988, read boottrap register and apply LED polarities accordingly to get uniform behavior from all LEDs on MT7988. This requires syscon phandle 'mediatek,pio' present in parenting MDIO bus which should point to the syscon holding the boottrap register. Signed-off-by: Daniel Golle Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/dc324d48c00cd7350f3a506eaa785324cae97372.1691977904.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/phy/mediatek-ge-soc.c | 435 +++++++++++++++++++++++++++++++++++++- 1 file changed, 426 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c index da512fab0eb0..8a20d9889f10 100644 --- a/drivers/net/phy/mediatek-ge-soc.c +++ b/drivers/net/phy/mediatek-ge-soc.c @@ -1,9 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ #include +#include +#include #include #include #include #include +#include #define MTK_GPHY_ID_MT7981 0x03a29461 #define MTK_GPHY_ID_MT7988 0x03a29481 @@ -206,9 +209,42 @@ #define MTK_PHY_DA_TX_R50_PAIR_C 0x53f #define MTK_PHY_DA_TX_R50_PAIR_D 0x540 +/* Registers on MDIO_MMD_VEND2 */ +#define MTK_PHY_LED0_ON_CTRL 0x24 +#define MTK_PHY_LED1_ON_CTRL 0x26 +#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) +#define MTK_PHY_LED_ON_LINK1000 BIT(0) +#define MTK_PHY_LED_ON_LINK100 BIT(1) +#define MTK_PHY_LED_ON_LINK10 BIT(2) +#define MTK_PHY_LED_ON_LINKDOWN BIT(3) +#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ +#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ +#define MTK_PHY_LED_ON_FORCE_ON BIT(6) +#define MTK_PHY_LED_ON_POLARITY BIT(14) +#define MTK_PHY_LED_ON_ENABLE BIT(15) + +#define MTK_PHY_LED0_BLINK_CTRL 0x25 +#define MTK_PHY_LED1_BLINK_CTRL 0x27 +#define MTK_PHY_LED_BLINK_1000TX BIT(0) +#define MTK_PHY_LED_BLINK_1000RX BIT(1) +#define MTK_PHY_LED_BLINK_100TX BIT(2) +#define MTK_PHY_LED_BLINK_100RX BIT(3) +#define MTK_PHY_LED_BLINK_10TX BIT(4) +#define MTK_PHY_LED_BLINK_10RX BIT(5) +#define MTK_PHY_LED_BLINK_COLLISION BIT(6) +#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) +#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) +#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) + +#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) + #define MTK_PHY_RG_BG_RASEL 0x115 #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) +/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */ +#define RG_GPIO_MISC_TPBANK0 0x6f0 +#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8) + /* These macro privides efuse parsing for internal phy. */ #define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) #define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) @@ -236,13 +272,6 @@ enum { PAIR_D, }; -enum { - GPHY_PORT0, - GPHY_PORT1, - GPHY_PORT2, - GPHY_PORT3, -}; - enum calibration_mode { EFUSE_K, SW_K @@ -261,6 +290,19 @@ enum CAL_MODE { SW_M }; +#define MTK_PHY_LED_STATE_FORCE_ON 0 +#define MTK_PHY_LED_STATE_FORCE_BLINK 1 +#define MTK_PHY_LED_STATE_NETDEV 2 + +struct mtk_socphy_priv { + unsigned long led_state; +}; + +struct mtk_socphy_shared { + u32 boottrap; + struct mtk_socphy_priv priv[4]; +}; + static int mtk_socphy_read_page(struct phy_device *phydev) { return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); @@ -1071,6 +1113,371 @@ static int mt798x_phy_config_init(struct phy_device *phydev) return mt798x_phy_calibration(phydev); } +static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, + bool on) +{ + unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); + struct mtk_socphy_priv *priv = phydev->priv; + bool changed; + + if (on) + changed = !test_and_set_bit(bit_on, &priv->led_state); + else + changed = !!test_and_clear_bit(bit_on, &priv->led_state); + + changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + + (index ? 16 : 0), &priv->led_state); + if (changed) + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? + MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED_ON_MASK, + on ? MTK_PHY_LED_ON_FORCE_ON : 0); + else + return 0; +} + +static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, + bool blinking) +{ + unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); + struct mtk_socphy_priv *priv = phydev->priv; + bool changed; + + if (blinking) + changed = !test_and_set_bit(bit_blink, &priv->led_state); + else + changed = !!test_and_clear_bit(bit_blink, &priv->led_state); + + changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + + (index ? 16 : 0), &priv->led_state); + if (changed) + return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? + MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL, + blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0); + else + return 0; +} + +static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) +{ + bool blinking = false; + int err = 0; + + if (index > 1) + return -EINVAL; + + if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { + blinking = true; + *delay_on = 50; + *delay_off = 50; + } + + err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); + if (err) + return err; + + return mt798x_phy_hw_led_on_set(phydev, index, false); +} + +static int mt798x_phy_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + int err; + + err = mt798x_phy_hw_led_blink_set(phydev, index, false); + if (err) + return err; + + return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); +} + +static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | + BIT(TRIGGER_NETDEV_HALF_DUPLEX) | + BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX)); + +static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + if (index > 1) + return -EINVAL; + + /* All combinations of the supported triggers are allowed */ + if (rules & ~supported_triggers) + return -EOPNOTSUPP; + + return 0; +}; + +static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); + unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); + unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); + struct mtk_socphy_priv *priv = phydev->priv; + int on, blink; + + if (index > 1) + return -EINVAL; + + on = phy_read_mmd(phydev, MDIO_MMD_VEND2, + index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); + + if (on < 0) + return -EIO; + + blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, + index ? MTK_PHY_LED1_BLINK_CTRL : + MTK_PHY_LED0_BLINK_CTRL); + if (blink < 0) + return -EIO; + + if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | + MTK_PHY_LED_ON_LINK10)) || + (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | + MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX | + MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))) + set_bit(bit_netdev, &priv->led_state); + else + clear_bit(bit_netdev, &priv->led_state); + + if (on & MTK_PHY_LED_ON_FORCE_ON) + set_bit(bit_on, &priv->led_state); + else + clear_bit(bit_on, &priv->led_state); + + if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) + set_bit(bit_blink, &priv->led_state); + else + clear_bit(bit_blink, &priv->led_state); + + if (!rules) + return 0; + + if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10)) + *rules |= BIT(TRIGGER_NETDEV_LINK); + + if (on & MTK_PHY_LED_ON_LINK10) + *rules |= BIT(TRIGGER_NETDEV_LINK_10); + + if (on & MTK_PHY_LED_ON_LINK100) + *rules |= BIT(TRIGGER_NETDEV_LINK_100); + + if (on & MTK_PHY_LED_ON_LINK1000) + *rules |= BIT(TRIGGER_NETDEV_LINK_1000); + + if (on & MTK_PHY_LED_ON_FDX) + *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); + + if (on & MTK_PHY_LED_ON_HDX) + *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); + + if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX)) + *rules |= BIT(TRIGGER_NETDEV_RX); + + if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)) + *rules |= BIT(TRIGGER_NETDEV_TX); + + return 0; +}; + +static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); + struct mtk_socphy_priv *priv = phydev->priv; + u16 on = 0, blink = 0; + int ret; + + if (index > 1) + return -EINVAL; + + if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) + on |= MTK_PHY_LED_ON_FDX; + + if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) + on |= MTK_PHY_LED_ON_HDX; + + if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) + on |= MTK_PHY_LED_ON_LINK10; + + if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) + on |= MTK_PHY_LED_ON_LINK100; + + if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) + on |= MTK_PHY_LED_ON_LINK1000; + + if (rules & BIT(TRIGGER_NETDEV_RX)) { + blink |= MTK_PHY_LED_BLINK_10RX | + MTK_PHY_LED_BLINK_100RX | + MTK_PHY_LED_BLINK_1000RX; + } + + if (rules & BIT(TRIGGER_NETDEV_TX)) { + blink |= MTK_PHY_LED_BLINK_10TX | + MTK_PHY_LED_BLINK_100TX | + MTK_PHY_LED_BLINK_1000TX; + } + + if (blink || on) + set_bit(bit_netdev, &priv->led_state); + else + clear_bit(bit_netdev, &priv->led_state); + + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? + MTK_PHY_LED1_ON_CTRL : + MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED_ON_FDX | + MTK_PHY_LED_ON_HDX | + MTK_PHY_LED_ON_LINK10 | + MTK_PHY_LED_ON_LINK100 | + MTK_PHY_LED_ON_LINK1000, + on); + + if (ret) + return ret; + + return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? + MTK_PHY_LED1_BLINK_CTRL : + MTK_PHY_LED0_BLINK_CTRL, blink); +}; + +static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) +{ + struct mtk_socphy_shared *priv = phydev->shared->priv; + u32 polarities; + + if (led_num == 0) + polarities = ~(priv->boottrap); + else + polarities = MTK_PHY_LED1_DEFAULT_POLARITIES; + + if (polarities & BIT(phydev->mdio.addr)) + return true; + + return false; +} + +static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev) +{ + struct pinctrl *pinctrl; + int index; + + /* Setup LED polarity according to bootstrap use of LED pins */ + for (index = 0; index < 2; ++index) + phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? + MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED_ON_POLARITY, + mt7988_phy_led_get_polarity(phydev, index) ? + MTK_PHY_LED_ON_POLARITY : 0); + + /* Only now setup pinctrl to avoid bogus blinking */ + pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); + if (IS_ERR(pinctrl)) + dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n"); + + return 0; +} + +static int mt7988_phy_probe_shared(struct phy_device *phydev) +{ + struct device_node *np = dev_of_node(&phydev->mdio.bus->dev); + struct mtk_socphy_shared *shared = phydev->shared->priv; + struct regmap *regmap; + u32 reg; + int ret; + + /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B, + * LED_C and LED_D respectively. At the same time those pins are used to + * bootstrap configuration of the reference clock source (LED_A), + * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). + * In practise this is done using a LED and a resistor pulling the pin + * either to GND or to VIO. + * The detected value at boot time is accessible at run-time using the + * TPBANK0 register located in the gpio base of the pinctrl, in order + * to read it here it needs to be referenced by a phandle called + * 'mediatek,pio' in the MDIO bus hosting the PHY. + * The 4 bits in TPBANK0 are kept as package shared data and are used to + * set LED polarity for each of the LED0. + */ + regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®); + if (ret) + return ret; + + shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); + + return 0; +} + +static void mt798x_phy_leds_state_init(struct phy_device *phydev) +{ + int i; + + for (i = 0; i < 2; ++i) + mt798x_phy_led_hw_control_get(phydev, i, NULL); +} + +static int mt7988_phy_probe(struct phy_device *phydev) +{ + struct mtk_socphy_shared *shared; + struct mtk_socphy_priv *priv; + int err; + + if (phydev->mdio.addr > 3) + return -EINVAL; + + err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, + sizeof(struct mtk_socphy_shared)); + if (err) + return err; + + if (phy_package_probe_once(phydev)) { + err = mt7988_phy_probe_shared(phydev); + if (err) + return err; + } + + shared = phydev->shared->priv; + priv = &shared->priv[phydev->mdio.addr]; + + phydev->priv = priv; + + mt798x_phy_leds_state_init(phydev); + + err = mt7988_phy_fix_leds_polarities(phydev); + if (err) + return err; + + return mt798x_phy_calibration(phydev); +} + +static int mt7981_phy_probe(struct phy_device *phydev) +{ + struct mtk_socphy_priv *priv; + + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + mt798x_phy_leds_state_init(phydev); + + return mt798x_phy_calibration(phydev); +} + static struct phy_driver mtk_socphy_driver[] = { { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), @@ -1078,11 +1485,16 @@ static struct phy_driver mtk_socphy_driver[] = { .config_init = mt798x_phy_config_init, .config_intr = genphy_no_config_intr, .handle_interrupt = genphy_handle_interrupt_no_ack, - .probe = mt798x_phy_calibration, + .probe = mt7981_phy_probe, .suspend = genphy_suspend, .resume = genphy_resume, .read_page = mtk_socphy_read_page, .write_page = mtk_socphy_write_page, + .led_blink_set = mt798x_phy_led_blink_set, + .led_brightness_set = mt798x_phy_led_brightness_set, + .led_hw_is_supported = mt798x_phy_led_hw_is_supported, + .led_hw_control_set = mt798x_phy_led_hw_control_set, + .led_hw_control_get = mt798x_phy_led_hw_control_get, }, { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), @@ -1090,11 +1502,16 @@ static struct phy_driver mtk_socphy_driver[] = { .config_init = mt798x_phy_config_init, .config_intr = genphy_no_config_intr, .handle_interrupt = genphy_handle_interrupt_no_ack, - .probe = mt798x_phy_calibration, + .probe = mt7988_phy_probe, .suspend = genphy_suspend, .resume = genphy_resume, .read_page = mtk_socphy_read_page, .write_page = mtk_socphy_write_page, + .led_blink_set = mt798x_phy_led_blink_set, + .led_brightness_set = mt798x_phy_led_brightness_set, + .led_hw_is_supported = mt798x_phy_led_hw_is_supported, + .led_hw_control_set = mt798x_phy_led_hw_control_set, + .led_hw_control_get = mt798x_phy_led_hw_control_get, }, }; -- cgit From 7a456b894ea57cceee6951ce421205152f23a051 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 14 Aug 2023 09:45:03 +0200 Subject: qed: remove unused 'resp_size' calculation Newer versions of clang warn about this variable being assigned but never used: drivers/net/ethernet/qlogic/qed/qed_vf.c:63:67: error: parameter 'resp_size' set but not used [-Werror,-Wunused-but-set-parameter] There is no indication in the git history on how this was ever meant to be used, so just remove the entire calculation and argument passing for it to avoid the warning. Signed-off-by: Arnd Bergmann Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230814074512.1067715-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/qlogic/qed/qed_vf.c | 45 ++++++++++++-------------------- 1 file changed, 17 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index 7b0e390c0b07..0e265ed1f501 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -60,7 +60,7 @@ static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status) #define QED_VF_CHANNEL_MSLEEP_ITERATIONS 10 #define QED_VF_CHANNEL_MSLEEP_DELAY 25 -static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) +static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done) { union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request; struct ustorm_trigger_vf_zone trigger; @@ -72,9 +72,6 @@ static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) /* output tlvs list */ qed_dp_tlv_list(p_hwfn, p_req); - /* need to add the END TLV to the message size */ - resp_size += sizeof(struct channel_list_end_tlv); - /* Send TLVs over HW channel */ memset(&trigger, 0, sizeof(struct ustorm_trigger_vf_zone)); trigger.vf_pf_msg_valid = 1; @@ -172,7 +169,7 @@ static int _qed_vf_pf_release(struct qed_hwfn *p_hwfn, bool b_final) CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (!rc && resp->hdr.status != PFVF_STATUS_SUCCESS) rc = -EAGAIN; @@ -301,7 +298,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn) memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); /* send acquire request */ - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); /* Re-try acquire in case of vf-pf hw channel timeout */ if (retry_cnt && rc == -EBUSY) { @@ -705,7 +702,7 @@ int qed_vf_pf_tunnel_param_update(struct qed_hwfn *p_hwfn, sizeof(struct channel_list_end_tlv)); p_resp = &p_iov->pf2vf_reply->tunn_param_resp; - rc = qed_send_msg2pf(p_hwfn, &p_resp->hdr.status, sizeof(*p_resp)); + rc = qed_send_msg2pf(p_hwfn, &p_resp->hdr.status); if (rc) goto exit; @@ -772,7 +769,7 @@ qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->queue_start; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -822,7 +819,7 @@ int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -867,7 +864,7 @@ qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->queue_start; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -918,7 +915,7 @@ int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid) CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -968,7 +965,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -997,7 +994,7 @@ int qed_vf_pf_vport_stop(struct qed_hwfn *p_hwfn) qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1075,12 +1072,10 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, struct vfpf_vport_update_tlv *req; struct pfvf_def_resp_tlv *resp; u8 update_rx, update_tx; - u32 resp_size = 0; u16 size, tlv; int rc; resp = &p_iov->pf2vf_reply->default_resp; - resp_size = sizeof(*resp); update_rx = p_params->update_vport_active_rx_flg; update_tx = p_params->update_vport_active_tx_flg; @@ -1096,7 +1091,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, p_act_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_VPORT_UPDATE_ACTIVATE, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); if (update_rx) { p_act_tlv->update_rx = update_rx; @@ -1116,7 +1110,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH; p_tx_switch_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); p_tx_switch_tlv->tx_switching = p_params->tx_switching_flg; } @@ -1127,7 +1120,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, size = sizeof(struct vfpf_vport_update_mcast_bin_tlv); p_mcast_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_VPORT_UPDATE_MCAST, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); memcpy(p_mcast_tlv->bins, p_params->bins, sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS); @@ -1142,7 +1134,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM; size = sizeof(struct vfpf_vport_update_accept_param_tlv); p_accept_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); if (update_rx) { p_accept_tlv->update_rx_mode = update_rx; @@ -1166,7 +1157,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, p_rss_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_VPORT_UPDATE_RSS, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); if (rss_params->update_rss_config) p_rss_tlv->update_rss_flags |= @@ -1203,7 +1193,6 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN; p_any_vlan_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size); - resp_size += sizeof(struct pfvf_def_resp_tlv); p_any_vlan_tlv->accept_any_vlan = p_params->accept_any_vlan; p_any_vlan_tlv->update_accept_any_vlan_flg = p_params->update_accept_any_vlan_flg; @@ -1213,7 +1202,7 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, resp_size); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1245,7 +1234,7 @@ int qed_vf_pf_reset(struct qed_hwfn *p_hwfn) CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1303,7 +1292,7 @@ int qed_vf_pf_filter_ucast(struct qed_hwfn *p_hwfn, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1332,7 +1321,7 @@ int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn) qed_add_tlv(p_hwfn, &p_iov->offset, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1364,7 +1353,7 @@ int qed_vf_pf_get_coalesce(struct qed_hwfn *p_hwfn, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->read_coal_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; @@ -1402,7 +1391,7 @@ qed_vf_pf_bulletin_update_mac(struct qed_hwfn *p_hwfn, sizeof(struct channel_list_end_tlv)); p_resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &p_resp->hdr.status, sizeof(*p_resp)); + rc = qed_send_msg2pf(p_hwfn, &p_resp->hdr.status); qed_vf_pf_req_end(p_hwfn, rc); return rc; } @@ -1433,7 +1422,7 @@ qed_vf_pf_set_coalesce(struct qed_hwfn *p_hwfn, sizeof(struct channel_list_end_tlv)); resp = &p_iov->pf2vf_reply->default_resp; - rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); + rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status); if (rc) goto exit; -- cgit From 3bfdcc324a04ba27f3fd2a6633c53de1758e7b6a Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 14 Aug 2023 21:58:21 +0800 Subject: net: e1000e: Remove unused declarations Commit bdfe2da6aefd ("e1000e: cosmetic move of function prototypes to the new mac.h") declared but never implemented them. Signed-off-by: Yue Haibing Reviewed-by: Tony Nguyen Link: https://lore.kernel.org/r/20230814135821.4808-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/e1000e/mac.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000e/mac.h b/drivers/net/ethernet/intel/e1000e/mac.h index 6ab261119801..563176fd436e 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.h +++ b/drivers/net/ethernet/intel/e1000e/mac.h @@ -29,8 +29,6 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); s32 e1000e_setup_led_generic(struct e1000_hw *hw); s32 e1000e_setup_link_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); void e1000_clear_vfta_generic(struct e1000_hw *hw); -- cgit From cf74eb5a5bc867258e7d0b0d1c3c4a60e1e3de2f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 14 Aug 2023 08:35:21 -0700 Subject: eth: r8152: try to use a normal budget Mario reports that loading r8152 on his system leads to a: netif_napi_add_weight() called with weight 256 warning getting printed. We don't have any solid data on why such high budget was chosen, and it may cause stalls in processing other softirqs and rt threads. So try to switch back to the default (64) weight. If this slows down someone's system we should investigate which part of stopping starting the NAPI poll in this driver are expensive. Reported-by: Mario Limonciello Link: https://lore.kernel.org/all/0bfd445a-81f7-f702-08b0-bd5a72095e49@amd.com/ Acked-by: Hayes Wang Link: https://lore.kernel.org/r/20230814153521.2697982-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/usb/r8152.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index db9897e825b4..bb234cf0cea0 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -9760,8 +9760,7 @@ static int rtl8152_probe(struct usb_interface *intf, usb_set_intfdata(intf, tp); - netif_napi_add_weight(netdev, &tp->napi, r8152_poll, - tp->support_2500full ? 256 : 64); + netif_napi_add(netdev, &tp->napi, r8152_poll); ret = register_netdev(netdev); if (ret != 0) { -- cgit From f601899e432155c1c7d372a7924f1a2301ca64b4 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 15 Aug 2023 13:19:54 +0800 Subject: net: fec: add XDP_TX feature support The XDP_TX feature is not supported before, and all the frames which are deemed to do XDP_TX action actually do the XDP_DROP action. So this patch adds the XDP_TX support to FEC driver. I tested the performance of XDP_TX in XDP_DRV mode and XDP_SKB mode respectively on i.MX8MP-EVK platform, and as suggested by Jesper, I also tested the performance of XDP_REDIRECT on the same platform. And the test steps and results are as follows. XDP_TX test: Step 1: One board is used as generator and connects to switch,and the FEC port of DUT also connects to the switch. Both boards with flow control off. Then the generator runs the pktgen_sample03_burst_single_flow.sh script to generate and send burst traffic to DUT. Note that the size of packet was set to 64 bytes and the procotol of packet was UDP in my test scenario. In addition, the SMAC of the packet need to be different from the MAC of the generator, because the xdp2 program will swap the DMAC and SMAC of the packet and send it back to the generator. If the SMAC of the generated packet is the MAC of the generator, the generator will receive the returned traffic which increase the CPU loading and significantly degrade the transmit speed of the generator, and finally it affects the test of XDP_TX performance. Step 2: The DUT runs the xdp2 program to transmit received UDP packets back out on the same port where they were received. root@imx8mpevk:~# ./xdp2 eth0 proto 17: 353918 pkt/s proto 17: 352923 pkt/s proto 17: 353900 pkt/s proto 17: 352672 pkt/s proto 17: 353912 pkt/s proto 17: 354219 pkt/s root@imx8mpevk:~# ./xdp2 -S eth0 proto 17: 160604 pkt/s proto 17: 160708 pkt/s proto 17: 160564 pkt/s proto 17: 160684 pkt/s proto 17: 160640 pkt/s proto 17: 160720 pkt/s The above results show that the XDP_TX performance of XDP_DRV mode is much better than XDP_SKB mode, more than twice that of XDP_SKB mode, which is in line with our expectation. XDP_REDIRECT test: Step1: Both the generator and the FEC port of the DUT connet to the switch port. All the ports with flow control off, then the generator runs the pktgen script to generate and send burst traffic to DUT. Note that the size of packet was set to 64 bytes and the procotol of packet was UDP in my test scenario. Step2: The DUT runs the xdp_redirect program to redirect the traffic from the FEC port to the FEC port itself. root@imx8mpevk:~# ./xdp_redirect eth0 eth0 Redirecting from eth0 (ifindex 2; driver fec) to eth0 (ifindex 2; driver fec) Summary 232,302 rx/s 0 err,drop/s 232,344 xmit/s Summary 234,579 rx/s 0 err,drop/s 234,577 xmit/s Summary 235,548 rx/s 0 err,drop/s 235,549 xmit/s Summary 234,704 rx/s 0 err,drop/s 234,703 xmit/s Summary 235,504 rx/s 0 err,drop/s 235,504 xmit/s Summary 235,223 rx/s 0 err,drop/s 235,224 xmit/s Summary 234,509 rx/s 0 err,drop/s 234,507 xmit/s Summary 235,481 rx/s 0 err,drop/s 235,482 xmit/s Summary 234,684 rx/s 0 err,drop/s 234,683 xmit/s Summary 235,520 rx/s 0 err,drop/s 235,520 xmit/s Summary 235,461 rx/s 0 err,drop/s 235,461 xmit/s Summary 234,627 rx/s 0 err,drop/s 234,627 xmit/s Summary 235,611 rx/s 0 err,drop/s 235,611 xmit/s Packets received : 3,053,753 Average packets/s : 234,904 Packets transmitted : 3,053,792 Average transmit/s : 234,907 Compared the performance of XDP_TX with XDP_REDIRECT, XDP_TX is also much better than XDP_REDIRECT. It's also in line with our expectation. Signed-off-by: Wei Fang Suggested-by: Jesper Dangaard Brouer Suggested-by: Jakub Kicinski Reviewed-by: Larysa Zaremba Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/freescale/fec_main.c | 107 ++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 5ca9906d7c6a..7bb02a9da2a6 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -548,6 +548,7 @@ enum { enum fec_txbuf_type { FEC_TXBUF_T_SKB, FEC_TXBUF_T_XDP_NDO, + FEC_TXBUF_T_XDP_TX, }; struct fec_tx_buffer { diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3bd0bf03aedb..9bba3d7c949c 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -69,6 +69,7 @@ #include #include #include +#include #include @@ -76,6 +77,9 @@ static void set_multicast_list(struct net_device *ndev); static void fec_enet_itr_coal_set(struct net_device *ndev); +static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep, + int cpu, struct xdp_buff *xdp, + u32 dma_sync_len); #define DRIVER_NAME "fec" @@ -961,7 +965,8 @@ static void fec_enet_bd_init(struct net_device *dev) txq->tx_buf[i].skb = NULL; } } else { - if (bdp->cbd_bufaddr) + if (bdp->cbd_bufaddr && + txq->tx_buf[i].type == FEC_TXBUF_T_XDP_NDO) dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), @@ -1424,13 +1429,14 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) break; xdpf = txq->tx_buf[index].xdp; - if (bdp->cbd_bufaddr) + if (bdp->cbd_bufaddr && + txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); bdp->cbd_bufaddr = cpu_to_fec32(0); - if (!xdpf) { + if (unlikely(!xdpf)) { txq->tx_buf[index].type = FEC_TXBUF_T_SKB; goto tx_buf_done; } @@ -1483,7 +1489,16 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); } else { - xdp_return_frame(xdpf); + if (txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) { + xdp_return_frame_rx_napi(xdpf); + } else { /* recycle pages of XDP_TX frames */ + struct page *page = virt_to_head_page(xdpf->data); + + /* The dma_sync_size = 0 as XDP_TX has already + * synced DMA for_device. + */ + page_pool_put_page(page->pp, page, 0, true); + } txq->tx_buf[index].xdp = NULL; /* restore default tx buffer type: FEC_TXBUF_T_SKB */ @@ -1542,7 +1557,7 @@ static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq, static u32 fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, - struct xdp_buff *xdp, struct fec_enet_priv_rx_q *rxq, int index) + struct xdp_buff *xdp, struct fec_enet_priv_rx_q *rxq, int cpu) { unsigned int sync, len = xdp->data_end - xdp->data; u32 ret = FEC_ENET_XDP_PASS; @@ -1552,8 +1567,10 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, act = bpf_prog_run_xdp(prog, xdp); - /* Due xdp_adjust_tail: DMA sync for_device cover max len CPU touch */ - sync = xdp->data_end - xdp->data_hard_start - FEC_ENET_XDP_HEADROOM; + /* Due xdp_adjust_tail and xdp_adjust_head: DMA sync for_device cover + * max len CPU touch + */ + sync = xdp->data_end - xdp->data; sync = max(sync, len); switch (act) { @@ -1574,11 +1591,19 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, } break; - default: - bpf_warn_invalid_xdp_action(fep->netdev, prog, act); - fallthrough; - case XDP_TX: + err = fec_enet_xdp_tx_xmit(fep, cpu, xdp, sync); + if (unlikely(err)) { + ret = FEC_ENET_XDP_CONSUMED; + page = virt_to_head_page(xdp->data); + page_pool_put_page(rxq->page_pool, page, sync, true); + trace_xdp_exception(fep->netdev, prog, act); + } else { + ret = FEC_ENET_XDP_TX; + } + break; + + default: bpf_warn_invalid_xdp_action(fep->netdev, prog, act); fallthrough; @@ -1620,6 +1645,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) struct bpf_prog *xdp_prog = READ_ONCE(fep->xdp_prog); u32 ret, xdp_result = FEC_ENET_XDP_PASS; u32 data_start = FEC_ENET_XDP_HEADROOM; + int cpu = smp_processor_id(); struct xdp_buff xdp; struct page *page; u32 sub_len = 4; @@ -1698,7 +1724,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) /* subtract 16bit shift and FCS */ xdp_prepare_buff(&xdp, page_address(page), data_start, pkt_len - sub_len, false); - ret = fec_enet_run_xdp(fep, xdp_prog, &xdp, rxq, index); + ret = fec_enet_run_xdp(fep, xdp_prog, &xdp, rxq, cpu); xdp_result |= ret; if (ret != FEC_ENET_XDP_PASS) goto rx_processing_done; @@ -3767,7 +3793,8 @@ fec_enet_xdp_get_tx_queue(struct fec_enet_private *fep, int index) static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, struct fec_enet_priv_tx_q *txq, - struct xdp_frame *frame) + struct xdp_frame *frame, + u32 dma_sync_len, bool ndo_xmit) { unsigned int index, status, estatus; struct bufdesc *bdp; @@ -3787,10 +3814,24 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, index = fec_enet_get_bd_index(bdp, &txq->bd); - dma_addr = dma_map_single(&fep->pdev->dev, frame->data, - frame->len, DMA_TO_DEVICE); - if (dma_mapping_error(&fep->pdev->dev, dma_addr)) - return -ENOMEM; + if (ndo_xmit) { + dma_addr = dma_map_single(&fep->pdev->dev, frame->data, + frame->len, DMA_TO_DEVICE); + if (dma_mapping_error(&fep->pdev->dev, dma_addr)) + return -ENOMEM; + + txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO; + } else { + struct page *page = virt_to_page(frame->data); + + dma_addr = page_pool_get_dma_addr(page) + sizeof(*frame) + + frame->headroom; + dma_sync_single_for_device(&fep->pdev->dev, dma_addr, + dma_sync_len, DMA_BIDIRECTIONAL); + txq->tx_buf[index].type = FEC_TXBUF_T_XDP_TX; + } + + txq->tx_buf[index].xdp = frame; status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); if (fep->bufdesc_ex) @@ -3809,9 +3850,6 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, ebdp->cbd_esc = cpu_to_fec32(estatus); } - txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO; - txq->tx_buf[index].xdp = frame; - /* Make sure the updates to rest of the descriptor are performed before * transferring ownership. */ @@ -3837,6 +3875,33 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, return 0; } +static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep, + int cpu, struct xdp_buff *xdp, + u32 dma_sync_len) +{ + struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); + struct fec_enet_priv_tx_q *txq; + struct netdev_queue *nq; + int queue, ret; + + if (unlikely(!xdpf)) + return -EFAULT; + + queue = fec_enet_xdp_get_tx_queue(fep, cpu); + txq = fep->tx_queue[queue]; + nq = netdev_get_tx_queue(fep->netdev, queue); + + __netif_tx_lock(nq, cpu); + + /* Avoid tx timeout as XDP shares the queue with kernel stack */ + txq_trans_cond_update(nq); + ret = fec_enet_txq_xmit_frame(fep, txq, xdpf, dma_sync_len, false); + + __netif_tx_unlock(nq); + + return ret; +} + static int fec_enet_xdp_xmit(struct net_device *dev, int num_frames, struct xdp_frame **frames, @@ -3859,7 +3924,7 @@ static int fec_enet_xdp_xmit(struct net_device *dev, /* Avoid tx timeout as XDP shares the queue with kernel stack */ txq_trans_cond_update(nq); for (i = 0; i < num_frames; i++) { - if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0) + if (fec_enet_txq_xmit_frame(fep, txq, frames[i], 0, true) < 0) break; sent_frames++; } -- cgit From af6f4791380c320802df2106e295efd29c5e8b16 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 15 Aug 2023 13:19:55 +0800 Subject: net: fec: improve XDP_TX performance As suggested by Jesper and Alexander, we can avoid converting xdp_buff to xdp_frame in case of XDP_TX to save a bunch of CPU cycles, so that we can further improve the XDP_TX performance. Before this patch on i.MX8MP-EVK board, the performance shows as follows. root@imx8mpevk:~# ./xdp2 eth0 proto 17: 353918 pkt/s proto 17: 352923 pkt/s proto 17: 353900 pkt/s proto 17: 352672 pkt/s proto 17: 353912 pkt/s proto 17: 354219 pkt/s After applying this patch, the performance is improved. root@imx8mpevk:~# ./xdp2 eth0 proto 17: 369261 pkt/s proto 17: 369267 pkt/s proto 17: 369206 pkt/s proto 17: 369214 pkt/s proto 17: 369126 pkt/s proto 17: 369272 pkt/s Signed-off-by: Wei Fang Suggested-by: Alexander Lobakin Suggested-by: Jesper Dangaard Brouer Reviewed-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 5 +- drivers/net/ethernet/freescale/fec_main.c | 140 ++++++++++++++++-------------- 2 files changed, 75 insertions(+), 70 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 7bb02a9da2a6..a8fbcada6b01 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -552,10 +552,7 @@ enum fec_txbuf_type { }; struct fec_tx_buffer { - union { - struct sk_buff *skb; - struct xdp_frame *xdp; - }; + void *buf_p; enum fec_txbuf_type type; }; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 9bba3d7c949c..f77105f017c1 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -400,7 +400,7 @@ static void fec_dump(struct net_device *ndev) fec16_to_cpu(bdp->cbd_sc), fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), - txq->tx_buf[index].skb); + txq->tx_buf[index].buf_p); bdp = fec_enet_get_nextdesc(bdp, &txq->bd); index++; } while (bdp != txq->bd.base); @@ -657,7 +657,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, index = fec_enet_get_bd_index(last_bdp, &txq->bd); /* Save skb pointer */ - txq->tx_buf[index].skb = skb; + txq->tx_buf[index].buf_p = skb; /* Make sure the updates to rest of the descriptor are performed before * transferring ownership. @@ -863,7 +863,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, } /* Save skb pointer */ - txq->tx_buf[index].skb = skb; + txq->tx_buf[index].buf_p = skb; skb_tx_timestamp(skb); txq->bd.cur = bdp; @@ -960,27 +960,27 @@ static void fec_enet_bd_init(struct net_device *dev) fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); - if (txq->tx_buf[i].skb) { - dev_kfree_skb_any(txq->tx_buf[i].skb); - txq->tx_buf[i].skb = NULL; - } - } else { - if (bdp->cbd_bufaddr && - txq->tx_buf[i].type == FEC_TXBUF_T_XDP_NDO) + if (txq->tx_buf[i].buf_p) + dev_kfree_skb_any(txq->tx_buf[i].buf_p); + } else if (txq->tx_buf[i].type == FEC_TXBUF_T_XDP_NDO) { + if (bdp->cbd_bufaddr) dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); - if (txq->tx_buf[i].xdp) { - xdp_return_frame(txq->tx_buf[i].xdp); - txq->tx_buf[i].xdp = NULL; - } + if (txq->tx_buf[i].buf_p) + xdp_return_frame(txq->tx_buf[i].buf_p); + } else { + struct page *page = txq->tx_buf[i].buf_p; - /* restore default tx buffer type: FEC_TXBUF_T_SKB */ - txq->tx_buf[i].type = FEC_TXBUF_T_SKB; + if (page) + page_pool_put_page(page->pp, page, 0, false); } + txq->tx_buf[i].buf_p = NULL; + /* restore default tx buffer type: FEC_TXBUF_T_SKB */ + txq->tx_buf[i].type = FEC_TXBUF_T_SKB; bdp->cbd_bufaddr = cpu_to_fec32(0); bdp = fec_enet_get_nextdesc(bdp, &txq->bd); } @@ -1387,6 +1387,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) struct netdev_queue *nq; int index = 0; int entries_free; + struct page *page; + int frame_len; fep = netdev_priv(ndev); @@ -1408,8 +1410,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) index = fec_enet_get_bd_index(bdp, &txq->bd); if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) { - skb = txq->tx_buf[index].skb; - txq->tx_buf[index].skb = NULL; + skb = txq->tx_buf[index].buf_p; if (bdp->cbd_bufaddr && !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) dma_unmap_single(&fep->pdev->dev, @@ -1428,18 +1429,24 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) if (unlikely(!budget)) break; - xdpf = txq->tx_buf[index].xdp; - if (bdp->cbd_bufaddr && - txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) - dma_unmap_single(&fep->pdev->dev, - fec32_to_cpu(bdp->cbd_bufaddr), - fec16_to_cpu(bdp->cbd_datlen), - DMA_TO_DEVICE); + if (txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) { + xdpf = txq->tx_buf[index].buf_p; + if (bdp->cbd_bufaddr) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + } else { + page = txq->tx_buf[index].buf_p; + } + bdp->cbd_bufaddr = cpu_to_fec32(0); - if (unlikely(!xdpf)) { + if (unlikely(!txq->tx_buf[index].buf_p)) { txq->tx_buf[index].type = FEC_TXBUF_T_SKB; goto tx_buf_done; } + + frame_len = fec16_to_cpu(bdp->cbd_datlen); } /* Check for errors. */ @@ -1463,7 +1470,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) ndev->stats.tx_bytes += skb->len; else - ndev->stats.tx_bytes += xdpf->len; + ndev->stats.tx_bytes += frame_len; } /* Deferred means some collisions occurred during transmit, @@ -1488,23 +1495,17 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); - } else { - if (txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) { - xdp_return_frame_rx_napi(xdpf); - } else { /* recycle pages of XDP_TX frames */ - struct page *page = virt_to_head_page(xdpf->data); - - /* The dma_sync_size = 0 as XDP_TX has already - * synced DMA for_device. - */ - page_pool_put_page(page->pp, page, 0, true); - } - - txq->tx_buf[index].xdp = NULL; - /* restore default tx buffer type: FEC_TXBUF_T_SKB */ - txq->tx_buf[index].type = FEC_TXBUF_T_SKB; + } else if (txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) { + xdp_return_frame_rx_napi(xdpf); + } else { /* recycle pages of XDP_TX frames */ + /* The dma_sync_size = 0 as XDP_TX has already synced DMA for_device */ + page_pool_put_page(page->pp, page, 0, true); } + txq->tx_buf[index].buf_p = NULL; + /* restore default tx buffer type: FEC_TXBUF_T_SKB */ + txq->tx_buf[index].type = FEC_TXBUF_T_SKB; + tx_buf_done: /* Make sure the update to bdp and tx_buf are performed * before dirty_tx @@ -3234,7 +3235,6 @@ static void fec_enet_free_buffers(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); unsigned int i; - struct sk_buff *skb; struct fec_enet_priv_tx_q *txq; struct fec_enet_priv_rx_q *rxq; unsigned int q; @@ -3259,18 +3259,23 @@ static void fec_enet_free_buffers(struct net_device *ndev) kfree(txq->tx_bounce[i]); txq->tx_bounce[i] = NULL; + if (!txq->tx_buf[i].buf_p) { + txq->tx_buf[i].type = FEC_TXBUF_T_SKB; + continue; + } + if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) { - skb = txq->tx_buf[i].skb; - txq->tx_buf[i].skb = NULL; - dev_kfree_skb(skb); + dev_kfree_skb(txq->tx_buf[i].buf_p); + } else if (txq->tx_buf[i].type == FEC_TXBUF_T_XDP_NDO) { + xdp_return_frame(txq->tx_buf[i].buf_p); } else { - if (txq->tx_buf[i].xdp) { - xdp_return_frame(txq->tx_buf[i].xdp); - txq->tx_buf[i].xdp = NULL; - } + struct page *page = txq->tx_buf[i].buf_p; - txq->tx_buf[i].type = FEC_TXBUF_T_SKB; + page_pool_put_page(page->pp, page, 0, false); } + + txq->tx_buf[i].buf_p = NULL; + txq->tx_buf[i].type = FEC_TXBUF_T_SKB; } } } @@ -3793,13 +3798,14 @@ fec_enet_xdp_get_tx_queue(struct fec_enet_private *fep, int index) static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, struct fec_enet_priv_tx_q *txq, - struct xdp_frame *frame, - u32 dma_sync_len, bool ndo_xmit) + void *frame, u32 dma_sync_len, + bool ndo_xmit) { unsigned int index, status, estatus; struct bufdesc *bdp; dma_addr_t dma_addr; int entries_free; + u16 frame_len; entries_free = fec_enet_get_free_txdesc_num(txq); if (entries_free < MAX_SKB_FRAGS + 1) { @@ -3815,30 +3821,36 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, index = fec_enet_get_bd_index(bdp, &txq->bd); if (ndo_xmit) { - dma_addr = dma_map_single(&fep->pdev->dev, frame->data, - frame->len, DMA_TO_DEVICE); + struct xdp_frame *xdpf = frame; + + dma_addr = dma_map_single(&fep->pdev->dev, xdpf->data, + xdpf->len, DMA_TO_DEVICE); if (dma_mapping_error(&fep->pdev->dev, dma_addr)) return -ENOMEM; + frame_len = xdpf->len; + txq->tx_buf[index].buf_p = xdpf; txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO; } else { - struct page *page = virt_to_page(frame->data); + struct xdp_buff *xdpb = frame; + struct page *page; - dma_addr = page_pool_get_dma_addr(page) + sizeof(*frame) + - frame->headroom; + page = virt_to_page(xdpb->data); + dma_addr = page_pool_get_dma_addr(page) + + (xdpb->data - xdpb->data_hard_start); dma_sync_single_for_device(&fep->pdev->dev, dma_addr, dma_sync_len, DMA_BIDIRECTIONAL); + frame_len = xdpb->data_end - xdpb->data; + txq->tx_buf[index].buf_p = page; txq->tx_buf[index].type = FEC_TXBUF_T_XDP_TX; } - txq->tx_buf[index].xdp = frame; - status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); if (fep->bufdesc_ex) estatus = BD_ENET_TX_INT; bdp->cbd_bufaddr = cpu_to_fec32(dma_addr); - bdp->cbd_datlen = cpu_to_fec16(frame->len); + bdp->cbd_datlen = cpu_to_fec16(frame_len); if (fep->bufdesc_ex) { struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; @@ -3879,14 +3891,10 @@ static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep, int cpu, struct xdp_buff *xdp, u32 dma_sync_len) { - struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); struct fec_enet_priv_tx_q *txq; struct netdev_queue *nq; int queue, ret; - if (unlikely(!xdpf)) - return -EFAULT; - queue = fec_enet_xdp_get_tx_queue(fep, cpu); txq = fep->tx_queue[queue]; nq = netdev_get_tx_queue(fep->netdev, queue); @@ -3895,7 +3903,7 @@ static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep, /* Avoid tx timeout as XDP shares the queue with kernel stack */ txq_trans_cond_update(nq); - ret = fec_enet_txq_xmit_frame(fep, txq, xdpf, dma_sync_len, false); + ret = fec_enet_txq_xmit_frame(fep, txq, xdp, dma_sync_len, false); __netif_tx_unlock(nq); -- cgit From 939ccd107ffcade20c9c7055a2e7ae0fd724fb72 Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Tue, 15 Aug 2023 14:06:38 +0800 Subject: net: hns3: move dump regs function to a separate file The dump register function is being refactored. The first step in refactoring is put the dump regs function into a separate file. Signed-off-by: Jijie Shao Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/Makefile | 4 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 558 +------------------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 - .../ethernet/hisilicon/hns3/hns3pf/hclge_regs.c | 567 +++++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_regs.h | 17 + .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 121 +---- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + .../ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c | 127 +++++ .../ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h | 13 + 10 files changed, 731 insertions(+), 680 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index 6efea4662858..e214bfaece1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -17,11 +17,11 @@ hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o -hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o \ +hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o hns3vf/hclgevf_regs.o \ hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o obj-$(CONFIG_HNS3_HCLGE) += hclge.o -hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o \ +hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o hns3pf/hclge_regs.o \ hns3pf/hclge_mbx.o hns3pf/hclge_err.o hns3pf/hclge_debugfs.o hns3pf/hclge_ptp.o hns3pf/hclge_devlink.o \ hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 0fb2eaee3e8a..f01a7a9ee02c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -7,6 +7,7 @@ #include "hclge_debugfs.h" #include "hclge_err.h" #include "hclge_main.h" +#include "hclge_regs.h" #include "hclge_tm.h" #include "hnae3.h" diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 437b510f2b80..36e8daf49811 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -20,6 +20,7 @@ #include "hclge_main.h" #include "hclge_mbx.h" #include "hclge_mdio.h" +#include "hclge_regs.h" #include "hclge_tm.h" #include "hclge_err.h" #include "hnae3.h" @@ -40,20 +41,6 @@ #define HCLGE_PF_RESET_SYNC_TIME 20 #define HCLGE_PF_RESET_SYNC_CNT 1500 -/* Get DFX BD number offset */ -#define HCLGE_DFX_BIOS_BD_OFFSET 1 -#define HCLGE_DFX_SSU_0_BD_OFFSET 2 -#define HCLGE_DFX_SSU_1_BD_OFFSET 3 -#define HCLGE_DFX_IGU_BD_OFFSET 4 -#define HCLGE_DFX_RPU_0_BD_OFFSET 5 -#define HCLGE_DFX_RPU_1_BD_OFFSET 6 -#define HCLGE_DFX_NCSI_BD_OFFSET 7 -#define HCLGE_DFX_RTC_BD_OFFSET 8 -#define HCLGE_DFX_PPP_BD_OFFSET 9 -#define HCLGE_DFX_RCB_BD_OFFSET 10 -#define HCLGE_DFX_TQP_BD_OFFSET 11 -#define HCLGE_DFX_SSU_2_BD_OFFSET 12 - #define HCLGE_LINK_STATUS_MS 10 static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); @@ -94,62 +81,6 @@ static const struct pci_device_id ae_algo_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl); -static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CSQ_DEPTH_REG, - HCLGE_COMM_NIC_CSQ_TAIL_REG, - HCLGE_COMM_NIC_CSQ_HEAD_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CRQ_DEPTH_REG, - HCLGE_COMM_NIC_CRQ_TAIL_REG, - HCLGE_COMM_NIC_CRQ_HEAD_REG, - HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, - HCLGE_COMM_CMDQ_INTR_STS_REG, - HCLGE_COMM_CMDQ_INTR_EN_REG, - HCLGE_COMM_CMDQ_INTR_GEN_REG}; - -static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE, - HCLGE_PF_OTHER_INT_REG, - HCLGE_MISC_RESET_STS_REG, - HCLGE_MISC_VECTOR_INT_STS, - HCLGE_GLOBAL_RESET_REG, - HCLGE_FUN_RST_ING, - HCLGE_GRO_EN_REG}; - -static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG, - HCLGE_RING_RX_ADDR_H_REG, - HCLGE_RING_RX_BD_NUM_REG, - HCLGE_RING_RX_BD_LENGTH_REG, - HCLGE_RING_RX_MERGE_EN_REG, - HCLGE_RING_RX_TAIL_REG, - HCLGE_RING_RX_HEAD_REG, - HCLGE_RING_RX_FBD_NUM_REG, - HCLGE_RING_RX_OFFSET_REG, - HCLGE_RING_RX_FBD_OFFSET_REG, - HCLGE_RING_RX_STASH_REG, - HCLGE_RING_RX_BD_ERR_REG, - HCLGE_RING_TX_ADDR_L_REG, - HCLGE_RING_TX_ADDR_H_REG, - HCLGE_RING_TX_BD_NUM_REG, - HCLGE_RING_TX_PRIORITY_REG, - HCLGE_RING_TX_TC_REG, - HCLGE_RING_TX_MERGE_EN_REG, - HCLGE_RING_TX_TAIL_REG, - HCLGE_RING_TX_HEAD_REG, - HCLGE_RING_TX_FBD_NUM_REG, - HCLGE_RING_TX_OFFSET_REG, - HCLGE_RING_TX_EBD_NUM_REG, - HCLGE_RING_TX_EBD_OFFSET_REG, - HCLGE_RING_TX_BD_ERR_REG, - HCLGE_RING_EN_REG}; - -static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG, - HCLGE_TQP_INTR_GL0_REG, - HCLGE_TQP_INTR_GL1_REG, - HCLGE_TQP_INTR_GL2_REG, - HCLGE_TQP_INTR_RL_REG}; - static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = { "External Loopback test", "App Loopback test", @@ -375,36 +306,6 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = { }, }; -static const u32 hclge_dfx_bd_offset_list[] = { - HCLGE_DFX_BIOS_BD_OFFSET, - HCLGE_DFX_SSU_0_BD_OFFSET, - HCLGE_DFX_SSU_1_BD_OFFSET, - HCLGE_DFX_IGU_BD_OFFSET, - HCLGE_DFX_RPU_0_BD_OFFSET, - HCLGE_DFX_RPU_1_BD_OFFSET, - HCLGE_DFX_NCSI_BD_OFFSET, - HCLGE_DFX_RTC_BD_OFFSET, - HCLGE_DFX_PPP_BD_OFFSET, - HCLGE_DFX_RCB_BD_OFFSET, - HCLGE_DFX_TQP_BD_OFFSET, - HCLGE_DFX_SSU_2_BD_OFFSET -}; - -static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { - HCLGE_OPC_DFX_BIOS_COMMON_REG, - HCLGE_OPC_DFX_SSU_REG_0, - HCLGE_OPC_DFX_SSU_REG_1, - HCLGE_OPC_DFX_IGU_EGU_REG, - HCLGE_OPC_DFX_RPU_REG_0, - HCLGE_OPC_DFX_RPU_REG_1, - HCLGE_OPC_DFX_NCSI_REG, - HCLGE_OPC_DFX_RTC_REG, - HCLGE_OPC_DFX_PPP_REG, - HCLGE_OPC_DFX_RCB_REG, - HCLGE_OPC_DFX_TQP_REG, - HCLGE_OPC_DFX_SSU_REG_2 -}; - static const struct key_info meta_data_key_info[] = { { PACKET_TYPE_ID, 6 }, { IP_FRAGEMENT, 1 }, @@ -12383,463 +12284,6 @@ out: return ret; } -static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit, - u32 *regs_num_64_bit) -{ - struct hclge_desc desc; - u32 total_num; - int ret; - - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query register number cmd failed, ret = %d.\n", ret); - return ret; - } - - *regs_num_32_bit = le32_to_cpu(desc.data[0]); - *regs_num_64_bit = le32_to_cpu(desc.data[1]); - - total_num = *regs_num_32_bit + *regs_num_64_bit; - if (!total_num) - return -EINVAL; - - return 0; -} - -static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num, - void *data) -{ -#define HCLGE_32_BIT_REG_RTN_DATANUM 8 -#define HCLGE_32_BIT_DESC_NODATA_LEN 2 - - struct hclge_desc *desc; - u32 *reg_val = data; - __le32 *desc_data; - int nodata_num; - int cmd_num; - int i, k, n; - int ret; - - if (regs_num == 0) - return 0; - - nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN; - cmd_num = DIV_ROUND_UP(regs_num + nodata_num, - HCLGE_32_BIT_REG_RTN_DATANUM); - desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; - - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true); - ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query 32 bit register cmd failed, ret = %d.\n", ret); - kfree(desc); - return ret; - } - - for (i = 0; i < cmd_num; i++) { - if (i == 0) { - desc_data = (__le32 *)(&desc[i].data[0]); - n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num; - } else { - desc_data = (__le32 *)(&desc[i]); - n = HCLGE_32_BIT_REG_RTN_DATANUM; - } - for (k = 0; k < n; k++) { - *reg_val++ = le32_to_cpu(*desc_data++); - - regs_num--; - if (!regs_num) - break; - } - } - - kfree(desc); - return 0; -} - -static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, - void *data) -{ -#define HCLGE_64_BIT_REG_RTN_DATANUM 4 -#define HCLGE_64_BIT_DESC_NODATA_LEN 1 - - struct hclge_desc *desc; - u64 *reg_val = data; - __le64 *desc_data; - int nodata_len; - int cmd_num; - int i, k, n; - int ret; - - if (regs_num == 0) - return 0; - - nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN; - cmd_num = DIV_ROUND_UP(regs_num + nodata_len, - HCLGE_64_BIT_REG_RTN_DATANUM); - desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; - - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true); - ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query 64 bit register cmd failed, ret = %d.\n", ret); - kfree(desc); - return ret; - } - - for (i = 0; i < cmd_num; i++) { - if (i == 0) { - desc_data = (__le64 *)(&desc[i].data[0]); - n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len; - } else { - desc_data = (__le64 *)(&desc[i]); - n = HCLGE_64_BIT_REG_RTN_DATANUM; - } - for (k = 0; k < n; k++) { - *reg_val++ = le64_to_cpu(*desc_data++); - - regs_num--; - if (!regs_num) - break; - } - } - - kfree(desc); - return 0; -} - -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) -#define REG_SEPARATOR_LINE 1 -#define REG_NUM_REMAIN_MASK 3 - -int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) -{ - int i; - - /* initialize command BD except the last one */ - for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) { - hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, - true); - desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); - } - - /* initialize the last command BD */ - hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true); - - return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT); -} - -static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev, - int *bd_num_list, - u32 type_num) -{ - u32 entries_per_desc, desc_index, index, offset, i; - struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; - int ret; - - ret = hclge_query_bd_num_cmd_send(hdev, desc); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx bd num fail, status is %d.\n", ret); - return ret; - } - - entries_per_desc = ARRAY_SIZE(desc[0].data); - for (i = 0; i < type_num; i++) { - offset = hclge_dfx_bd_offset_list[i]; - index = offset % entries_per_desc; - desc_index = offset / entries_per_desc; - bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]); - } - - return ret; -} - -static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, - struct hclge_desc *desc_src, int bd_num, - enum hclge_opcode_type cmd) -{ - struct hclge_desc *desc = desc_src; - int i, ret; - - hclge_cmd_setup_basic_desc(desc, cmd, true); - for (i = 0; i < bd_num - 1; i++) { - desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); - desc++; - hclge_cmd_setup_basic_desc(desc, cmd, true); - } - - desc = desc_src; - ret = hclge_cmd_send(&hdev->hw, desc, bd_num); - if (ret) - dev_err(&hdev->pdev->dev, - "Query dfx reg cmd(0x%x) send fail, status is %d.\n", - cmd, ret); - - return ret; -} - -static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, - void *data) -{ - int entries_per_desc, reg_num, separator_num, desc_index, index, i; - struct hclge_desc *desc = desc_src; - u32 *reg = data; - - entries_per_desc = ARRAY_SIZE(desc->data); - reg_num = entries_per_desc * bd_num; - separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) { - index = i % entries_per_desc; - desc_index = i / entries_per_desc; - *reg++ = le32_to_cpu(desc[desc_index].data[index]); - } - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - return reg_num + separator_num; -} - -static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) -{ - u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); - int data_len_per_desc, bd_num, i; - int *bd_num_list; - u32 data_len; - int ret; - - bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); - if (!bd_num_list) - return -ENOMEM; - - ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg bd num fail, status is %d.\n", ret); - goto out; - } - - data_len_per_desc = sizeof_field(struct hclge_desc, data); - *len = 0; - for (i = 0; i < dfx_reg_type_num; i++) { - bd_num = bd_num_list[i]; - data_len = data_len_per_desc * bd_num; - *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; - } - -out: - kfree(bd_num_list); - return ret; -} - -static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) -{ - u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); - int bd_num, bd_num_max, buf_len, i; - struct hclge_desc *desc_src; - int *bd_num_list; - u32 *reg = data; - int ret; - - bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); - if (!bd_num_list) - return -ENOMEM; - - ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg bd num fail, status is %d.\n", ret); - goto out; - } - - bd_num_max = bd_num_list[0]; - for (i = 1; i < dfx_reg_type_num; i++) - bd_num_max = max_t(int, bd_num_max, bd_num_list[i]); - - buf_len = sizeof(*desc_src) * bd_num_max; - desc_src = kzalloc(buf_len, GFP_KERNEL); - if (!desc_src) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < dfx_reg_type_num; i++) { - bd_num = bd_num_list[i]; - ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num, - hclge_dfx_reg_opcode_list[i]); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg fail, status is %d.\n", ret); - break; - } - - reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); - } - - kfree(desc_src); -out: - kfree(bd_num_list); - return ret; -} - -static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, - struct hnae3_knic_private_info *kinfo) -{ -#define HCLGE_RING_REG_OFFSET 0x200 -#define HCLGE_RING_INT_REG_OFFSET 0x4 - - int i, j, reg_num, separator_num; - int data_num_sum; - u32 *reg = data; - - /* fetching per-PF registers valus from PF PCIe register space */ - reg_num = ARRAY_SIZE(cmdq_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum = reg_num + separator_num; - - reg_num = ARRAY_SIZE(common_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum += reg_num + separator_num; - - reg_num = ARRAY_SIZE(ring_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (j = 0; j < kinfo->num_tqps; j++) { - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGE_RING_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - data_num_sum += (reg_num + separator_num) * kinfo->num_tqps; - - reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (j = 0; j < hdev->num_msi_used - 1; j++) { - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, - tqp_intr_reg_addr_list[i] + - HCLGE_RING_INT_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1); - - return data_num_sum; -} - -static int hclge_get_regs_len(struct hnae3_handle *handle) -{ - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; - int regs_lines_32_bit, regs_lines_64_bit; - int ret; - - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return ret; - } - - ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg len failed, ret = %d.\n", ret); - return ret; - } - - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - - return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit + - regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len; -} - -static void hclge_get_regs(struct hnae3_handle *handle, u32 *version, - void *data) -{ - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - u32 regs_num_32_bit, regs_num_64_bit; - int i, reg_num, separator_num, ret; - u32 *reg = data; - - *version = hdev->fw_version; - - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return; - } - - reg += hclge_fetch_pf_reg(hdev, reg, kinfo); - - ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get 32 bit register failed, ret = %d.\n", ret); - return; - } - reg_num = regs_num_32_bit; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get 64 bit register failed, ret = %d.\n", ret); - return; - } - reg_num = regs_num_64_bit * 2; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - ret = hclge_get_dfx_reg(hdev, reg); - if (ret) - dev_err(&hdev->pdev->dev, - "Get dfx register failed, ret = %d.\n", ret); -} - static int hclge_set_led_status(struct hclge_dev *hdev, u8 locate_led_status) { struct hclge_set_led_state_cmd *req; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 70b059e6d35f..ec233ec57222 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1142,8 +1142,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, u16 state, struct hclge_vlan_info *vlan_info); void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time); -int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, - struct hclge_desc *desc); void hclge_report_hw_error(struct hclge_dev *hdev, enum hnae3_hw_error_type type); int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c new file mode 100644 index 000000000000..e56644394875 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c @@ -0,0 +1,567 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hclge_cmd.h" +#include "hclge_main.h" +#include "hclge_regs.h" +#include "hnae3.h" + +static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CSQ_DEPTH_REG, + HCLGE_COMM_NIC_CSQ_TAIL_REG, + HCLGE_COMM_NIC_CSQ_HEAD_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CRQ_DEPTH_REG, + HCLGE_COMM_NIC_CRQ_TAIL_REG, + HCLGE_COMM_NIC_CRQ_HEAD_REG, + HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, + HCLGE_COMM_CMDQ_INTR_STS_REG, + HCLGE_COMM_CMDQ_INTR_EN_REG, + HCLGE_COMM_CMDQ_INTR_GEN_REG}; + +static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE, + HCLGE_PF_OTHER_INT_REG, + HCLGE_MISC_RESET_STS_REG, + HCLGE_MISC_VECTOR_INT_STS, + HCLGE_GLOBAL_RESET_REG, + HCLGE_FUN_RST_ING, + HCLGE_GRO_EN_REG}; + +static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG, + HCLGE_RING_RX_ADDR_H_REG, + HCLGE_RING_RX_BD_NUM_REG, + HCLGE_RING_RX_BD_LENGTH_REG, + HCLGE_RING_RX_MERGE_EN_REG, + HCLGE_RING_RX_TAIL_REG, + HCLGE_RING_RX_HEAD_REG, + HCLGE_RING_RX_FBD_NUM_REG, + HCLGE_RING_RX_OFFSET_REG, + HCLGE_RING_RX_FBD_OFFSET_REG, + HCLGE_RING_RX_STASH_REG, + HCLGE_RING_RX_BD_ERR_REG, + HCLGE_RING_TX_ADDR_L_REG, + HCLGE_RING_TX_ADDR_H_REG, + HCLGE_RING_TX_BD_NUM_REG, + HCLGE_RING_TX_PRIORITY_REG, + HCLGE_RING_TX_TC_REG, + HCLGE_RING_TX_MERGE_EN_REG, + HCLGE_RING_TX_TAIL_REG, + HCLGE_RING_TX_HEAD_REG, + HCLGE_RING_TX_FBD_NUM_REG, + HCLGE_RING_TX_OFFSET_REG, + HCLGE_RING_TX_EBD_NUM_REG, + HCLGE_RING_TX_EBD_OFFSET_REG, + HCLGE_RING_TX_BD_ERR_REG, + HCLGE_RING_EN_REG}; + +static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG, + HCLGE_TQP_INTR_GL0_REG, + HCLGE_TQP_INTR_GL1_REG, + HCLGE_TQP_INTR_GL2_REG, + HCLGE_TQP_INTR_RL_REG}; + +/* Get DFX BD number offset */ +#define HCLGE_DFX_BIOS_BD_OFFSET 1 +#define HCLGE_DFX_SSU_0_BD_OFFSET 2 +#define HCLGE_DFX_SSU_1_BD_OFFSET 3 +#define HCLGE_DFX_IGU_BD_OFFSET 4 +#define HCLGE_DFX_RPU_0_BD_OFFSET 5 +#define HCLGE_DFX_RPU_1_BD_OFFSET 6 +#define HCLGE_DFX_NCSI_BD_OFFSET 7 +#define HCLGE_DFX_RTC_BD_OFFSET 8 +#define HCLGE_DFX_PPP_BD_OFFSET 9 +#define HCLGE_DFX_RCB_BD_OFFSET 10 +#define HCLGE_DFX_TQP_BD_OFFSET 11 +#define HCLGE_DFX_SSU_2_BD_OFFSET 12 + +static const u32 hclge_dfx_bd_offset_list[] = { + HCLGE_DFX_BIOS_BD_OFFSET, + HCLGE_DFX_SSU_0_BD_OFFSET, + HCLGE_DFX_SSU_1_BD_OFFSET, + HCLGE_DFX_IGU_BD_OFFSET, + HCLGE_DFX_RPU_0_BD_OFFSET, + HCLGE_DFX_RPU_1_BD_OFFSET, + HCLGE_DFX_NCSI_BD_OFFSET, + HCLGE_DFX_RTC_BD_OFFSET, + HCLGE_DFX_PPP_BD_OFFSET, + HCLGE_DFX_RCB_BD_OFFSET, + HCLGE_DFX_TQP_BD_OFFSET, + HCLGE_DFX_SSU_2_BD_OFFSET +}; + +static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { + HCLGE_OPC_DFX_BIOS_COMMON_REG, + HCLGE_OPC_DFX_SSU_REG_0, + HCLGE_OPC_DFX_SSU_REG_1, + HCLGE_OPC_DFX_IGU_EGU_REG, + HCLGE_OPC_DFX_RPU_REG_0, + HCLGE_OPC_DFX_RPU_REG_1, + HCLGE_OPC_DFX_NCSI_REG, + HCLGE_OPC_DFX_RTC_REG, + HCLGE_OPC_DFX_PPP_REG, + HCLGE_OPC_DFX_RCB_REG, + HCLGE_OPC_DFX_TQP_REG, + HCLGE_OPC_DFX_SSU_REG_2 +}; + +#define MAX_SEPARATE_NUM 4 +#define SEPARATOR_VALUE 0xFDFCFBFA +#define REG_NUM_PER_LINE 4 +#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) +#define REG_SEPARATOR_LINE 1 +#define REG_NUM_REMAIN_MASK 3 + +static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num, + void *data) +{ +#define HCLGE_32_BIT_REG_RTN_DATANUM 8 +#define HCLGE_32_BIT_DESC_NODATA_LEN 2 + + struct hclge_desc *desc; + u32 *reg_val = data; + __le32 *desc_data; + int nodata_num; + int cmd_num; + int i, k, n; + int ret; + + if (regs_num == 0) + return 0; + + nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN; + cmd_num = DIV_ROUND_UP(regs_num + nodata_num, + HCLGE_32_BIT_REG_RTN_DATANUM); + desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true); + ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query 32 bit register cmd failed, ret = %d.\n", ret); + kfree(desc); + return ret; + } + + for (i = 0; i < cmd_num; i++) { + if (i == 0) { + desc_data = (__le32 *)(&desc[i].data[0]); + n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num; + } else { + desc_data = (__le32 *)(&desc[i]); + n = HCLGE_32_BIT_REG_RTN_DATANUM; + } + for (k = 0; k < n; k++) { + *reg_val++ = le32_to_cpu(*desc_data++); + + regs_num--; + if (!regs_num) + break; + } + } + + kfree(desc); + return 0; +} + +static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, + void *data) +{ +#define HCLGE_64_BIT_REG_RTN_DATANUM 4 +#define HCLGE_64_BIT_DESC_NODATA_LEN 1 + + struct hclge_desc *desc; + u64 *reg_val = data; + __le64 *desc_data; + int nodata_len; + int cmd_num; + int i, k, n; + int ret; + + if (regs_num == 0) + return 0; + + nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN; + cmd_num = DIV_ROUND_UP(regs_num + nodata_len, + HCLGE_64_BIT_REG_RTN_DATANUM); + desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true); + ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query 64 bit register cmd failed, ret = %d.\n", ret); + kfree(desc); + return ret; + } + + for (i = 0; i < cmd_num; i++) { + if (i == 0) { + desc_data = (__le64 *)(&desc[i].data[0]); + n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len; + } else { + desc_data = (__le64 *)(&desc[i]); + n = HCLGE_64_BIT_REG_RTN_DATANUM; + } + for (k = 0; k < n; k++) { + *reg_val++ = le64_to_cpu(*desc_data++); + + regs_num--; + if (!regs_num) + break; + } + } + + kfree(desc); + return 0; +} + +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) +{ + int i; + + /* initialize command BD except the last one */ + for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) { + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, + true); + desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + } + + /* initialize the last command BD */ + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true); + + return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT); +} + +static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev, + int *bd_num_list, + u32 type_num) +{ + u32 entries_per_desc, desc_index, index, offset, i; + struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; + int ret; + + ret = hclge_query_bd_num_cmd_send(hdev, desc); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx bd num fail, status is %d.\n", ret); + return ret; + } + + entries_per_desc = ARRAY_SIZE(desc[0].data); + for (i = 0; i < type_num; i++) { + offset = hclge_dfx_bd_offset_list[i]; + index = offset % entries_per_desc; + desc_index = offset / entries_per_desc; + bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]); + } + + return ret; +} + +static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc_src, int bd_num, + enum hclge_opcode_type cmd) +{ + struct hclge_desc *desc = desc_src; + int i, ret; + + hclge_cmd_setup_basic_desc(desc, cmd, true); + for (i = 0; i < bd_num - 1; i++) { + desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + desc++; + hclge_cmd_setup_basic_desc(desc, cmd, true); + } + + desc = desc_src; + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(&hdev->pdev->dev, + "Query dfx reg cmd(0x%x) send fail, status is %d.\n", + cmd, ret); + + return ret; +} + +static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, + void *data) +{ + int entries_per_desc, reg_num, separator_num, desc_index, index, i; + struct hclge_desc *desc = desc_src; + u32 *reg = data; + + entries_per_desc = ARRAY_SIZE(desc->data); + reg_num = entries_per_desc * bd_num; + separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) { + index = i % entries_per_desc; + desc_index = i / entries_per_desc; + *reg++ = le32_to_cpu(desc[desc_index].data[index]); + } + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + return reg_num + separator_num; +} + +static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int data_len_per_desc, bd_num; + int *bd_num_list; + u32 data_len, i; + int ret; + + bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); + goto out; + } + + data_len_per_desc = sizeof_field(struct hclge_desc, data); + *len = 0; + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; + data_len = data_len_per_desc * bd_num; + *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; + } + +out: + kfree(bd_num_list); + return ret; +} + +static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int bd_num, bd_num_max, buf_len; + struct hclge_desc *desc_src; + int *bd_num_list; + u32 *reg = data; + int ret; + u32 i; + + bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); + goto out; + } + + bd_num_max = bd_num_list[0]; + for (i = 1; i < dfx_reg_type_num; i++) + bd_num_max = max_t(int, bd_num_max, bd_num_list[i]); + + buf_len = sizeof(*desc_src) * bd_num_max; + desc_src = kzalloc(buf_len, GFP_KERNEL); + if (!desc_src) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; + ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num, + hclge_dfx_reg_opcode_list[i]); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg fail, status is %d.\n", ret); + break; + } + + reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); + } + + kfree(desc_src); +out: + kfree(bd_num_list); + return ret; +} + +static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, + struct hnae3_knic_private_info *kinfo) +{ +#define HCLGE_RING_REG_OFFSET 0x200 +#define HCLGE_RING_INT_REG_OFFSET 0x4 + + int i, j, reg_num, separator_num; + int data_num_sum; + u32 *reg = data; + + /* fetching per-PF registers valus from PF PCIe register space */ + reg_num = ARRAY_SIZE(cmdq_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + data_num_sum = reg_num + separator_num; + + reg_num = ARRAY_SIZE(common_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + data_num_sum += reg_num + separator_num; + + reg_num = ARRAY_SIZE(ring_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (j = 0; j < kinfo->num_tqps; j++) { + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, + ring_reg_addr_list[i] + + HCLGE_RING_REG_OFFSET * j); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + } + data_num_sum += (reg_num + separator_num) * kinfo->num_tqps; + + reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (j = 0; j < hdev->num_msi_used - 1; j++) { + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, + tqp_intr_reg_addr_list[i] + + HCLGE_RING_INT_REG_OFFSET * j); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + } + data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1); + + return data_num_sum; +} + +static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit, + u32 *regs_num_64_bit) +{ + struct hclge_desc desc; + u32 total_num; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query register number cmd failed, ret = %d.\n", ret); + return ret; + } + + *regs_num_32_bit = le32_to_cpu(desc.data[0]); + *regs_num_64_bit = le32_to_cpu(desc.data[1]); + + total_num = *regs_num_32_bit + *regs_num_64_bit; + if (!total_num) + return -EINVAL; + + return 0; +} + +int hclge_get_regs_len(struct hnae3_handle *handle) +{ + int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; + int regs_lines_32_bit, regs_lines_64_bit; + int ret; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return ret; + } + + ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg len failed, ret = %d.\n", ret); + return ret; + } + + cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE + + REG_SEPARATOR_LINE; + + return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + + tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit + + regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len; +} + +void hclge_get_regs(struct hnae3_handle *handle, u32 *version, + void *data) +{ +#define HCLGE_REG_64_BIT_SPACE_MULTIPLE 2 + + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + u32 regs_num_32_bit, regs_num_64_bit; + int i, reg_num, separator_num, ret; + u32 *reg = data; + + *version = hdev->fw_version; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return; + } + + reg += hclge_fetch_pf_reg(hdev, reg, kinfo); + + ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get 32 bit register failed, ret = %d.\n", ret); + return; + } + reg_num = regs_num_32_bit; + reg += reg_num; + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get 64 bit register failed, ret = %d.\n", ret); + return; + } + reg_num = regs_num_64_bit * HCLGE_REG_64_BIT_SPACE_MULTIPLE; + reg += reg_num; + separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + ret = hclge_get_dfx_reg(hdev, reg); + if (ret) + dev_err(&hdev->pdev->dev, + "Get dfx register failed, ret = %d.\n", ret); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h new file mode 100644 index 000000000000..b6bc1ecb8054 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2023 Hisilicon Limited. + +#ifndef __HCLGE_REGS_H +#define __HCLGE_REGS_H +#include +#include "hclge_comm_cmd.h" + +struct hnae3_handle; +struct hclge_dev; + +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc); +int hclge_get_regs_len(struct hnae3_handle *handle); +void hclge_get_regs(struct hnae3_handle *handle, u32 *version, + void *data); +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 34f02ca8d1d2..7a2f9233d695 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -6,6 +6,7 @@ #include #include "hclgevf_cmd.h" #include "hclgevf_main.h" +#include "hclgevf_regs.h" #include "hclge_mbx.h" #include "hnae3.h" #include "hclgevf_devlink.h" @@ -33,58 +34,6 @@ static const struct pci_device_id ae_algovf_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl); -static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CSQ_DEPTH_REG, - HCLGE_COMM_NIC_CSQ_TAIL_REG, - HCLGE_COMM_NIC_CSQ_HEAD_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CRQ_DEPTH_REG, - HCLGE_COMM_NIC_CRQ_TAIL_REG, - HCLGE_COMM_NIC_CRQ_HEAD_REG, - HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, - HCLGE_COMM_VECTOR0_CMDQ_STATE_REG, - HCLGE_COMM_CMDQ_INTR_EN_REG, - HCLGE_COMM_CMDQ_INTR_GEN_REG}; - -static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE, - HCLGEVF_RST_ING, - HCLGEVF_GRO_EN_REG}; - -static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG, - HCLGEVF_RING_RX_ADDR_H_REG, - HCLGEVF_RING_RX_BD_NUM_REG, - HCLGEVF_RING_RX_BD_LENGTH_REG, - HCLGEVF_RING_RX_MERGE_EN_REG, - HCLGEVF_RING_RX_TAIL_REG, - HCLGEVF_RING_RX_HEAD_REG, - HCLGEVF_RING_RX_FBD_NUM_REG, - HCLGEVF_RING_RX_OFFSET_REG, - HCLGEVF_RING_RX_FBD_OFFSET_REG, - HCLGEVF_RING_RX_STASH_REG, - HCLGEVF_RING_RX_BD_ERR_REG, - HCLGEVF_RING_TX_ADDR_L_REG, - HCLGEVF_RING_TX_ADDR_H_REG, - HCLGEVF_RING_TX_BD_NUM_REG, - HCLGEVF_RING_TX_PRIORITY_REG, - HCLGEVF_RING_TX_TC_REG, - HCLGEVF_RING_TX_MERGE_EN_REG, - HCLGEVF_RING_TX_TAIL_REG, - HCLGEVF_RING_TX_HEAD_REG, - HCLGEVF_RING_TX_FBD_NUM_REG, - HCLGEVF_RING_TX_OFFSET_REG, - HCLGEVF_RING_TX_EBD_NUM_REG, - HCLGEVF_RING_TX_EBD_OFFSET_REG, - HCLGEVF_RING_TX_BD_ERR_REG, - HCLGEVF_RING_EN_REG}; - -static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, - HCLGEVF_TQP_INTR_GL0_REG, - HCLGEVF_TQP_INTR_GL1_REG, - HCLGEVF_TQP_INTR_GL2_REG, - HCLGEVF_TQP_INTR_RL_REG}; - /* hclgevf_cmd_send - send command to command queue * @hw: pointer to the hw struct * @desc: prefilled descriptor for describing the command @@ -111,7 +60,7 @@ void hclgevf_arq_init(struct hclgevf_dev *hdev) spin_unlock(&cmdq->crq.lock); } -static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle) +struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle) { if (!handle->client) return container_of(handle, struct hclgevf_dev, nic); @@ -3258,72 +3207,6 @@ static void hclgevf_get_link_mode(struct hnae3_handle *handle, *advertising = hdev->hw.mac.advertising; } -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) - -static int hclgevf_get_regs_len(struct hnae3_handle *handle) -{ - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1; - - return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE; -} - -static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, - void *data) -{ - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - int i, j, reg_um, separator_num; - u32 *reg = data; - - *version = hdev->fw_version; - - /* fetching per-VF registers values from VF PCIe register space */ - reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - reg_um = sizeof(common_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (j = 0; j < hdev->num_tqps; j++) { - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGEVF_TQP_REG_SIZE * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - - reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (j = 0; j < hdev->num_msi_used - 1; j++) { - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, - tqp_intr_reg_addr_list[i] + - 4 * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } -} - void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, struct hclge_mbx_port_base_vlan *port_base_vlan) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 59ca6c794d6d..81c16b8c8da2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -294,4 +294,5 @@ void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev); void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev); void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, struct hclge_mbx_port_base_vlan *port_base_vlan); +struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c new file mode 100644 index 000000000000..197ab733306b --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hclgevf_main.h" +#include "hclgevf_regs.h" +#include "hnae3.h" + +static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CSQ_DEPTH_REG, + HCLGE_COMM_NIC_CSQ_TAIL_REG, + HCLGE_COMM_NIC_CSQ_HEAD_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CRQ_DEPTH_REG, + HCLGE_COMM_NIC_CRQ_TAIL_REG, + HCLGE_COMM_NIC_CRQ_HEAD_REG, + HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, + HCLGE_COMM_VECTOR0_CMDQ_STATE_REG, + HCLGE_COMM_CMDQ_INTR_EN_REG, + HCLGE_COMM_CMDQ_INTR_GEN_REG}; + +static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE, + HCLGEVF_RST_ING, + HCLGEVF_GRO_EN_REG}; + +static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG, + HCLGEVF_RING_RX_ADDR_H_REG, + HCLGEVF_RING_RX_BD_NUM_REG, + HCLGEVF_RING_RX_BD_LENGTH_REG, + HCLGEVF_RING_RX_MERGE_EN_REG, + HCLGEVF_RING_RX_TAIL_REG, + HCLGEVF_RING_RX_HEAD_REG, + HCLGEVF_RING_RX_FBD_NUM_REG, + HCLGEVF_RING_RX_OFFSET_REG, + HCLGEVF_RING_RX_FBD_OFFSET_REG, + HCLGEVF_RING_RX_STASH_REG, + HCLGEVF_RING_RX_BD_ERR_REG, + HCLGEVF_RING_TX_ADDR_L_REG, + HCLGEVF_RING_TX_ADDR_H_REG, + HCLGEVF_RING_TX_BD_NUM_REG, + HCLGEVF_RING_TX_PRIORITY_REG, + HCLGEVF_RING_TX_TC_REG, + HCLGEVF_RING_TX_MERGE_EN_REG, + HCLGEVF_RING_TX_TAIL_REG, + HCLGEVF_RING_TX_HEAD_REG, + HCLGEVF_RING_TX_FBD_NUM_REG, + HCLGEVF_RING_TX_OFFSET_REG, + HCLGEVF_RING_TX_EBD_NUM_REG, + HCLGEVF_RING_TX_EBD_OFFSET_REG, + HCLGEVF_RING_TX_BD_ERR_REG, + HCLGEVF_RING_EN_REG}; + +static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, + HCLGEVF_TQP_INTR_GL0_REG, + HCLGEVF_TQP_INTR_GL1_REG, + HCLGEVF_TQP_INTR_GL2_REG, + HCLGEVF_TQP_INTR_RL_REG}; + +#define MAX_SEPARATE_NUM 4 +#define SEPARATOR_VALUE 0xFDFCFBFA +#define REG_NUM_PER_LINE 4 +#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) + +int hclgevf_get_regs_len(struct hnae3_handle *handle) +{ + int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + + cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1; + common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1; + ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1; + tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1; + + return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps + + tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE; +} + +void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, + void *data) +{ +#define HCLGEVF_RING_REG_OFFSET 0x200 +#define HCLGEVF_RING_INT_REG_OFFSET 0x4 + + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int i, j, reg_um, separator_num; + u32 *reg = data; + + *version = hdev->fw_version; + + /* fetching per-VF registers values from VF PCIe register space */ + reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); + separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + reg_um = sizeof(common_reg_addr_list) / sizeof(u32); + separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + + reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); + separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + for (j = 0; j < hdev->num_tqps; j++) { + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, + ring_reg_addr_list[i] + + HCLGEVF_RING_REG_OFFSET * j); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + } + + reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); + separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + for (j = 0; j < hdev->num_msi_used - 1; j++) { + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, + tqp_intr_reg_addr_list[i] + + HCLGEVF_RING_INT_REG_OFFSET * j); + for (i = 0; i < separator_num; i++) + *reg++ = SEPARATOR_VALUE; + } +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h new file mode 100644 index 000000000000..77bdcf60a1af --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2023 Hisilicon Limited. */ + +#ifndef __HCLGEVF_REGS_H +#define __HCLGEVF_REGS_H +#include + +struct hnae3_handle; + +int hclgevf_get_regs_len(struct hnae3_handle *handle); +void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, + void *data); +#endif -- cgit From d8634b7c3f62d265fc2ecf29286aa9c5b78f969f Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Tue, 15 Aug 2023 14:06:39 +0800 Subject: net: hns3: Support tlv in regs data for HNS3 PF driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dump register function is being refactored. The second step in refactoring is to support tlv info in regs data for HNS3 PF driver. Currently, if we use "ethtool -d" to dump regs value, the output is as follows: offset1: 00 01 02 03 04 05 ... offset2:10 11 12 13 14 15 ... ...... We can't get the value of a register directly. This patch deletes the original separator information and add tag_len_value information in regs data. ethtool can parse register data in key-value format by -d command. a patch will be added to the ethtool to parse regs data in the following format: reg1 : value2 reg2 : value2 ...... Signed-off-by: Jijie Shao Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_regs.c | 167 +++++++++++++-------- 1 file changed, 102 insertions(+), 65 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c index e56644394875..734e5f757b9c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c @@ -106,12 +106,66 @@ static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { HCLGE_OPC_DFX_SSU_REG_2 }; -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) -#define REG_SEPARATOR_LINE 1 -#define REG_NUM_REMAIN_MASK 3 +enum hclge_reg_tag { + HCLGE_REG_TAG_CMDQ = 0, + HCLGE_REG_TAG_COMMON, + HCLGE_REG_TAG_RING, + HCLGE_REG_TAG_TQP_INTR, + HCLGE_REG_TAG_QUERY_32_BIT, + HCLGE_REG_TAG_QUERY_64_BIT, + HCLGE_REG_TAG_DFX_BIOS_COMMON, + HCLGE_REG_TAG_DFX_SSU_0, + HCLGE_REG_TAG_DFX_SSU_1, + HCLGE_REG_TAG_DFX_IGU_EGU, + HCLGE_REG_TAG_DFX_RPU_0, + HCLGE_REG_TAG_DFX_RPU_1, + HCLGE_REG_TAG_DFX_NCSI, + HCLGE_REG_TAG_DFX_RTC, + HCLGE_REG_TAG_DFX_PPP, + HCLGE_REG_TAG_DFX_RCB, + HCLGE_REG_TAG_DFX_TQP, + HCLGE_REG_TAG_DFX_SSU_2, +}; + +#pragma pack(4) +struct hclge_reg_tlv { + u16 tag; + u16 len; +}; + +struct hclge_reg_header { + u64 magic_number; + u8 is_vf; + u8 rsv[7]; +}; + +#pragma pack() + +#define HCLGE_REG_TLV_SIZE sizeof(struct hclge_reg_tlv) +#define HCLGE_REG_HEADER_SIZE sizeof(struct hclge_reg_header) +#define HCLGE_REG_TLV_SPACE (sizeof(struct hclge_reg_tlv) / sizeof(u32)) +#define HCLGE_REG_HEADER_SPACE (sizeof(struct hclge_reg_header) / sizeof(u32)) +#define HCLGE_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */ + +static u32 hclge_reg_get_header(void *data) +{ + struct hclge_reg_header *header = data; + + header->magic_number = HCLGE_REG_MAGIC_NUMBER; + header->is_vf = 0x0; + + return HCLGE_REG_HEADER_SPACE; +} + +static u32 hclge_reg_get_tlv(u32 tag, u32 regs_num, void *data) +{ + struct hclge_reg_tlv *tlv = data; + + tlv->tag = tag; + tlv->len = regs_num * sizeof(u32) + HCLGE_REG_TLV_SIZE; + + return HCLGE_REG_TLV_SPACE; +} static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num, void *data) @@ -291,31 +345,28 @@ static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, void *data) { - int entries_per_desc, reg_num, separator_num, desc_index, index, i; + int entries_per_desc, reg_num, desc_index, index, i; struct hclge_desc *desc = desc_src; u32 *reg = data; entries_per_desc = ARRAY_SIZE(desc->data); reg_num = entries_per_desc * bd_num; - separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK); for (i = 0; i < reg_num; i++) { index = i % entries_per_desc; desc_index = i / entries_per_desc; *reg++ = le32_to_cpu(desc[desc_index].data[index]); } - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - return reg_num + separator_num; + return reg_num; } static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) { u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); - int data_len_per_desc, bd_num; + int data_len_per_desc; int *bd_num_list; - u32 data_len, i; int ret; + u32 i; bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); if (!bd_num_list) @@ -330,11 +381,8 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) data_len_per_desc = sizeof_field(struct hclge_desc, data); *len = 0; - for (i = 0; i < dfx_reg_type_num; i++) { - bd_num = bd_num_list[i]; - data_len = data_len_per_desc * bd_num; - *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; - } + for (i = 0; i < dfx_reg_type_num; i++) + *len += bd_num_list[i] * data_len_per_desc + HCLGE_REG_TLV_SIZE; out: kfree(bd_num_list); @@ -383,6 +431,9 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) break; } + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_DFX_BIOS_COMMON + i, + ARRAY_SIZE(desc_src->data) * bd_num, + reg); reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); } @@ -398,50 +449,43 @@ static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, #define HCLGE_RING_REG_OFFSET 0x200 #define HCLGE_RING_INT_REG_OFFSET 0x4 - int i, j, reg_num, separator_num; + int i, j, reg_num; int data_num_sum; u32 *reg = data; /* fetching per-PF registers valus from PF PCIe register space */ reg_num = ARRAY_SIZE(cmdq_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_CMDQ, reg_num, reg); for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum = reg_num + separator_num; + data_num_sum = reg_num + HCLGE_REG_TLV_SPACE; reg_num = ARRAY_SIZE(common_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_COMMON, reg_num, reg); for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum += reg_num + separator_num; + data_num_sum += reg_num + HCLGE_REG_TLV_SPACE; reg_num = ARRAY_SIZE(ring_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); for (j = 0; j < kinfo->num_tqps; j++) { + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg); for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, ring_reg_addr_list[i] + HCLGE_RING_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; } - data_num_sum += (reg_num + separator_num) * kinfo->num_tqps; + data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps; reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); for (j = 0; j < hdev->num_msi_used - 1; j++) { + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_TQP_INTR, reg_num, reg); for (i = 0; i < reg_num; i++) *reg++ = hclge_read_dev(&hdev->hw, tqp_intr_reg_addr_list[i] + HCLGE_RING_INT_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; } - data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1); + data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * + (hdev->num_msi_used - 1); return data_num_sum; } @@ -473,12 +517,12 @@ static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit, int hclge_get_regs_len(struct hnae3_handle *handle) { - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; struct hnae3_knic_private_info *kinfo = &handle->kinfo; struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; - int regs_lines_32_bit, regs_lines_64_bit; + int cmdq_len, common_len, ring_len, tqp_intr_len; + int regs_len_32_bit, regs_len_64_bit; + struct hclge_dev *hdev = vport->back; int ret; ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); @@ -495,22 +539,17 @@ int hclge_get_regs_len(struct hnae3_handle *handle) return ret; } - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - - return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit + - regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len; + cmdq_len = HCLGE_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list); + common_len = HCLGE_REG_TLV_SIZE + sizeof(common_reg_addr_list); + ring_len = HCLGE_REG_TLV_SIZE + sizeof(ring_reg_addr_list); + tqp_intr_len = HCLGE_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list); + regs_len_32_bit = HCLGE_REG_TLV_SIZE + regs_num_32_bit * sizeof(u32); + regs_len_64_bit = HCLGE_REG_TLV_SIZE + regs_num_64_bit * sizeof(u64); + + /* return the total length of all register values */ + return HCLGE_REG_HEADER_SIZE + cmdq_len + common_len + ring_len * + kinfo->num_tqps + tqp_intr_len * (hdev->num_msi_used - 1) + + regs_len_32_bit + regs_len_64_bit + dfx_regs_len; } void hclge_get_regs(struct hnae3_handle *handle, u32 *version, @@ -522,8 +561,8 @@ void hclge_get_regs(struct hnae3_handle *handle, u32 *version, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; u32 regs_num_32_bit, regs_num_64_bit; - int i, reg_num, separator_num, ret; u32 *reg = data; + int ret; *version = hdev->fw_version; @@ -534,31 +573,29 @@ void hclge_get_regs(struct hnae3_handle *handle, u32 *version, return; } + reg += hclge_reg_get_header(reg); reg += hclge_fetch_pf_reg(hdev, reg, kinfo); + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_32_BIT, + regs_num_32_bit, reg); ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); if (ret) { dev_err(&hdev->pdev->dev, "Get 32 bit register failed, ret = %d.\n", ret); return; } - reg_num = regs_num_32_bit; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; + reg += regs_num_32_bit; + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_64_BIT, + regs_num_64_bit * + HCLGE_REG_64_BIT_SPACE_MULTIPLE, reg); ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); if (ret) { dev_err(&hdev->pdev->dev, "Get 64 bit register failed, ret = %d.\n", ret); return; } - reg_num = regs_num_64_bit * HCLGE_REG_64_BIT_SPACE_MULTIPLE; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; + reg += regs_num_64_bit * HCLGE_REG_64_BIT_SPACE_MULTIPLE; ret = hclge_get_dfx_reg(hdev, reg); if (ret) -- cgit From 3ef5d70b82ad5be1235e16318d9ab4f848a5bd68 Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Tue, 15 Aug 2023 14:06:40 +0800 Subject: net: hns3: Support tlv in regs data for HNS3 VF driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dump register function is being refactored. The third step in refactoring is to support tlv info in regs data for HNS3 PF driver. Currently, if we use "ethtool -d" to dump regs value, the output is as follows: offset1: 00 01 02 03 04 05 ... offset2:10 11 12 13 14 15 ... ...... We can't get the value of a register directly. This patch deletes the original separator information and add tag_len_value information in regs data. ethtool can parse register data in key-value format by -d command. a patch will be added to the ethtool to parse regs data in the following format: reg1 : value2 reg2 : value2 ...... Signed-off-by: Jijie Shao Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c | 85 ++++++++++++++++------ 1 file changed, 61 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c index 197ab733306b..65b9dcd38137 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c @@ -57,23 +57,67 @@ static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, HCLGEVF_TQP_INTR_GL2_REG, HCLGEVF_TQP_INTR_RL_REG}; -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) +enum hclgevf_reg_tag { + HCLGEVF_REG_TAG_CMDQ = 0, + HCLGEVF_REG_TAG_COMMON, + HCLGEVF_REG_TAG_RING, + HCLGEVF_REG_TAG_TQP_INTR, +}; + +#pragma pack(4) +struct hclgevf_reg_tlv { + u16 tag; + u16 len; +}; + +struct hclgevf_reg_header { + u64 magic_number; + u8 is_vf; + u8 rsv[7]; +}; + +#pragma pack() + +#define HCLGEVF_REG_TLV_SIZE sizeof(struct hclgevf_reg_tlv) +#define HCLGEVF_REG_HEADER_SIZE sizeof(struct hclgevf_reg_header) +#define HCLGEVF_REG_TLV_SPACE (sizeof(struct hclgevf_reg_tlv) / sizeof(u32)) +#define HCLGEVF_REG_HEADER_SPACE (sizeof(struct hclgevf_reg_header) / sizeof(u32)) +#define HCLGEVF_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */ + +static u32 hclgevf_reg_get_header(void *data) +{ + struct hclgevf_reg_header *header = data; + + header->magic_number = HCLGEVF_REG_MAGIC_NUMBER; + header->is_vf = 0x1; + + return HCLGEVF_REG_HEADER_SPACE; +} + +static u32 hclgevf_reg_get_tlv(u32 tag, u32 regs_num, void *data) +{ + struct hclgevf_reg_tlv *tlv = data; + + tlv->tag = tag; + tlv->len = regs_num * sizeof(u32) + HCLGEVF_REG_TLV_SIZE; + + return HCLGEVF_REG_TLV_SPACE; +} int hclgevf_get_regs_len(struct hnae3_handle *handle) { - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int cmdq_len, common_len, ring_len, tqp_intr_len; - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1; + cmdq_len = HCLGEVF_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list); + common_len = HCLGEVF_REG_TLV_SIZE + sizeof(common_reg_addr_list); + ring_len = HCLGEVF_REG_TLV_SIZE + sizeof(ring_reg_addr_list); + tqp_intr_len = HCLGEVF_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list); - return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE; + /* return the total length of all register values */ + return HCLGEVF_REG_HEADER_SIZE + cmdq_len + common_len + + tqp_intr_len * (hdev->num_msi_used - 1) + + ring_len * hdev->num_tqps; } void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, @@ -83,45 +127,38 @@ void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, #define HCLGEVF_RING_INT_REG_OFFSET 0x4 struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - int i, j, reg_um, separator_num; + int i, j, reg_um; u32 *reg = data; *version = hdev->fw_version; + reg += hclgevf_reg_get_header(reg); /* fetching per-VF registers values from VF PCIe register space */ reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_CMDQ, reg_um, reg); for (i = 0; i < reg_um; i++) *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; reg_um = sizeof(common_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_COMMON, reg_um, reg); for (i = 0; i < reg_um; i++) *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; for (j = 0; j < hdev->num_tqps; j++) { + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_RING, reg_um, reg); for (i = 0; i < reg_um; i++) *reg++ = hclgevf_read_dev(&hdev->hw, ring_reg_addr_list[i] + HCLGEVF_RING_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; } reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; for (j = 0; j < hdev->num_msi_used - 1; j++) { + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_TQP_INTR, reg_um, reg); for (i = 0; i < reg_um; i++) *reg++ = hclgevf_read_dev(&hdev->hw, tqp_intr_reg_addr_list[i] + HCLGEVF_RING_INT_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; } } -- cgit From 36122201eeaefd78547def9681aa5d83b5a00b6a Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Tue, 15 Aug 2023 14:06:41 +0800 Subject: net: hns3: fix wrong rpu tln reg issue In the original RPU query command, the status register values of multiple RPU tunnels are accumulated by default, which is unreasonable. This patch Fix it by querying the specified tunnel ID. The tunnel number of the device can be obtained from firmware during initialization. Fixes: ddb54554fa51 ("net: hns3: add DFX registers information for ethtool -d") Signed-off-by: Jijie Shao Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 4 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_regs.c | 66 +++++++++++++++++++++- 4 files changed, 71 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 514a20bce4f4..a4b43bcd2f0c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -382,6 +382,7 @@ struct hnae3_dev_specs { u16 umv_size; u16 mc_mac_size; u32 mac_stats_num; + u8 tnl_num; }; struct hnae3_client_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 0bd858620f27..4d15eb73b972 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -826,7 +826,9 @@ struct hclge_dev_specs_1_cmd { u8 rsv0[2]; __le16 umv_size; __le16 mc_mac_size; - u8 rsv1[12]; + u8 rsv1[6]; + u8 tnl_num; + u8 rsv2[5]; }; /* mac speed type defined in firmware command */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 36e8daf49811..0f50dba6cc47 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1326,6 +1326,7 @@ static void hclge_set_default_dev_specs(struct hclge_dev *hdev) ae_dev->dev_specs.max_frm_size = HCLGE_MAC_MAX_FRAME; ae_dev->dev_specs.max_qset_num = HCLGE_MAX_QSET_NUM; ae_dev->dev_specs.umv_size = HCLGE_DEFAULT_UMV_SPACE_PER_PF; + ae_dev->dev_specs.tnl_num = 0; } static void hclge_parse_dev_specs(struct hclge_dev *hdev, @@ -1349,6 +1350,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev, ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size); ae_dev->dev_specs.umv_size = le16_to_cpu(req1->umv_size); ae_dev->dev_specs.mc_mac_size = le16_to_cpu(req1->mc_mac_size); + ae_dev->dev_specs.tnl_num = req1->tnl_num; } static void hclge_check_dev_specs(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c index 734e5f757b9c..43c1c18fa81f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c @@ -125,6 +125,7 @@ enum hclge_reg_tag { HCLGE_REG_TAG_DFX_RCB, HCLGE_REG_TAG_DFX_TQP, HCLGE_REG_TAG_DFX_SSU_2, + HCLGE_REG_TAG_RPU_TNL, }; #pragma pack(4) @@ -147,6 +148,8 @@ struct hclge_reg_header { #define HCLGE_REG_HEADER_SPACE (sizeof(struct hclge_reg_header) / sizeof(u32)) #define HCLGE_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */ +#define HCLGE_REG_RPU_TNL_ID_0 1 + static u32 hclge_reg_get_header(void *data) { struct hclge_reg_header *header = data; @@ -342,6 +345,28 @@ static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, return ret; } +/* tnl_id = 0 means get sum of all tnl reg's value */ +static int hclge_dfx_reg_rpu_tnl_cmd_send(struct hclge_dev *hdev, u32 tnl_id, + struct hclge_desc *desc, int bd_num) +{ + int i, ret; + + for (i = 0; i < bd_num; i++) { + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_RPU_REG_0, + true); + if (i != bd_num - 1) + desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + } + + desc[0].data[0] = cpu_to_le32(tnl_id); + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to query dfx rpu tnl reg, ret = %d\n", + ret); + return ret; +} + static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, void *data) { @@ -363,6 +388,7 @@ static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) { u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); int data_len_per_desc; int *bd_num_list; int ret; @@ -384,11 +410,41 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) for (i = 0; i < dfx_reg_type_num; i++) *len += bd_num_list[i] * data_len_per_desc + HCLGE_REG_TLV_SIZE; + /** + * the num of dfx_rpu_0 is reused by each dfx_rpu_tnl + * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is + * starting at 0, so offset need '- 1'. + */ + *len += (bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1] * data_len_per_desc + + HCLGE_REG_TLV_SIZE) * ae_dev->dev_specs.tnl_num; + out: kfree(bd_num_list); return ret; } +static int hclge_get_dfx_rpu_tnl_reg(struct hclge_dev *hdev, u32 *reg, + struct hclge_desc *desc_src, + int bd_num) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + int ret = 0; + u8 i; + + for (i = HCLGE_REG_RPU_TNL_ID_0; i <= ae_dev->dev_specs.tnl_num; i++) { + ret = hclge_dfx_reg_rpu_tnl_cmd_send(hdev, i, desc_src, bd_num); + if (ret) + break; + + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RPU_TNL, + ARRAY_SIZE(desc_src->data) * bd_num, + reg); + reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); + } + + return ret; +} + static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) { u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); @@ -428,7 +484,7 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) if (ret) { dev_err(&hdev->pdev->dev, "Get dfx reg fail, status is %d.\n", ret); - break; + goto free; } reg += hclge_reg_get_tlv(HCLGE_REG_TAG_DFX_BIOS_COMMON + i, @@ -437,6 +493,14 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); } + /** + * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is + * starting at 0, so offset need '- 1'. + */ + bd_num = bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1]; + ret = hclge_get_dfx_rpu_tnl_reg(hdev, reg, desc_src, bd_num); + +free: kfree(desc_src); out: kfree(bd_num_list); -- cgit From aae249dfa089c0c9d845ef18d70c0b7ef367df64 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 10:55:15 +0800 Subject: net: dsa: realtek: Remove redundant of_match_ptr() The driver depends on CONFIG_OF, it is not necessary to use of_match_ptr() here. Signed-off-by: Ruan Jinjie Acked-by: Linus Walleij Reviewed-by: Vladimir Oltean Reviewed-by: Linus Walleij Signed-off-by: David S. Miller --- drivers/net/dsa/realtek/realtek-mdio.c | 2 +- drivers/net/dsa/realtek/realtek-smi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c index 4310e7793e58..292e6d087e8b 100644 --- a/drivers/net/dsa/realtek/realtek-mdio.c +++ b/drivers/net/dsa/realtek/realtek-mdio.c @@ -276,7 +276,7 @@ MODULE_DEVICE_TABLE(of, realtek_mdio_of_match); static struct mdio_driver realtek_mdio_driver = { .mdiodrv.driver = { .name = "realtek-mdio", - .of_match_table = of_match_ptr(realtek_mdio_of_match), + .of_match_table = realtek_mdio_of_match, }, .probe = realtek_mdio_probe, .remove = realtek_mdio_remove, diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c index c2bd8bb6c9c2..ff13563059c5 100644 --- a/drivers/net/dsa/realtek/realtek-smi.c +++ b/drivers/net/dsa/realtek/realtek-smi.c @@ -556,7 +556,7 @@ MODULE_DEVICE_TABLE(of, realtek_smi_of_match); static struct platform_driver realtek_smi_driver = { .driver = { .name = "realtek-smi", - .of_match_table = of_match_ptr(realtek_smi_of_match), + .of_match_table = realtek_smi_of_match, }, .probe = realtek_smi_probe, .remove = realtek_smi_remove, -- cgit From 81d463c02b910f4abb1415c365f9491e10333552 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 10:55:16 +0800 Subject: net: dsa: rzn1-a5psw: Remove redundant of_match_ptr() The driver depends on CONFIG_OF, it is not necessary to use of_match_ptr() here. Signed-off-by: Ruan Jinjie Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/rzn1_a5psw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 2bb458f2c1f8..9167e83fbceb 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -1314,7 +1314,7 @@ MODULE_DEVICE_TABLE(of, a5psw_of_mtable); static struct platform_driver a5psw_driver = { .driver = { .name = "rzn1_a5psw", - .of_match_table = of_match_ptr(a5psw_of_mtable), + .of_match_table = a5psw_of_mtable, }, .probe = a5psw_probe, .remove = a5psw_remove, -- cgit From 21b566fda00f1907b41a06fb0255746639e4579f Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 10:55:17 +0800 Subject: net: gemini: Remove redundant of_match_ptr() The driver depends on CONFIG_OF, it is not necessary to use of_match_ptr() here. Signed-off-by: Ruan Jinjie Acked-by: Linus Walleij Signed-off-by: David S. Miller --- drivers/net/ethernet/cortina/gemini.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 692cb2d04c1c..a8b9d1a3e4d5 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2538,7 +2538,7 @@ MODULE_DEVICE_TABLE(of, gemini_ethernet_port_of_match); static struct platform_driver gemini_ethernet_port_driver = { .driver = { .name = "gemini-ethernet-port", - .of_match_table = of_match_ptr(gemini_ethernet_port_of_match), + .of_match_table = gemini_ethernet_port_of_match, }, .probe = gemini_ethernet_port_probe, .remove = gemini_ethernet_port_remove, @@ -2604,7 +2604,7 @@ MODULE_DEVICE_TABLE(of, gemini_ethernet_of_match); static struct platform_driver gemini_ethernet_driver = { .driver = { .name = DRV_NAME, - .of_match_table = of_match_ptr(gemini_ethernet_of_match), + .of_match_table = gemini_ethernet_of_match, }, .probe = gemini_ethernet_probe, .remove = gemini_ethernet_remove, -- cgit From 537a6b9927083e2b7b0b3223dc77a985707d5339 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 10:55:18 +0800 Subject: net: qualcomm: Remove redundant of_match_ptr() The driver depends on CONFIG_OF, it is not necessary to use of_match_ptr() here. Signed-off-by: Ruan Jinjie Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/qca_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c index ace99c62d03a..9adec91f35e9 100644 --- a/drivers/net/ethernet/qualcomm/qca_uart.c +++ b/drivers/net/ethernet/qualcomm/qca_uart.c @@ -403,7 +403,7 @@ static struct serdev_device_driver qca_uart_driver = { .remove = qca_uart_remove, .driver = { .name = QCAUART_DRV_NAME, - .of_match_table = of_match_ptr(qca_uart_of_match), + .of_match_table = qca_uart_of_match, }, }; -- cgit From cf2abd8724318195a0cd7e55ff1dcac74b4b110a Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 10:55:19 +0800 Subject: wlcore: spi: Remove redundant of_match_ptr() The driver depends on CONFIG_OF, it is not necessary to use of_match_ptr() here. Signed-off-by: Ruan Jinjie Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/wireless/ti/wlcore/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 3f88e6a0a510..7d9a139db59e 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -554,7 +554,7 @@ static void wl1271_remove(struct spi_device *spi) static struct spi_driver wl1271_spi_driver = { .driver = { .name = "wl1271_spi", - .of_match_table = of_match_ptr(wlcore_spi_of_match_table), + .of_match_table = wlcore_spi_of_match_table, }, .probe = wl1271_probe, -- cgit From 90bc21aaef4adaefceda2d385756138fc247c0c2 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 15 Aug 2023 11:21:05 +0300 Subject: net: ethernet: ti: am65-cpsw: add mqprio qdisc offload in channel mode This patch adds MQPRIO Qdisc offload in full 'channel' mode which allows not only setting up pri:tc mapping, but also configuring TX shapers on external port FIFOs. The K3 CPSW MQPRIO Qdisc offload is expected to work with VLAN/priority tagged packets. Non-tagged packets have to be mapped only to TC0. - TX traffic classes must be rated starting from TC that has highest priority and with no gaps - Traffic classes are used starting from 0, that has highest priority - min_rate defines Committed Information Rate (guaranteed) - max_rate defines Excess Information Rate (non guaranteed) and offloaded as (max_rate[i] - tcX_min_rate[i]) - VLAN/priority tagged packets mapped to TC0 will exit switch with VLAN tag priority 0 The configuration example: ethtool -L eth1 tx 5 ethtool --set-priv-flags eth1 p0-rx-ptype-rrobin off tc qdisc add dev eth1 parent root handle 100: mqprio num_tc 3 \ map 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 \ queues 1@0 1@1 1@2 hw 1 mode channel \ shaper bw_rlimit min_rate 0 100mbit 200mbit max_rate 0 101mbit 202mbit tc qdisc replace dev eth2 handle 100: parent root mqprio num_tc 1 \ map 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 queues 1@0 hw 1 ip link add link eth1 name eth1.100 type vlan id 100 ip link set eth1.100 type vlan egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 In the above example two ports share the same TX CPPI queue 0 for low priority traffic. 3 traffic classes are defined for eth1 and mapped to: TC0 - low priority, TX CPPI queue 0 -> ext Port 1 fifo0, no rate limit TC1 - prio 2, TX CPPI queue 1 -> ext Port 1 fifo1, CIR=100Mbit/s, EIR=1Mbit/s TC2 - prio 3, TX CPPI queue 2 -> ext Port 1 fifo2, CIR=200Mbit/s, EIR=2Mbit/s Signed-off-by: Grygorii Strashko Signed-off-by: Roger Quadros Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 3 + drivers/net/ethernet/ti/am65-cpsw-qos.c | 295 ++++++++++++++++++++++++++++++- drivers/net/ethernet/ti/am65-cpsw-qos.h | 14 ++ 3 files changed, 311 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index bea6fc0f324c..09593d6fd618 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -633,6 +633,9 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) /* restore vlan configurations */ vlan_for_each(ndev, cpsw_restore_vlans, port); + /* Initialize QoS */ + am65_cpsw_qos_mqprio_init(port); + phylink_start(port->slave.phylink); return 0; diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c index 9ac2ff05d501..3b3e75fbb64d 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.c +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c @@ -17,9 +17,12 @@ #define AM65_CPSW_REG_CTL 0x004 #define AM65_CPSW_PN_REG_CTL 0x004 +#define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 +#define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 #define AM65_CPSW_PN_REG_EST_CTL 0x060 #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) +#define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) /* AM65_CPSW_REG_CTL register fields */ #define AM65_CPSW_CTL_EST_EN BIT(18) @@ -56,6 +59,12 @@ enum timer_act { TACT_SKIP_PROG, /* just buffer can be updated */ }; +/* number of traffic classes (FIFOs) per port */ +#define AM65_CPSW_PN_TC_NUM 8 +#define AM65_CPSW_PN_TX_PRI_MAP_DEFAULT 0x76543210 + +static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data); + static int am65_cpsw_port_est_enabled(struct am65_cpsw_port *port) { return port->qos.est_oper || port->qos.est_admin; @@ -541,7 +550,6 @@ static void am65_cpsw_est_link_up(struct net_device *ndev, int link_speed) ktime_t cur_time; s64 delta; - port->qos.link_speed = link_speed; if (!am65_cpsw_port_est_enabled(port)) return; @@ -795,6 +803,8 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, return am65_cpsw_tc_query_caps(ndev, type_data); case TC_SETUP_QDISC_TAPRIO: return am65_cpsw_setup_taprio(ndev, type_data); + case TC_SETUP_QDISC_MQPRIO: + return am65_cpsw_setup_mqprio(ndev, type_data); case TC_SETUP_BLOCK: return am65_cpsw_qos_setup_tc_block(ndev, type_data); default: @@ -802,10 +812,15 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, } } +static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port); + void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) { struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + port->qos.link_speed = link_speed; + am65_cpsw_tx_pn_shaper_link_up(port); + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) return; @@ -937,3 +952,281 @@ void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common) host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch)); } } + +static void am65_cpsw_tx_pn_shaper_apply(struct am65_cpsw_port *port) +{ + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; + struct am65_cpsw_common *common = port->common; + struct tc_mqprio_qopt_offload *mqprio; + bool shaper_en; + u32 rate_mbps; + int i; + + mqprio = &p_mqprio->mqprio_hw; + shaper_en = p_mqprio->shaper_en && !p_mqprio->shaper_susp; + + for (i = 0; i < mqprio->qopt.num_tc; i++) { + rate_mbps = 0; + if (shaper_en) { + rate_mbps = mqprio->min_rate[i] * 8 / 1000000; + rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, + common->bus_freq); + } + + writel(rate_mbps, + port->port_base + AM65_CPSW_PN_REG_PRI_CIR(i)); + } + + for (i = 0; i < mqprio->qopt.num_tc; i++) { + rate_mbps = 0; + if (shaper_en && mqprio->max_rate[i]) { + rate_mbps = mqprio->max_rate[i] - mqprio->min_rate[i]; + rate_mbps = rate_mbps * 8 / 1000000; + rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, + common->bus_freq); + } + + writel(rate_mbps, + port->port_base + AM65_CPSW_PN_REG_PRI_EIR(i)); + } +} + +static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port) +{ + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; + struct am65_cpsw_common *common = port->common; + bool shaper_susp = false; + + if (!p_mqprio->enable || !p_mqprio->shaper_en) + return; + + if (p_mqprio->max_rate_total > port->qos.link_speed) + shaper_susp = true; + + if (p_mqprio->shaper_susp == shaper_susp) + return; + + if (shaper_susp) + dev_info(common->dev, + "Port%u: total shaper tx rate > link speed - suspend shaper\n", + port->port_id); + else + dev_info(common->dev, + "Port%u: link recover - resume shaper\n", + port->port_id); + + p_mqprio->shaper_susp = shaper_susp; + am65_cpsw_tx_pn_shaper_apply(port); +} + +void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port) +{ + struct am65_cpsw_host *host = am65_common_get_host(port->common); + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; + struct tc_mqprio_qopt_offload *mqprio; + u32 tx_prio_map = 0, rx_prio_map; + int i, fifo; + + mqprio = &p_mqprio->mqprio_hw; + rx_prio_map = readl(host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP); + + if (p_mqprio->enable) { + for (i = 0; i < AM65_CPSW_PN_TC_NUM; i++) { + fifo = mqprio->qopt.prio_tc_map[i]; + tx_prio_map |= fifo << (4 * i); + } + + netdev_set_num_tc(port->ndev, mqprio->qopt.num_tc); + for (i = 0; i < mqprio->qopt.num_tc; i++) { + netdev_set_tc_queue(port->ndev, i, + mqprio->qopt.count[i], + mqprio->qopt.offset[i]); + if (!i) { + p_mqprio->tc0_q = mqprio->qopt.offset[i]; + rx_prio_map &= ~(0x7 << (4 * p_mqprio->tc0_q)); + } + } + } else { + /* restore default configuration */ + netdev_reset_tc(port->ndev); + tx_prio_map = AM65_CPSW_PN_TX_PRI_MAP_DEFAULT; + rx_prio_map |= p_mqprio->tc0_q << (4 * p_mqprio->tc0_q); + p_mqprio->tc0_q = 0; + } + + writel(tx_prio_map, + port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); + writel(rx_prio_map, + host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP); + + am65_cpsw_tx_pn_shaper_apply(port); +} + +static int am65_cpsw_mqprio_verify(struct am65_cpsw_port *port, + struct tc_mqprio_qopt_offload *mqprio) +{ + int i; + + for (i = 0; i < mqprio->qopt.num_tc; i++) { + unsigned int last = mqprio->qopt.offset[i] + + mqprio->qopt.count[i]; + + if (mqprio->qopt.offset[i] >= port->ndev->real_num_tx_queues || + !mqprio->qopt.count[i] || + last > port->ndev->real_num_tx_queues) + return -EINVAL; + } + + return 0; +} + +static int am65_cpsw_mqprio_verify_shaper(struct am65_cpsw_port *port, + struct tc_mqprio_qopt_offload *mqprio, + u64 *max_rate) +{ + struct am65_cpsw_common *common = port->common; + u64 min_rate_total = 0, max_rate_total = 0; + u32 min_rate_msk = 0, max_rate_msk = 0; + bool has_min_rate, has_max_rate; + int num_tc, i; + + has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); + has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE); + + if (!has_min_rate && has_max_rate) + return -EOPNOTSUPP; + + if (!has_min_rate) + return 0; + + num_tc = mqprio->qopt.num_tc; + + for (i = num_tc - 1; i >= 0; i--) { + u32 ch_msk; + + if (mqprio->min_rate[i]) + min_rate_msk |= BIT(i); + min_rate_total += mqprio->min_rate[i]; + + if (has_max_rate) { + if (mqprio->max_rate[i]) + max_rate_msk |= BIT(i); + max_rate_total += mqprio->max_rate[i]; + + if (!mqprio->min_rate[i] && mqprio->max_rate[i]) { + dev_err(common->dev, "TX tc%d rate max>0 but min=0\n", + i); + return -EINVAL; + } + + if (mqprio->max_rate[i] && + mqprio->max_rate[i] < mqprio->min_rate[i]) { + dev_err(common->dev, "TX tc%d rate min(%llu)>max(%llu)\n", + i, mqprio->min_rate[i], + mqprio->max_rate[i]); + return -EINVAL; + } + } + + ch_msk = GENMASK(num_tc - 1, i); + if ((min_rate_msk & BIT(i)) && (min_rate_msk ^ ch_msk)) { + dev_err(common->dev, "TX Min rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n", + min_rate_msk); + return -EINVAL; + } + + if ((max_rate_msk & BIT(i)) && (max_rate_msk ^ ch_msk)) { + dev_err(common->dev, "TX max rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n", + max_rate_msk); + return -EINVAL; + } + } + min_rate_total *= 8; + min_rate_total /= 1000 * 1000; + max_rate_total *= 8; + max_rate_total /= 1000 * 1000; + + if (port->qos.link_speed != SPEED_UNKNOWN) { + if (min_rate_total > port->qos.link_speed) { + dev_err(common->dev, "TX rate min exceed %llu link speed %d\n", + min_rate_total, port->qos.link_speed); + return -EINVAL; + } + + if (max_rate_total > port->qos.link_speed) { + dev_err(common->dev, "TX rate max exceed %llu link speed %d\n", + max_rate_total, port->qos.link_speed); + return -EINVAL; + } + } + + *max_rate = max_t(u64, min_rate_total, max_rate_total); + + return 0; +} + +static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data) +{ + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct tc_mqprio_qopt_offload *mqprio = type_data; + struct am65_cpsw_common *common = port->common; + struct am65_cpsw_mqprio *p_mqprio; + bool has_min_rate; + int num_tc, ret; + u64 max_rate; + + p_mqprio = &port->qos.mqprio; + + if (!mqprio->qopt.hw) + goto skip_check; + + if (mqprio->mode != TC_MQPRIO_MODE_CHANNEL) + return -EOPNOTSUPP; + + num_tc = mqprio->qopt.num_tc; + if (num_tc > AM65_CPSW_PN_TC_NUM) + return -ERANGE; + + if ((mqprio->flags & TC_MQPRIO_F_SHAPER) && + mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) + return -EOPNOTSUPP; + + ret = am65_cpsw_mqprio_verify(port, mqprio); + if (ret) + return ret; + + ret = am65_cpsw_mqprio_verify_shaper(port, mqprio, &max_rate); + if (ret) + return ret; + +skip_check: + ret = pm_runtime_get_sync(common->dev); + if (ret < 0) { + pm_runtime_put_noidle(common->dev); + return ret; + } + + if (mqprio->qopt.hw) { + memcpy(&p_mqprio->mqprio_hw, mqprio, sizeof(*mqprio)); + has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); + p_mqprio->enable = 1; + p_mqprio->shaper_en = has_min_rate; + p_mqprio->shaper_susp = !has_min_rate; + p_mqprio->max_rate_total = max_rate; + } else { + unsigned int tc0_q = p_mqprio->tc0_q; + + memset(p_mqprio, 0, sizeof(*p_mqprio)); + p_mqprio->mqprio_hw.qopt.num_tc = AM65_CPSW_PN_TC_NUM; + p_mqprio->tc0_q = tc0_q; + } + + if (!netif_running(ndev)) + goto exit_put; + + am65_cpsw_qos_mqprio_init(port); + +exit_put: + pm_runtime_put(common->dev); + return 0; +} diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.h b/drivers/net/ethernet/ti/am65-cpsw-qos.h index 0cc2a3b3d7f9..247a42788687 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.h +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.h @@ -7,8 +7,10 @@ #include #include +#include struct am65_cpsw_common; +struct am65_cpsw_port; struct am65_cpsw_est { int buf; @@ -16,6 +18,16 @@ struct am65_cpsw_est { struct tc_taprio_qopt_offload taprio; }; +struct am65_cpsw_mqprio { + struct tc_mqprio_qopt_offload mqprio_hw; + u64 max_rate_total; + + unsigned enable:1; + unsigned shaper_en:1; + unsigned shaper_susp:1; + unsigned tc0_q:3; +}; + struct am65_cpsw_ale_ratelimit { unsigned long cookie; u64 rate_packet_ps; @@ -26,6 +38,7 @@ struct am65_cpsw_qos { struct am65_cpsw_est *est_oper; ktime_t link_down_time; int link_speed; + struct am65_cpsw_mqprio mqprio; struct am65_cpsw_ale_ratelimit ale_bc_ratelimit; struct am65_cpsw_ale_ratelimit ale_mc_ratelimit; @@ -35,6 +48,7 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, void *type_data); void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed); void am65_cpsw_qos_link_down(struct net_device *ndev); +void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port); int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, int queue, u32 rate_mbps); void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common); -- cgit From d147085183ea1b0efd2c18fca76e4dee873b1e4e Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 15 Aug 2023 10:01:11 -0700 Subject: e1000e: Use PME poll to circumvent unreliable ACPI wake On some I219 devices, ethernet cable plugging detection only works once from PCI D3 state. Subsequent cable plugging does set PME bit correctly, but device still doesn't get woken up. Since I219 connects to the root complex directly, it relies on platform firmware (ACPI) to wake it up. In this case, the GPE from _PRW only works for first cable plugging but fails to notify the driver for subsequent plugging events. The issue was originally found on CNP, but the same issue can be found on ADL too. So workaround the issue by continuing use PME poll after first ACPI wake. As PME poll is always used, the runtime suspend restriction for CNP can also be removed. Signed-off-by: Kai-Heng Feng Tested-by: Naama Meir Acked-by: Sasha Neftin Reviewed-by: Simon Horman Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000e/netdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 771a3c909c45..18a5e73b8680 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -7021,6 +7021,8 @@ static __maybe_unused int e1000e_pm_runtime_resume(struct device *dev) struct e1000_adapter *adapter = netdev_priv(netdev); int rc; + pdev->pme_poll = true; + rc = __e1000_resume(pdev); if (rc) return rc; @@ -7682,7 +7684,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE); - if (pci_dev_run_wake(pdev) && hw->mac.type != e1000_pch_cnp) + if (pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); return 0; -- cgit From dd2e84bb3804103ad1c26a21deb4b35b0e166746 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Fri, 28 Jul 2023 17:52:05 +0200 Subject: virtchnl: fix fake 1-elem arrays in structs allocated as `nents + 1` - 1 The two most problematic virtchnl structures are virtchnl_rss_key and virtchnl_rss_lut. Their "flex" arrays have the type of u8, thus, when allocating / checking, the actual size is calculated as `sizeof + nents - 1 byte`. But their sizeof() is not 1 byte larger than the size of such structure with proper flex array, it's two bytes larger due to the padding. That said, their size is always 1 byte larger unless there are no tail elements -- then it's +2 bytes. Add virtchnl_struct_size() macro which will handle this case (and later other cases as well). Make its calling conv the same as we call struct_size() to allow it to be drop-in, even though it's unlikely to become possible to switch to generic API. The macro will calculate a proper size of a structure with a flex array at the end, so that it becomes transparent for the compilers, but add the difference from the old values, so that the real size of sorta-ABI-messages doesn't change. Use it on the allocation side in IAVF and the receiving side (defined as static inline in virtchnl.h) for the mentioned two structures. Signed-off-by: Alexander Lobakin Reviewed-by: Kees Cook Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index be3c007ce90a..10f03054a603 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -1085,8 +1085,7 @@ void iavf_set_rss_key(struct iavf_adapter *adapter) adapter->current_op); return; } - len = sizeof(struct virtchnl_rss_key) + - (adapter->rss_key_size * sizeof(u8)) - 1; + len = virtchnl_struct_size(vrk, key, adapter->rss_key_size); vrk = kzalloc(len, GFP_KERNEL); if (!vrk) return; @@ -1117,8 +1116,7 @@ void iavf_set_rss_lut(struct iavf_adapter *adapter) adapter->current_op); return; } - len = sizeof(struct virtchnl_rss_lut) + - (adapter->rss_lut_size * sizeof(u8)) - 1; + len = virtchnl_struct_size(vrl, lut, adapter->rss_lut_size); vrl = kzalloc(len, GFP_KERNEL); if (!vrl) return; -- cgit From 5e7f59fa07f86f554c301c7a383bba54d5ef9819 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Fri, 28 Jul 2023 17:52:06 +0200 Subject: virtchnl: fix fake 1-elem arrays in structures allocated as `nents + 1` There are five virtchnl structures, which are allocated and checked in the code as `nents + 1`, meaning that they always have memory for one excessive element regardless of their actual number. This comes from that their sizeof() includes space for 1 element and then they get allocated via struct_size() or its open-coded equivalents, passing the actual number of elements. Expand virtchnl_struct_size() to handle such structures and replace those 1-elem arrays with proper flex ones. Also fix several places which open-code %IAVF_VIRTCHNL_VF_RESOURCE_SIZE. Finally, let the virtchnl_ether_addr_list size be computed automatically when there's no enough space for the whole list, otherwise we have to open-code reverse struct_size() logics. Signed-off-by: Alexander Lobakin Reviewed-by: Kees Cook Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- drivers/net/ethernet/intel/iavf/iavf.h | 6 +-- drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 44 ++++++++++------------ drivers/net/ethernet/intel/ice/ice_virtchnl.c | 2 +- 4 files changed, 24 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 98aca9f8b602..a6983c2d7c30 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2103,7 +2103,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) goto err; } - len = struct_size(vfres, vsi_res, num_vsis); + len = virtchnl_struct_size(vfres, vsi_res, num_vsis); vfres = kzalloc(len, GFP_KERNEL); if (!vfres) { aq_ret = -ENOMEM; diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 8cbdebc5b698..85fba85fbb23 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -92,9 +92,9 @@ struct iavf_vsi { #define IAVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */ #define IAVF_MBPS_QUANTA 50 -#define IAVF_VIRTCHNL_VF_RESOURCE_SIZE (sizeof(struct virtchnl_vf_resource) + \ - (IAVF_MAX_VF_VSI * \ - sizeof(struct virtchnl_vsi_resource))) +#define IAVF_VIRTCHNL_VF_RESOURCE_SIZE \ + virtchnl_struct_size((struct virtchnl_vf_resource *)NULL, \ + vsi_res, IAVF_MAX_VF_VSI) /* MAX_MSIX_Q_VECTORS of these are allocated, * but we only use one per queue-specific vector. diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 10f03054a603..4fdac698eb38 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -215,8 +215,7 @@ int iavf_get_vf_config(struct iavf_adapter *adapter) u16 len; int err; - len = sizeof(struct virtchnl_vf_resource) + - IAVF_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource); + len = IAVF_VIRTCHNL_VF_RESOURCE_SIZE; event.buf_len = len; event.msg_buf = kzalloc(len, GFP_KERNEL); if (!event.msg_buf) @@ -284,7 +283,7 @@ void iavf_configure_queues(struct iavf_adapter *adapter) return; } adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES; - len = struct_size(vqci, qpair, pairs); + len = virtchnl_struct_size(vqci, qpair, pairs); vqci = kzalloc(len, GFP_KERNEL); if (!vqci) return; @@ -397,7 +396,7 @@ void iavf_map_queues(struct iavf_adapter *adapter) q_vectors = adapter->num_msix_vectors - NONQ_VECS; - len = struct_size(vimi, vecmap, adapter->num_msix_vectors); + len = virtchnl_struct_size(vimi, vecmap, adapter->num_msix_vectors); vimi = kzalloc(len, GFP_KERNEL); if (!vimi) return; @@ -476,13 +475,11 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter) } adapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR; - len = struct_size(veal, list, count); + len = virtchnl_struct_size(veal, list, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - - sizeof(struct virtchnl_ether_addr_list)) / - sizeof(struct virtchnl_ether_addr); - len = struct_size(veal, list, count); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(veal, list, --count); more = true; } @@ -547,13 +544,11 @@ void iavf_del_ether_addrs(struct iavf_adapter *adapter) } adapter->current_op = VIRTCHNL_OP_DEL_ETH_ADDR; - len = struct_size(veal, list, count); + len = virtchnl_struct_size(veal, list, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - - sizeof(struct virtchnl_ether_addr_list)) / - sizeof(struct virtchnl_ether_addr); - len = struct_size(veal, list, count); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(veal, list, --count); more = true; } veal = kzalloc(len, GFP_ATOMIC); @@ -687,12 +682,12 @@ void iavf_add_vlans(struct iavf_adapter *adapter) adapter->current_op = VIRTCHNL_OP_ADD_VLAN; - len = sizeof(*vvfl) + (count * sizeof(u16)); + len = virtchnl_struct_size(vvfl, vlan_id, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - sizeof(*vvfl)) / - sizeof(u16); - len = sizeof(*vvfl) + (count * sizeof(u16)); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(vvfl, vlan_id, + --count); more = true; } vvfl = kzalloc(len, GFP_ATOMIC); @@ -838,12 +833,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter) adapter->current_op = VIRTCHNL_OP_DEL_VLAN; - len = sizeof(*vvfl) + (count * sizeof(u16)); + len = virtchnl_struct_size(vvfl, vlan_id, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - sizeof(*vvfl)) / - sizeof(u16); - len = sizeof(*vvfl) + (count * sizeof(u16)); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(vvfl, vlan_id, + --count); more = true; } vvfl = kzalloc(len, GFP_ATOMIC); @@ -2173,9 +2168,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, } break; case VIRTCHNL_OP_GET_VF_RESOURCES: { - u16 len = sizeof(struct virtchnl_vf_resource) + - IAVF_MAX_VF_VSI * - sizeof(struct virtchnl_vsi_resource); + u16 len = IAVF_VIRTCHNL_VF_RESOURCE_SIZE; + memcpy(adapter->vf_res, msg, min(msglen, len)); iavf_validate_num_queues(adapter); iavf_vf_parse_hw_config(&adapter->hw, adapter->vf_res); diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 85d996531502..4a02ed91ba73 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -428,7 +428,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg) goto err; } - len = sizeof(struct virtchnl_vf_resource); + len = virtchnl_struct_size(vfres, vsi_res, 0); vfres = kzalloc(len, GFP_KERNEL); if (!vfres) { -- cgit From b0654e64dbaf62f565b5f2b4fbd92202e88dcba3 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Fri, 28 Jul 2023 17:52:07 +0200 Subject: virtchnl: fix fake 1-elem arrays for structures allocated as `nents` Finally, fix 3 structures which are allocated technically correctly, i.e. the calculated size equals to the one that struct_size() would return, except for sizeof(). For &virtchnl_vlan_filter_list_v2, use the same approach when there are no enough space as taken previously for &virtchnl_vlan_filter_list, i.e. let the maximum size be calculated automatically instead of trying to guestimate it using maths. Signed-off-by: Alexander Lobakin Reviewed-by: Kees Cook Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 7 +++--- drivers/net/ethernet/intel/iavf/iavf_client.c | 4 ++-- drivers/net/ethernet/intel/iavf/iavf_client.h | 2 +- drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 25 ++++++++-------------- 4 files changed, 16 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index a6983c2d7c30..8ea1a238dcef 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -506,6 +506,7 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf, struct virtchnl_rdma_qv_info *qv_info; u32 v_idx, i, reg_idx, reg; u32 next_q_idx, next_q_type; + size_t size; u32 msix_vf; int ret = 0; @@ -521,9 +522,9 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf, } kfree(vf->qvlist_info); - vf->qvlist_info = kzalloc(struct_size(vf->qvlist_info, qv_info, - qvlist_info->num_vectors - 1), - GFP_KERNEL); + size = virtchnl_struct_size(vf->qvlist_info, qv_info, + qvlist_info->num_vectors); + vf->qvlist_info = kzalloc(size, GFP_KERNEL); if (!vf->qvlist_info) { ret = -ENOMEM; goto err_out; diff --git a/drivers/net/ethernet/intel/iavf/iavf_client.c b/drivers/net/ethernet/intel/iavf/iavf_client.c index 93c903c02c64..e6051b6355aa 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_client.c +++ b/drivers/net/ethernet/intel/iavf/iavf_client.c @@ -469,8 +469,8 @@ static int iavf_client_setup_qvlist(struct iavf_info *ldev, } v_qvlist_info = (struct virtchnl_rdma_qvlist_info *)qvlist_info; - msg_size = struct_size(v_qvlist_info, qv_info, - v_qvlist_info->num_vectors - 1); + msg_size = virtchnl_struct_size(v_qvlist_info, qv_info, + v_qvlist_info->num_vectors); adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP); err = iavf_aq_send_msg_to_pf(&adapter->hw, diff --git a/drivers/net/ethernet/intel/iavf/iavf_client.h b/drivers/net/ethernet/intel/iavf/iavf_client.h index c5d51d7dc7cc..500269bc0f5b 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_client.h +++ b/drivers/net/ethernet/intel/iavf/iavf_client.h @@ -53,7 +53,7 @@ struct iavf_qv_info { struct iavf_qvlist_info { u32 num_vectors; - struct iavf_qv_info qv_info[1]; + struct iavf_qv_info qv_info[]; }; #define IAVF_CLIENT_MSIX_ALL 0xFFFFFFFF diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 4fdac698eb38..f9727e9c3d63 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -727,15 +727,12 @@ void iavf_add_vlans(struct iavf_adapter *adapter) more = true; } - len = sizeof(*vvfl_v2) + ((count - 1) * - sizeof(struct virtchnl_vlan_filter)); + len = virtchnl_struct_size(vvfl_v2, filters, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - sizeof(*vvfl_v2)) / - sizeof(struct virtchnl_vlan_filter); - len = sizeof(*vvfl_v2) + - ((count - 1) * - sizeof(struct virtchnl_vlan_filter)); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(vvfl_v2, filters, + --count); more = true; } @@ -879,16 +876,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter) adapter->current_op = VIRTCHNL_OP_DEL_VLAN_V2; - len = sizeof(*vvfl_v2) + - ((count - 1) * sizeof(struct virtchnl_vlan_filter)); + len = virtchnl_struct_size(vvfl_v2, filters, count); if (len > IAVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); - count = (IAVF_MAX_AQ_BUF_SIZE - - sizeof(*vvfl_v2)) / - sizeof(struct virtchnl_vlan_filter); - len = sizeof(*vvfl_v2) + - ((count - 1) * - sizeof(struct virtchnl_vlan_filter)); + while (len > IAVF_MAX_AQ_BUF_SIZE) + len = virtchnl_struct_size(vvfl_v2, filters, + --count); more = true; } @@ -1492,7 +1485,7 @@ void iavf_enable_channels(struct iavf_adapter *adapter) return; } - len = struct_size(vti, list, adapter->num_tc - 1); + len = virtchnl_struct_size(vti, list, adapter->num_tc); vti = kzalloc(len, GFP_KERNEL); if (!vti) return; -- cgit From 42b118c9f97f5e0431b6a364a789c212bed96652 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 16 Aug 2023 19:33:44 -0700 Subject: Revert "net: ethernet: ti: am65-cpsw: add mqprio qdisc offload in channel mode" This reverts commit 90bc21aaef4adaefceda2d385756138fc247c0c2. Patch was merged too hastily, Vladimir requested changes in: https://lore.kernel.org/all/20230816121305.5dio5tk3chge2ndh@skbuf/ Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 3 - drivers/net/ethernet/ti/am65-cpsw-qos.c | 295 +------------------------------ drivers/net/ethernet/ti/am65-cpsw-qos.h | 14 -- 3 files changed, 1 insertion(+), 311 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 09593d6fd618..bea6fc0f324c 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -633,9 +633,6 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) /* restore vlan configurations */ vlan_for_each(ndev, cpsw_restore_vlans, port); - /* Initialize QoS */ - am65_cpsw_qos_mqprio_init(port); - phylink_start(port->slave.phylink); return 0; diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c index 3b3e75fbb64d..9ac2ff05d501 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.c +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c @@ -17,12 +17,9 @@ #define AM65_CPSW_REG_CTL 0x004 #define AM65_CPSW_PN_REG_CTL 0x004 -#define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 -#define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 #define AM65_CPSW_PN_REG_EST_CTL 0x060 #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) -#define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) /* AM65_CPSW_REG_CTL register fields */ #define AM65_CPSW_CTL_EST_EN BIT(18) @@ -59,12 +56,6 @@ enum timer_act { TACT_SKIP_PROG, /* just buffer can be updated */ }; -/* number of traffic classes (FIFOs) per port */ -#define AM65_CPSW_PN_TC_NUM 8 -#define AM65_CPSW_PN_TX_PRI_MAP_DEFAULT 0x76543210 - -static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data); - static int am65_cpsw_port_est_enabled(struct am65_cpsw_port *port) { return port->qos.est_oper || port->qos.est_admin; @@ -550,6 +541,7 @@ static void am65_cpsw_est_link_up(struct net_device *ndev, int link_speed) ktime_t cur_time; s64 delta; + port->qos.link_speed = link_speed; if (!am65_cpsw_port_est_enabled(port)) return; @@ -803,8 +795,6 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, return am65_cpsw_tc_query_caps(ndev, type_data); case TC_SETUP_QDISC_TAPRIO: return am65_cpsw_setup_taprio(ndev, type_data); - case TC_SETUP_QDISC_MQPRIO: - return am65_cpsw_setup_mqprio(ndev, type_data); case TC_SETUP_BLOCK: return am65_cpsw_qos_setup_tc_block(ndev, type_data); default: @@ -812,15 +802,10 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, } } -static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port); - void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) { struct am65_cpsw_port *port = am65_ndev_to_port(ndev); - port->qos.link_speed = link_speed; - am65_cpsw_tx_pn_shaper_link_up(port); - if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) return; @@ -952,281 +937,3 @@ void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common) host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch)); } } - -static void am65_cpsw_tx_pn_shaper_apply(struct am65_cpsw_port *port) -{ - struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; - struct am65_cpsw_common *common = port->common; - struct tc_mqprio_qopt_offload *mqprio; - bool shaper_en; - u32 rate_mbps; - int i; - - mqprio = &p_mqprio->mqprio_hw; - shaper_en = p_mqprio->shaper_en && !p_mqprio->shaper_susp; - - for (i = 0; i < mqprio->qopt.num_tc; i++) { - rate_mbps = 0; - if (shaper_en) { - rate_mbps = mqprio->min_rate[i] * 8 / 1000000; - rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, - common->bus_freq); - } - - writel(rate_mbps, - port->port_base + AM65_CPSW_PN_REG_PRI_CIR(i)); - } - - for (i = 0; i < mqprio->qopt.num_tc; i++) { - rate_mbps = 0; - if (shaper_en && mqprio->max_rate[i]) { - rate_mbps = mqprio->max_rate[i] - mqprio->min_rate[i]; - rate_mbps = rate_mbps * 8 / 1000000; - rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, - common->bus_freq); - } - - writel(rate_mbps, - port->port_base + AM65_CPSW_PN_REG_PRI_EIR(i)); - } -} - -static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port) -{ - struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; - struct am65_cpsw_common *common = port->common; - bool shaper_susp = false; - - if (!p_mqprio->enable || !p_mqprio->shaper_en) - return; - - if (p_mqprio->max_rate_total > port->qos.link_speed) - shaper_susp = true; - - if (p_mqprio->shaper_susp == shaper_susp) - return; - - if (shaper_susp) - dev_info(common->dev, - "Port%u: total shaper tx rate > link speed - suspend shaper\n", - port->port_id); - else - dev_info(common->dev, - "Port%u: link recover - resume shaper\n", - port->port_id); - - p_mqprio->shaper_susp = shaper_susp; - am65_cpsw_tx_pn_shaper_apply(port); -} - -void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port) -{ - struct am65_cpsw_host *host = am65_common_get_host(port->common); - struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; - struct tc_mqprio_qopt_offload *mqprio; - u32 tx_prio_map = 0, rx_prio_map; - int i, fifo; - - mqprio = &p_mqprio->mqprio_hw; - rx_prio_map = readl(host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP); - - if (p_mqprio->enable) { - for (i = 0; i < AM65_CPSW_PN_TC_NUM; i++) { - fifo = mqprio->qopt.prio_tc_map[i]; - tx_prio_map |= fifo << (4 * i); - } - - netdev_set_num_tc(port->ndev, mqprio->qopt.num_tc); - for (i = 0; i < mqprio->qopt.num_tc; i++) { - netdev_set_tc_queue(port->ndev, i, - mqprio->qopt.count[i], - mqprio->qopt.offset[i]); - if (!i) { - p_mqprio->tc0_q = mqprio->qopt.offset[i]; - rx_prio_map &= ~(0x7 << (4 * p_mqprio->tc0_q)); - } - } - } else { - /* restore default configuration */ - netdev_reset_tc(port->ndev); - tx_prio_map = AM65_CPSW_PN_TX_PRI_MAP_DEFAULT; - rx_prio_map |= p_mqprio->tc0_q << (4 * p_mqprio->tc0_q); - p_mqprio->tc0_q = 0; - } - - writel(tx_prio_map, - port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); - writel(rx_prio_map, - host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP); - - am65_cpsw_tx_pn_shaper_apply(port); -} - -static int am65_cpsw_mqprio_verify(struct am65_cpsw_port *port, - struct tc_mqprio_qopt_offload *mqprio) -{ - int i; - - for (i = 0; i < mqprio->qopt.num_tc; i++) { - unsigned int last = mqprio->qopt.offset[i] + - mqprio->qopt.count[i]; - - if (mqprio->qopt.offset[i] >= port->ndev->real_num_tx_queues || - !mqprio->qopt.count[i] || - last > port->ndev->real_num_tx_queues) - return -EINVAL; - } - - return 0; -} - -static int am65_cpsw_mqprio_verify_shaper(struct am65_cpsw_port *port, - struct tc_mqprio_qopt_offload *mqprio, - u64 *max_rate) -{ - struct am65_cpsw_common *common = port->common; - u64 min_rate_total = 0, max_rate_total = 0; - u32 min_rate_msk = 0, max_rate_msk = 0; - bool has_min_rate, has_max_rate; - int num_tc, i; - - has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); - has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE); - - if (!has_min_rate && has_max_rate) - return -EOPNOTSUPP; - - if (!has_min_rate) - return 0; - - num_tc = mqprio->qopt.num_tc; - - for (i = num_tc - 1; i >= 0; i--) { - u32 ch_msk; - - if (mqprio->min_rate[i]) - min_rate_msk |= BIT(i); - min_rate_total += mqprio->min_rate[i]; - - if (has_max_rate) { - if (mqprio->max_rate[i]) - max_rate_msk |= BIT(i); - max_rate_total += mqprio->max_rate[i]; - - if (!mqprio->min_rate[i] && mqprio->max_rate[i]) { - dev_err(common->dev, "TX tc%d rate max>0 but min=0\n", - i); - return -EINVAL; - } - - if (mqprio->max_rate[i] && - mqprio->max_rate[i] < mqprio->min_rate[i]) { - dev_err(common->dev, "TX tc%d rate min(%llu)>max(%llu)\n", - i, mqprio->min_rate[i], - mqprio->max_rate[i]); - return -EINVAL; - } - } - - ch_msk = GENMASK(num_tc - 1, i); - if ((min_rate_msk & BIT(i)) && (min_rate_msk ^ ch_msk)) { - dev_err(common->dev, "TX Min rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n", - min_rate_msk); - return -EINVAL; - } - - if ((max_rate_msk & BIT(i)) && (max_rate_msk ^ ch_msk)) { - dev_err(common->dev, "TX max rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n", - max_rate_msk); - return -EINVAL; - } - } - min_rate_total *= 8; - min_rate_total /= 1000 * 1000; - max_rate_total *= 8; - max_rate_total /= 1000 * 1000; - - if (port->qos.link_speed != SPEED_UNKNOWN) { - if (min_rate_total > port->qos.link_speed) { - dev_err(common->dev, "TX rate min exceed %llu link speed %d\n", - min_rate_total, port->qos.link_speed); - return -EINVAL; - } - - if (max_rate_total > port->qos.link_speed) { - dev_err(common->dev, "TX rate max exceed %llu link speed %d\n", - max_rate_total, port->qos.link_speed); - return -EINVAL; - } - } - - *max_rate = max_t(u64, min_rate_total, max_rate_total); - - return 0; -} - -static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data) -{ - struct am65_cpsw_port *port = am65_ndev_to_port(ndev); - struct tc_mqprio_qopt_offload *mqprio = type_data; - struct am65_cpsw_common *common = port->common; - struct am65_cpsw_mqprio *p_mqprio; - bool has_min_rate; - int num_tc, ret; - u64 max_rate; - - p_mqprio = &port->qos.mqprio; - - if (!mqprio->qopt.hw) - goto skip_check; - - if (mqprio->mode != TC_MQPRIO_MODE_CHANNEL) - return -EOPNOTSUPP; - - num_tc = mqprio->qopt.num_tc; - if (num_tc > AM65_CPSW_PN_TC_NUM) - return -ERANGE; - - if ((mqprio->flags & TC_MQPRIO_F_SHAPER) && - mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) - return -EOPNOTSUPP; - - ret = am65_cpsw_mqprio_verify(port, mqprio); - if (ret) - return ret; - - ret = am65_cpsw_mqprio_verify_shaper(port, mqprio, &max_rate); - if (ret) - return ret; - -skip_check: - ret = pm_runtime_get_sync(common->dev); - if (ret < 0) { - pm_runtime_put_noidle(common->dev); - return ret; - } - - if (mqprio->qopt.hw) { - memcpy(&p_mqprio->mqprio_hw, mqprio, sizeof(*mqprio)); - has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); - p_mqprio->enable = 1; - p_mqprio->shaper_en = has_min_rate; - p_mqprio->shaper_susp = !has_min_rate; - p_mqprio->max_rate_total = max_rate; - } else { - unsigned int tc0_q = p_mqprio->tc0_q; - - memset(p_mqprio, 0, sizeof(*p_mqprio)); - p_mqprio->mqprio_hw.qopt.num_tc = AM65_CPSW_PN_TC_NUM; - p_mqprio->tc0_q = tc0_q; - } - - if (!netif_running(ndev)) - goto exit_put; - - am65_cpsw_qos_mqprio_init(port); - -exit_put: - pm_runtime_put(common->dev); - return 0; -} diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.h b/drivers/net/ethernet/ti/am65-cpsw-qos.h index 247a42788687..0cc2a3b3d7f9 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.h +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.h @@ -7,10 +7,8 @@ #include #include -#include struct am65_cpsw_common; -struct am65_cpsw_port; struct am65_cpsw_est { int buf; @@ -18,16 +16,6 @@ struct am65_cpsw_est { struct tc_taprio_qopt_offload taprio; }; -struct am65_cpsw_mqprio { - struct tc_mqprio_qopt_offload mqprio_hw; - u64 max_rate_total; - - unsigned enable:1; - unsigned shaper_en:1; - unsigned shaper_susp:1; - unsigned tc0_q:3; -}; - struct am65_cpsw_ale_ratelimit { unsigned long cookie; u64 rate_packet_ps; @@ -38,7 +26,6 @@ struct am65_cpsw_qos { struct am65_cpsw_est *est_oper; ktime_t link_down_time; int link_speed; - struct am65_cpsw_mqprio mqprio; struct am65_cpsw_ale_ratelimit ale_bc_ratelimit; struct am65_cpsw_ale_ratelimit ale_mc_ratelimit; @@ -48,7 +35,6 @@ int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, void *type_data); void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed); void am65_cpsw_qos_link_down(struct net_device *ndev); -void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port); int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, int queue, u32 rate_mbps); void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common); -- cgit From 74e7940e0d21328784322b7966d1ec65e9c11c52 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Fri, 11 Aug 2023 08:11:04 -0700 Subject: ice: remove unused methods Following methods were found to no longer be in use: ice_is_pca9575_present ice_mac_fltr_exist ice_napi_del Remove them. Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 15 --------- drivers/net/ethernet/intel/ice/ice_lib.h | 2 -- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 19 ------------ drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 1 - drivers/net/ethernet/intel/ice/ice_switch.c | 48 ----------------------------- drivers/net/ethernet/intel/ice/ice_switch.h | 1 - 6 files changed, 86 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 927518fcad51..54aa01d2a474 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2943,21 +2943,6 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) synchronize_irq(vsi->q_vectors[i]->irq.virq); } -/** - * ice_napi_del - Remove NAPI handler for the VSI - * @vsi: VSI for which NAPI handler is to be removed - */ -void ice_napi_del(struct ice_vsi *vsi) -{ - int v_idx; - - if (!vsi->netdev) - return; - - ice_for_each_q_vector(vsi, v_idx) - netif_napi_del(&vsi->q_vectors[v_idx]->napi); -} - /** * ice_vsi_release - Delete a VSI and free its resources * @vsi: the VSI being removed diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index dd53fe968ad8..cb6599cb8be6 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -93,8 +93,6 @@ void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc); struct ice_vsi * ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params); -void ice_napi_del(struct ice_vsi *vsi); - int ice_vsi_release(struct ice_vsi *vsi); void ice_vsi_close(struct ice_vsi *vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index a38614d21ea8..a0da1bb55ba1 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -3308,25 +3308,6 @@ int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); } -/** - * ice_is_pca9575_present - * @hw: pointer to the hw struct - * - * Check if the SW IO expander is present in the netlist - */ -bool ice_is_pca9575_present(struct ice_hw *hw) -{ - u16 handle = 0; - int status; - - if (!ice_is_e810t(hw)) - return false; - - status = ice_get_pca9575_handle(hw, &handle); - - return !status && handle; -} - /** * ice_ptp_reset_ts_memory - Reset timestamp memory for all blocks * @hw: pointer to the HW struct diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 1969425f0084..07cd023b0efd 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -199,7 +199,6 @@ int ice_ptp_init_phy_e810(struct ice_hw *hw); int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data); int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data); int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data); -bool ice_is_pca9575_present(struct ice_hw *hw); #define PFTSYN_SEM_BYTES 4 diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index a7afb612fe32..24c3f481848b 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -3408,54 +3408,6 @@ exit: return status; } -/** - * ice_mac_fltr_exist - does this MAC filter exist for given VSI - * @hw: pointer to the hardware structure - * @mac: MAC address to be checked (for MAC filter) - * @vsi_handle: check MAC filter for this VSI - */ -bool ice_mac_fltr_exist(struct ice_hw *hw, u8 *mac, u16 vsi_handle) -{ - struct ice_fltr_mgmt_list_entry *entry; - struct list_head *rule_head; - struct ice_switch_info *sw; - struct mutex *rule_lock; /* Lock to protect filter rule list */ - u16 hw_vsi_id; - - if (!ice_is_vsi_valid(hw, vsi_handle)) - return false; - - hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); - sw = hw->switch_info; - rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; - if (!rule_head) - return false; - - rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; - mutex_lock(rule_lock); - list_for_each_entry(entry, rule_head, list_entry) { - struct ice_fltr_info *f_info = &entry->fltr_info; - u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; - - if (is_zero_ether_addr(mac_addr)) - continue; - - if (f_info->flag != ICE_FLTR_TX || - f_info->src_id != ICE_SRC_ID_VSI || - f_info->lkup_type != ICE_SW_LKUP_MAC || - f_info->fltr_act != ICE_FWD_TO_VSI || - hw_vsi_id != f_info->fwd_id.hw_vsi_id) - continue; - - if (ether_addr_equal(mac, mac_addr)) { - mutex_unlock(rule_lock); - return true; - } - } - mutex_unlock(rule_lock); - return false; -} - /** * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 0bd4320e39df..db7e501b7e0a 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -371,7 +371,6 @@ int ice_add_vlan(struct ice_hw *hw, struct list_head *m_list); int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list); int ice_add_mac(struct ice_hw *hw, struct list_head *m_lst); int ice_remove_mac(struct ice_hw *hw, struct list_head *m_lst); -bool ice_mac_fltr_exist(struct ice_hw *hw, u8 *mac, u16 vsi_handle); bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle); int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list); int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list); -- cgit From 708b352fc6938089d5fe9fce91ee51648d611ff1 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:08 +0200 Subject: ice: refactor ice_ddp to make functions static As following methods are not used outside of ice_ddp, they can be made static: ice_verify_pgk ice_pkg_val_buf ice_aq_download_pkg ice_aq_update_pkg ice_find_seg_in_pkg Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_ddp.c | 120 ++++++++++++++++--------------- drivers/net/ethernet/intel/ice/ice_ddp.h | 10 --- 2 files changed, 61 insertions(+), 69 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c index d71ed210f9c4..b27ec93638b6 100644 --- a/drivers/net/ethernet/intel/ice/ice_ddp.c +++ b/drivers/net/ethernet/intel/ice/ice_ddp.c @@ -30,7 +30,7 @@ static const struct ice_tunnel_type_scan tnls[] = { * Verifies various attributes of the package file, including length, format * version, and the requirement of at least one segment. */ -enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) +static enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) { u32 seg_count; u32 i; @@ -118,7 +118,7 @@ static enum ice_ddp_state ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver) * * This helper function validates a buffer's header. */ -struct ice_buf_hdr *ice_pkg_val_buf(struct ice_buf *buf) +static struct ice_buf_hdr *ice_pkg_val_buf(struct ice_buf *buf) { struct ice_buf_hdr *hdr; u16 section_count; @@ -1152,6 +1152,54 @@ static void ice_release_global_cfg_lock(struct ice_hw *hw) ice_release_res(hw, ICE_GLOBAL_CFG_LOCK_RES_ID); } +/** + * ice_aq_download_pkg + * @hw: pointer to the hardware structure + * @pkg_buf: the package buffer to transfer + * @buf_size: the size of the package buffer + * @last_buf: last buffer indicator + * @error_offset: returns error offset + * @error_info: returns error information + * @cd: pointer to command details structure or NULL + * + * Download Package (0x0C40) + */ +static int +ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, + u16 buf_size, bool last_buf, u32 *error_offset, + u32 *error_info, struct ice_sq_cd *cd) +{ + struct ice_aqc_download_pkg *cmd; + struct ice_aq_desc desc; + int status; + + if (error_offset) + *error_offset = 0; + if (error_info) + *error_info = 0; + + cmd = &desc.params.download_pkg; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_download_pkg); + desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); + + if (last_buf) + cmd->flags |= ICE_AQC_DOWNLOAD_PKG_LAST_BUF; + + status = ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd); + if (status == -EIO) { + /* Read error from buffer only when the FW returned an error */ + struct ice_aqc_download_pkg_resp *resp; + + resp = (struct ice_aqc_download_pkg_resp *)pkg_buf; + if (error_offset) + *error_offset = le32_to_cpu(resp->error_offset); + if (error_info) + *error_info = le32_to_cpu(resp->error_info); + } + + return status; +} + /** * ice_dwnld_cfg_bufs * @hw: pointer to the hardware structure @@ -1294,20 +1342,20 @@ static enum ice_ddp_state ice_download_pkg(struct ice_hw *hw, } /** - * ice_aq_download_pkg + * ice_aq_update_pkg * @hw: pointer to the hardware structure - * @pkg_buf: the package buffer to transfer - * @buf_size: the size of the package buffer + * @pkg_buf: the package cmd buffer + * @buf_size: the size of the package cmd buffer * @last_buf: last buffer indicator * @error_offset: returns error offset * @error_info: returns error information * @cd: pointer to command details structure or NULL * - * Download Package (0x0C40) + * Update Package (0x0C42) */ -int ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, - u16 buf_size, bool last_buf, u32 *error_offset, - u32 *error_info, struct ice_sq_cd *cd) +static int ice_aq_update_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, + u16 buf_size, bool last_buf, u32 *error_offset, + u32 *error_info, struct ice_sq_cd *cd) { struct ice_aqc_download_pkg *cmd; struct ice_aq_desc desc; @@ -1319,7 +1367,7 @@ int ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, *error_info = 0; cmd = &desc.params.download_pkg; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_download_pkg); + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_pkg); desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); if (last_buf) @@ -1360,53 +1408,6 @@ int ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, return ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd); } -/** - * ice_aq_update_pkg - * @hw: pointer to the hardware structure - * @pkg_buf: the package cmd buffer - * @buf_size: the size of the package cmd buffer - * @last_buf: last buffer indicator - * @error_offset: returns error offset - * @error_info: returns error information - * @cd: pointer to command details structure or NULL - * - * Update Package (0x0C42) - */ -static int ice_aq_update_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, - u16 buf_size, bool last_buf, u32 *error_offset, - u32 *error_info, struct ice_sq_cd *cd) -{ - struct ice_aqc_download_pkg *cmd; - struct ice_aq_desc desc; - int status; - - if (error_offset) - *error_offset = 0; - if (error_info) - *error_info = 0; - - cmd = &desc.params.download_pkg; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_pkg); - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - - if (last_buf) - cmd->flags |= ICE_AQC_DOWNLOAD_PKG_LAST_BUF; - - status = ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd); - if (status == -EIO) { - /* Read error from buffer only when the FW returned an error */ - struct ice_aqc_download_pkg_resp *resp; - - resp = (struct ice_aqc_download_pkg_resp *)pkg_buf; - if (error_offset) - *error_offset = le32_to_cpu(resp->error_offset); - if (error_info) - *error_info = le32_to_cpu(resp->error_info); - } - - return status; -} - /** * ice_update_pkg_no_lock * @hw: pointer to the hardware structure @@ -1470,8 +1471,9 @@ int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) * success it returns a pointer to the segment header, otherwise it will * return NULL. */ -struct ice_generic_seg_hdr *ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type, - struct ice_pkg_hdr *pkg_hdr) +static struct ice_generic_seg_hdr * +ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type, + struct ice_pkg_hdr *pkg_hdr) { u32 i; diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.h b/drivers/net/ethernet/intel/ice/ice_ddp.h index 41acfe26df1c..abb5f32f2ef4 100644 --- a/drivers/net/ethernet/intel/ice/ice_ddp.h +++ b/drivers/net/ethernet/intel/ice/ice_ddp.h @@ -416,21 +416,13 @@ struct ice_pkg_enum { void *(*handler)(u32 sect_type, void *section, u32 index, u32 *offset); }; -int ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, - u16 buf_size, bool last_buf, u32 *error_offset, - u32 *error_info, struct ice_sq_cd *cd); int ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, u16 buf_size, struct ice_sq_cd *cd); void *ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size); -enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len); - struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw); -struct ice_generic_seg_hdr *ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type, - struct ice_pkg_hdr *pkg_hdr); - int ice_update_pkg_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 count); int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count); @@ -439,6 +431,4 @@ u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld); void *ice_pkg_enum_section(struct ice_seg *ice_seg, struct ice_pkg_enum *state, u32 sect_type); -struct ice_buf_hdr *ice_pkg_val_buf(struct ice_buf *buf); - #endif -- cgit From 45f5478c039c104c03c698c18ac30f21a728208f Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:09 +0200 Subject: ice: refactor ice_lib to make functions static As following methods are not used outside of ice_lib, they can be made static: ice_vsi_is_vlan_pruning_ena ice_vsi_cfg_frame_size Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 70 ++++++++++++++++---------------- drivers/net/ethernet/intel/ice/ice_lib.h | 3 -- 2 files changed, 35 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 54aa01d2a474..d3fb2b7535e7 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1227,6 +1227,20 @@ ice_chnl_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) ctxt->info.q_mapping[1] = cpu_to_le16(qcount); } +/** + * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not + * @vsi: VSI to check whether or not VLAN pruning is enabled. + * + * returns true if Rx VLAN pruning is enabled and false otherwise. + */ +static bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi) +{ + if (!vsi) + return false; + + return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA); +} + /** * ice_vsi_init - Create and initialize a VSI * @vsi: the VSI being configured @@ -1684,6 +1698,27 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) vsi_num, status); } +/** + * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length + * @vsi: VSI + */ +static void ice_vsi_cfg_frame_size(struct ice_vsi *vsi) +{ + if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) { + vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX; + vsi->rx_buf_len = ICE_RXBUF_1664; +#if (PAGE_SIZE < 8192) + } else if (!ICE_2K_TOO_SMALL_WITH_PADDING && + (vsi->netdev->mtu <= ETH_DATA_LEN)) { + vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN; + vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN; +#endif + } else { + vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; + vsi->rx_buf_len = ICE_RXBUF_3072; + } +} + /** * ice_pf_state_is_nominal - checks the PF for nominal state * @pf: pointer to PF to check @@ -1758,27 +1793,6 @@ void ice_update_eth_stats(struct ice_vsi *vsi) vsi->stat_offsets_loaded = true; } -/** - * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length - * @vsi: VSI - */ -void ice_vsi_cfg_frame_size(struct ice_vsi *vsi) -{ - if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) { - vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX; - vsi->rx_buf_len = ICE_RXBUF_1664; -#if (PAGE_SIZE < 8192) - } else if (!ICE_2K_TOO_SMALL_WITH_PADDING && - (vsi->netdev->mtu <= ETH_DATA_LEN)) { - vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN; - vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN; -#endif - } else { - vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; - vsi->rx_buf_len = ICE_RXBUF_3072; - } -} - /** * ice_write_qrxflxp_cntxt - write/configure QRXFLXP_CNTXT register * @hw: HW pointer @@ -2185,20 +2199,6 @@ bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi) return false; } -/** - * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not - * @vsi: VSI to check whether or not VLAN pruning is enabled. - * - * returns true if Rx VLAN pruning is enabled and false otherwise. - */ -bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi) -{ - if (!vsi) - return false; - - return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA); -} - static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) { if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) { diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index cb6599cb8be6..f24f5d1e6f9c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -76,8 +76,6 @@ int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi); int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi); -bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi); - void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create); int ice_set_link(struct ice_vsi *vsi, bool ena); @@ -128,7 +126,6 @@ void ice_update_tx_ring_stats(struct ice_tx_ring *ring, u64 pkts, u64 bytes); void ice_update_rx_ring_stats(struct ice_rx_ring *ring, u64 pkts, u64 bytes); -void ice_vsi_cfg_frame_size(struct ice_vsi *vsi); void ice_write_intrl(struct ice_q_vector *q_vector, u8 intrl); void ice_write_itr(struct ice_ring_container *rc, u16 itr); void ice_set_q_vector_intrl(struct ice_q_vector *q_vector); -- cgit From cc9c60c9edfed4fa629975848e80a45c17332b9a Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:10 +0200 Subject: ice: refactor ice_vf_lib to make functions static As following methods are not used outside ice_vf_lib, they can be made static: ice_vf_rebuild_host_vlan_cfg ice_vf_rebuild_host_tx_rate_cfg ice_vf_set_host_trust_cfg ice_vf_rebuild_host_mac_cfg ice_vf_rebuild_aggregator_node_cfg ice_vf_rebuild_host_cfg ice_set_vf_state_qs_dis ice_vf_set_initialized In order to achieve that, the order in which these were defined was reorganized. Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_vf_lib.c | 468 ++++++++++----------- .../net/ethernet/intel/ice/ice_vf_lib_private.h | 2 - 2 files changed, 234 insertions(+), 236 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index b26ce4425f45..20c4beaa05d8 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -322,6 +322,240 @@ static int ice_vf_rebuild_vsi(struct ice_vf *vf) return 0; } +/** + * ice_vf_rebuild_host_vlan_cfg - add VLAN 0 filter or rebuild the Port VLAN + * @vf: VF to add MAC filters for + * @vsi: Pointer to VSI + * + * Called after a VF VSI has been re-added/rebuilt during reset. The PF driver + * always re-adds either a VLAN 0 or port VLAN based filter after reset. + */ +static int ice_vf_rebuild_host_vlan_cfg(struct ice_vf *vf, struct ice_vsi *vsi) +{ + struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); + struct device *dev = ice_pf_to_dev(vf->pf); + int err; + + if (ice_vf_is_port_vlan_ena(vf)) { + err = vlan_ops->set_port_vlan(vsi, &vf->port_vlan_info); + if (err) { + dev_err(dev, "failed to configure port VLAN via VSI parameters for VF %u, error %d\n", + vf->vf_id, err); + return err; + } + + err = vlan_ops->add_vlan(vsi, &vf->port_vlan_info); + } else { + err = ice_vsi_add_vlan_zero(vsi); + } + + if (err) { + dev_err(dev, "failed to add VLAN %u filter for VF %u during VF rebuild, error %d\n", + ice_vf_is_port_vlan_ena(vf) ? + ice_vf_get_port_vlan_id(vf) : 0, vf->vf_id, err); + return err; + } + + err = vlan_ops->ena_rx_filtering(vsi); + if (err) + dev_warn(dev, "failed to enable Rx VLAN filtering for VF %d VSI %d during VF rebuild, error %d\n", + vf->vf_id, vsi->idx, err); + + return 0; +} + +/** + * ice_vf_rebuild_host_tx_rate_cfg - re-apply the Tx rate limiting configuration + * @vf: VF to re-apply the configuration for + * + * Called after a VF VSI has been re-added/rebuild during reset. The PF driver + * needs to re-apply the host configured Tx rate limiting configuration. + */ +static int ice_vf_rebuild_host_tx_rate_cfg(struct ice_vf *vf) +{ + struct device *dev = ice_pf_to_dev(vf->pf); + struct ice_vsi *vsi = ice_get_vf_vsi(vf); + int err; + + if (WARN_ON(!vsi)) + return -EINVAL; + + if (vf->min_tx_rate) { + err = ice_set_min_bw_limit(vsi, (u64)vf->min_tx_rate * 1000); + if (err) { + dev_err(dev, "failed to set min Tx rate to %d Mbps for VF %u, error %d\n", + vf->min_tx_rate, vf->vf_id, err); + return err; + } + } + + if (vf->max_tx_rate) { + err = ice_set_max_bw_limit(vsi, (u64)vf->max_tx_rate * 1000); + if (err) { + dev_err(dev, "failed to set max Tx rate to %d Mbps for VF %u, error %d\n", + vf->max_tx_rate, vf->vf_id, err); + return err; + } + } + + return 0; +} + +/** + * ice_vf_set_host_trust_cfg - set trust setting based on pre-reset value + * @vf: VF to configure trust setting for + */ +static void ice_vf_set_host_trust_cfg(struct ice_vf *vf) +{ + if (vf->trusted) + set_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); + else + clear_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); +} + +/** + * ice_vf_rebuild_host_mac_cfg - add broadcast and the VF's perm_addr/LAA + * @vf: VF to add MAC filters for + * + * Called after a VF VSI has been re-added/rebuilt during reset. The PF driver + * always re-adds a broadcast filter and the VF's perm_addr/LAA after reset. + */ +static int ice_vf_rebuild_host_mac_cfg(struct ice_vf *vf) +{ + struct device *dev = ice_pf_to_dev(vf->pf); + struct ice_vsi *vsi = ice_get_vf_vsi(vf); + u8 broadcast[ETH_ALEN]; + int status; + + if (WARN_ON(!vsi)) + return -EINVAL; + + if (ice_is_eswitch_mode_switchdev(vf->pf)) + return 0; + + eth_broadcast_addr(broadcast); + status = ice_fltr_add_mac(vsi, broadcast, ICE_FWD_TO_VSI); + if (status) { + dev_err(dev, "failed to add broadcast MAC filter for VF %u, error %d\n", + vf->vf_id, status); + return status; + } + + vf->num_mac++; + + if (is_valid_ether_addr(vf->hw_lan_addr)) { + status = ice_fltr_add_mac(vsi, vf->hw_lan_addr, + ICE_FWD_TO_VSI); + if (status) { + dev_err(dev, "failed to add default unicast MAC filter %pM for VF %u, error %d\n", + &vf->hw_lan_addr[0], vf->vf_id, + status); + return status; + } + vf->num_mac++; + + ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr); + } + + return 0; +} + +/** + * ice_vf_rebuild_aggregator_node_cfg - rebuild aggregator node config + * @vsi: Pointer to VSI + * + * This function moves VSI into corresponding scheduler aggregator node + * based on cached value of "aggregator node info" per VSI + */ +static void ice_vf_rebuild_aggregator_node_cfg(struct ice_vsi *vsi) +{ + struct ice_pf *pf = vsi->back; + struct device *dev; + int status; + + if (!vsi->agg_node) + return; + + dev = ice_pf_to_dev(pf); + if (vsi->agg_node->num_vsis == ICE_MAX_VSIS_IN_AGG_NODE) { + dev_dbg(dev, + "agg_id %u already has reached max_num_vsis %u\n", + vsi->agg_node->agg_id, vsi->agg_node->num_vsis); + return; + } + + status = ice_move_vsi_to_agg(pf->hw.port_info, vsi->agg_node->agg_id, + vsi->idx, vsi->tc_cfg.ena_tc); + if (status) + dev_dbg(dev, "unable to move VSI idx %u into aggregator %u node", + vsi->idx, vsi->agg_node->agg_id); + else + vsi->agg_node->num_vsis++; +} + +/** + * ice_vf_rebuild_host_cfg - host admin configuration is persistent across reset + * @vf: VF to rebuild host configuration on + */ +static void ice_vf_rebuild_host_cfg(struct ice_vf *vf) +{ + struct device *dev = ice_pf_to_dev(vf->pf); + struct ice_vsi *vsi = ice_get_vf_vsi(vf); + + if (WARN_ON(!vsi)) + return; + + ice_vf_set_host_trust_cfg(vf); + + if (ice_vf_rebuild_host_mac_cfg(vf)) + dev_err(dev, "failed to rebuild default MAC configuration for VF %d\n", + vf->vf_id); + + if (ice_vf_rebuild_host_vlan_cfg(vf, vsi)) + dev_err(dev, "failed to rebuild VLAN configuration for VF %u\n", + vf->vf_id); + + if (ice_vf_rebuild_host_tx_rate_cfg(vf)) + dev_err(dev, "failed to rebuild Tx rate limiting configuration for VF %u\n", + vf->vf_id); + + if (ice_vsi_apply_spoofchk(vsi, vf->spoofchk)) + dev_err(dev, "failed to rebuild spoofchk configuration for VF %d\n", + vf->vf_id); + + /* rebuild aggregator node config for main VF VSI */ + ice_vf_rebuild_aggregator_node_cfg(vsi); +} + +/** + * ice_set_vf_state_qs_dis - Set VF queues state to disabled + * @vf: pointer to the VF structure + */ +static void ice_set_vf_state_qs_dis(struct ice_vf *vf) +{ + /* Clear Rx/Tx enabled queues flag */ + bitmap_zero(vf->txq_ena, ICE_MAX_RSS_QS_PER_VF); + bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF); + clear_bit(ICE_VF_STATE_QS_ENA, vf->vf_states); +} + +/** + * ice_vf_set_initialized - VF is ready for VIRTCHNL communication + * @vf: VF to set in initialized state + * + * After this function the VF will be ready to receive/handle the + * VIRTCHNL_OP_GET_VF_RESOURCES message + */ +static void ice_vf_set_initialized(struct ice_vf *vf) +{ + ice_set_vf_state_qs_dis(vf); + clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states); + clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states); + clear_bit(ICE_VF_STATE_DIS, vf->vf_states); + set_bit(ICE_VF_STATE_INIT, vf->vf_states); + memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps)); +} + /** * ice_vf_post_vsi_rebuild - Reset tasks that occur after VSI rebuild * @vf: the VF being reset @@ -725,18 +959,6 @@ out_unlock: return err; } -/** - * ice_set_vf_state_qs_dis - Set VF queues state to disabled - * @vf: pointer to the VF structure - */ -static void ice_set_vf_state_qs_dis(struct ice_vf *vf) -{ - /* Clear Rx/Tx enabled queues flag */ - bitmap_zero(vf->txq_ena, ICE_MAX_RSS_QS_PER_VF); - bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF); - clear_bit(ICE_VF_STATE_QS_ENA, vf->vf_states); -} - /** * ice_set_vf_state_dis - Set VF state to disabled * @vf: pointer to the VF structure @@ -977,211 +1199,6 @@ bool ice_is_vf_link_up(struct ice_vf *vf) ICE_AQ_LINK_UP; } -/** - * ice_vf_set_host_trust_cfg - set trust setting based on pre-reset value - * @vf: VF to configure trust setting for - */ -static void ice_vf_set_host_trust_cfg(struct ice_vf *vf) -{ - if (vf->trusted) - set_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); - else - clear_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); -} - -/** - * ice_vf_rebuild_host_mac_cfg - add broadcast and the VF's perm_addr/LAA - * @vf: VF to add MAC filters for - * - * Called after a VF VSI has been re-added/rebuilt during reset. The PF driver - * always re-adds a broadcast filter and the VF's perm_addr/LAA after reset. - */ -static int ice_vf_rebuild_host_mac_cfg(struct ice_vf *vf) -{ - struct device *dev = ice_pf_to_dev(vf->pf); - struct ice_vsi *vsi = ice_get_vf_vsi(vf); - u8 broadcast[ETH_ALEN]; - int status; - - if (WARN_ON(!vsi)) - return -EINVAL; - - if (ice_is_eswitch_mode_switchdev(vf->pf)) - return 0; - - eth_broadcast_addr(broadcast); - status = ice_fltr_add_mac(vsi, broadcast, ICE_FWD_TO_VSI); - if (status) { - dev_err(dev, "failed to add broadcast MAC filter for VF %u, error %d\n", - vf->vf_id, status); - return status; - } - - vf->num_mac++; - - if (is_valid_ether_addr(vf->hw_lan_addr)) { - status = ice_fltr_add_mac(vsi, vf->hw_lan_addr, - ICE_FWD_TO_VSI); - if (status) { - dev_err(dev, "failed to add default unicast MAC filter %pM for VF %u, error %d\n", - &vf->hw_lan_addr[0], vf->vf_id, - status); - return status; - } - vf->num_mac++; - - ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr); - } - - return 0; -} - -/** - * ice_vf_rebuild_host_vlan_cfg - add VLAN 0 filter or rebuild the Port VLAN - * @vf: VF to add MAC filters for - * @vsi: Pointer to VSI - * - * Called after a VF VSI has been re-added/rebuilt during reset. The PF driver - * always re-adds either a VLAN 0 or port VLAN based filter after reset. - */ -static int ice_vf_rebuild_host_vlan_cfg(struct ice_vf *vf, struct ice_vsi *vsi) -{ - struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); - struct device *dev = ice_pf_to_dev(vf->pf); - int err; - - if (ice_vf_is_port_vlan_ena(vf)) { - err = vlan_ops->set_port_vlan(vsi, &vf->port_vlan_info); - if (err) { - dev_err(dev, "failed to configure port VLAN via VSI parameters for VF %u, error %d\n", - vf->vf_id, err); - return err; - } - - err = vlan_ops->add_vlan(vsi, &vf->port_vlan_info); - } else { - err = ice_vsi_add_vlan_zero(vsi); - } - - if (err) { - dev_err(dev, "failed to add VLAN %u filter for VF %u during VF rebuild, error %d\n", - ice_vf_is_port_vlan_ena(vf) ? - ice_vf_get_port_vlan_id(vf) : 0, vf->vf_id, err); - return err; - } - - err = vlan_ops->ena_rx_filtering(vsi); - if (err) - dev_warn(dev, "failed to enable Rx VLAN filtering for VF %d VSI %d during VF rebuild, error %d\n", - vf->vf_id, vsi->idx, err); - - return 0; -} - -/** - * ice_vf_rebuild_host_tx_rate_cfg - re-apply the Tx rate limiting configuration - * @vf: VF to re-apply the configuration for - * - * Called after a VF VSI has been re-added/rebuild during reset. The PF driver - * needs to re-apply the host configured Tx rate limiting configuration. - */ -static int ice_vf_rebuild_host_tx_rate_cfg(struct ice_vf *vf) -{ - struct device *dev = ice_pf_to_dev(vf->pf); - struct ice_vsi *vsi = ice_get_vf_vsi(vf); - int err; - - if (WARN_ON(!vsi)) - return -EINVAL; - - if (vf->min_tx_rate) { - err = ice_set_min_bw_limit(vsi, (u64)vf->min_tx_rate * 1000); - if (err) { - dev_err(dev, "failed to set min Tx rate to %d Mbps for VF %u, error %d\n", - vf->min_tx_rate, vf->vf_id, err); - return err; - } - } - - if (vf->max_tx_rate) { - err = ice_set_max_bw_limit(vsi, (u64)vf->max_tx_rate * 1000); - if (err) { - dev_err(dev, "failed to set max Tx rate to %d Mbps for VF %u, error %d\n", - vf->max_tx_rate, vf->vf_id, err); - return err; - } - } - - return 0; -} - -/** - * ice_vf_rebuild_aggregator_node_cfg - rebuild aggregator node config - * @vsi: Pointer to VSI - * - * This function moves VSI into corresponding scheduler aggregator node - * based on cached value of "aggregator node info" per VSI - */ -static void ice_vf_rebuild_aggregator_node_cfg(struct ice_vsi *vsi) -{ - struct ice_pf *pf = vsi->back; - struct device *dev; - int status; - - if (!vsi->agg_node) - return; - - dev = ice_pf_to_dev(pf); - if (vsi->agg_node->num_vsis == ICE_MAX_VSIS_IN_AGG_NODE) { - dev_dbg(dev, - "agg_id %u already has reached max_num_vsis %u\n", - vsi->agg_node->agg_id, vsi->agg_node->num_vsis); - return; - } - - status = ice_move_vsi_to_agg(pf->hw.port_info, vsi->agg_node->agg_id, - vsi->idx, vsi->tc_cfg.ena_tc); - if (status) - dev_dbg(dev, "unable to move VSI idx %u into aggregator %u node", - vsi->idx, vsi->agg_node->agg_id); - else - vsi->agg_node->num_vsis++; -} - -/** - * ice_vf_rebuild_host_cfg - host admin configuration is persistent across reset - * @vf: VF to rebuild host configuration on - */ -void ice_vf_rebuild_host_cfg(struct ice_vf *vf) -{ - struct device *dev = ice_pf_to_dev(vf->pf); - struct ice_vsi *vsi = ice_get_vf_vsi(vf); - - if (WARN_ON(!vsi)) - return; - - ice_vf_set_host_trust_cfg(vf); - - if (ice_vf_rebuild_host_mac_cfg(vf)) - dev_err(dev, "failed to rebuild default MAC configuration for VF %d\n", - vf->vf_id); - - if (ice_vf_rebuild_host_vlan_cfg(vf, vsi)) - dev_err(dev, "failed to rebuild VLAN configuration for VF %u\n", - vf->vf_id); - - if (ice_vf_rebuild_host_tx_rate_cfg(vf)) - dev_err(dev, "failed to rebuild Tx rate limiting configuration for VF %u\n", - vf->vf_id); - - if (ice_vsi_apply_spoofchk(vsi, vf->spoofchk)) - dev_err(dev, "failed to rebuild spoofchk configuration for VF %d\n", - vf->vf_id); - - /* rebuild aggregator node config for main VF VSI */ - ice_vf_rebuild_aggregator_node_cfg(vsi); -} - /** * ice_vf_ctrl_invalidate_vsi - invalidate ctrl_vsi_idx to remove VSI access * @vf: VF that control VSI is being invalidated on @@ -1310,23 +1327,6 @@ void ice_vf_vsi_release(struct ice_vf *vf) ice_vf_invalidate_vsi(vf); } -/** - * ice_vf_set_initialized - VF is ready for VIRTCHNL communication - * @vf: VF to set in initialized state - * - * After this function the VF will be ready to receive/handle the - * VIRTCHNL_OP_GET_VF_RESOURCES message - */ -void ice_vf_set_initialized(struct ice_vf *vf) -{ - ice_set_vf_state_qs_dis(vf); - clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states); - clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states); - clear_bit(ICE_VF_STATE_DIS, vf->vf_states); - set_bit(ICE_VF_STATE_INIT, vf->vf_states); - memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps)); -} - /** * ice_get_vf_ctrl_vsi - Get first VF control VSI pointer * @pf: the PF private structure diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h b/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h index 6f3293b793b5..0c7e77c0a09f 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h @@ -32,13 +32,11 @@ int ice_vsi_apply_spoofchk(struct ice_vsi *vsi, bool enable); bool ice_is_vf_trusted(struct ice_vf *vf); bool ice_vf_has_no_qs_ena(struct ice_vf *vf); bool ice_is_vf_link_up(struct ice_vf *vf); -void ice_vf_rebuild_host_cfg(struct ice_vf *vf); void ice_vf_ctrl_invalidate_vsi(struct ice_vf *vf); void ice_vf_ctrl_vsi_release(struct ice_vf *vf); struct ice_vsi *ice_vf_ctrl_vsi_setup(struct ice_vf *vf); int ice_vf_init_host_cfg(struct ice_vf *vf, struct ice_vsi *vsi); void ice_vf_invalidate_vsi(struct ice_vf *vf); void ice_vf_vsi_release(struct ice_vf *vf); -void ice_vf_set_initialized(struct ice_vf *vf); #endif /* _ICE_VF_LIB_PRIVATE_H_ */ -- cgit From 54e852da07150b40de2d451618a557338ae98061 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Thu, 17 Aug 2023 09:59:01 -0700 Subject: ice: Utilize assign_bit() helper The if/else check for bit setting can be replaced by using the assign_bit() helper so do so. Suggested-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_vf_lib.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 20c4beaa05d8..b95931272b16 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -407,10 +407,7 @@ static int ice_vf_rebuild_host_tx_rate_cfg(struct ice_vf *vf) */ static void ice_vf_set_host_trust_cfg(struct ice_vf *vf) { - if (vf->trusted) - set_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); - else - clear_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); + assign_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps, vf->trusted); } /** -- cgit From 9762f8fa832c33cd351cf3efd56ca74e2548dd06 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:11 +0200 Subject: ice: refactor ice_sched to make functions static As ice_sched_set_node_bw_lmt_per_tc is not used outside of ice_sched, it can be made static. Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_sched.c | 2 +- drivers/net/ethernet/intel/ice/ice_sched.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index f4677704b95e..c0533d7b66b9 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -3971,7 +3971,7 @@ ice_sched_get_node_by_id_type(struct ice_port_info *pi, u32 id, * This function sets BW limit of VSI or Aggregator scheduling node * based on TC information from passed in argument BW. */ -int +static int ice_sched_set_node_bw_lmt_per_tc(struct ice_port_info *pi, u32 id, enum ice_agg_type agg_type, u8 tc, enum ice_rl_type rl_type, u32 bw) diff --git a/drivers/net/ethernet/intel/ice/ice_sched.h b/drivers/net/ethernet/intel/ice/ice_sched.h index 8bd26353d76a..0055d9330c07 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.h +++ b/drivers/net/ethernet/intel/ice/ice_sched.h @@ -141,10 +141,6 @@ ice_cfg_vsi_bw_lmt_per_tc(struct ice_port_info *pi, u16 vsi_handle, u8 tc, int ice_cfg_vsi_bw_dflt_lmt_per_tc(struct ice_port_info *pi, u16 vsi_handle, u8 tc, enum ice_rl_type rl_type); -int -ice_sched_set_node_bw_lmt_per_tc(struct ice_port_info *pi, u32 id, - enum ice_agg_type agg_type, u8 tc, - enum ice_rl_type rl_type, u32 bw); int ice_cfg_rl_burst_size(struct ice_hw *hw, u32 bytes); int ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, -- cgit From cae48047052f3baec0fbc0ebf498b19c72753294 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:12 +0200 Subject: ice: refactor ice_ptp_hw to make functions static As following methods are not used outside ice_ptp_hw, they can be made static: ice_read_phy_reg_e822 ice_write_phy_reg_e822 ice_ptp_prep_port_adj_e822 Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 6 +++--- drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index a0da1bb55ba1..68e2d5ca01f3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -293,7 +293,7 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) * * Read a PHY register for the given port over the device sideband queue. */ -int +static int ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) { struct ice_sbq_msg_input msg = {0}; @@ -370,7 +370,7 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) * * Write a PHY register for the given port over the device sideband queue. */ -int +static int ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) { struct ice_sbq_msg_input msg = {0}; @@ -1079,7 +1079,7 @@ exit_err: * * Negative adjustments are supported using 2s complement arithmetic. */ -int +static int ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) { u32 l_time, u_time; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 07cd023b0efd..13547707b8e3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -141,11 +141,8 @@ int ice_ptp_init_phc(struct ice_hw *hw); int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready); /* E822 family functions */ -int ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val); -int ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val); int ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val); int ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val); -int ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time); void ice_ptp_reset_ts_memory_quad_e822(struct ice_hw *hw, u8 quad); /** -- cgit From e528e5b237550b9c9f738a7e56174e5195c925d3 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 9 Aug 2023 15:39:13 +0200 Subject: ice: refactor ice_vsi_is_vlan_pruning_ena As this method became static, and is already called with check for vsi being non-null, an unnecessary check along with superfluous parentheses is removed. Signed-off-by: Jan Sokolowski Reviewed-by: Jacob Keller Reviewed-by: Przemek Kitszel Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index d3fb2b7535e7..201570cd2e0b 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1235,10 +1235,7 @@ ice_chnl_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) */ static bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi) { - if (!vsi) - return false; - - return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA); + return vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; } /** -- cgit From 403e48539b160cd43f4ce67c641496b9911ff916 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 11 Jul 2023 16:47:34 -0700 Subject: ice: move E810T functions to before device agnostic ones Commit 885fe6932a11 ("ice: Add support for SMA control multiplexer") accidentally placed all of the E810T SMA control functions in the middle of the device agnostic functions section of ice_ptp_hw.c This works fine, but makes it harder for readers to follow. The ice_ptp_hw.c file is laid out such that each hardware family has the specific functions in one block, with the access functions placed at the end of the file. Move the E810T functions so that they are in a block just after the E810 functions. Also move the ice_get_phy_tx_tstamp_ready_e810 which got added at the end of the E810T block. This keeps the functions laid out in a logical order and avoids intermixing the generic access functions with the device specific implementations. Signed-off-by: Jacob Keller Reviewed-by: Przemek Kitszel Tested-by: Arpana Arland (A Contingent worker at Intel) Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 358 ++++++++++++++-------------- 1 file changed, 179 insertions(+), 179 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index 68e2d5ca01f3..5a6ffa738396 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -2869,6 +2869,185 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) return 0; } +/** + * ice_get_phy_tx_tstamp_ready_e810 - Read Tx memory status register + * @hw: pointer to the HW struct + * @port: the PHY port to read + * @tstamp_ready: contents of the Tx memory status register + * + * E810 devices do not use a Tx memory status register. Instead simply + * indicate that all timestamps are currently ready. + */ +static int +ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready) +{ + *tstamp_ready = 0xFFFFFFFFFFFFFFFF; + return 0; +} + +/* E810T SMA functions + * + * The following functions operate specifically on E810T hardware and are used + * to access the extended GPIOs available. + */ + +/** + * ice_get_pca9575_handle + * @hw: pointer to the hw struct + * @pca9575_handle: GPIO controller's handle + * + * Find and return the GPIO controller's handle in the netlist. + * When found - the value will be cached in the hw structure and following calls + * will return cached value + */ +static int +ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle) +{ + struct ice_aqc_get_link_topo *cmd; + struct ice_aq_desc desc; + int status; + u8 idx; + + /* If handle was read previously return cached value */ + if (hw->io_expander_handle) { + *pca9575_handle = hw->io_expander_handle; + return 0; + } + + /* If handle was not detected read it from the netlist */ + cmd = &desc.params.get_link_topo; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); + + /* Set node type to GPIO controller */ + cmd->addr.topo_params.node_type_ctx = + (ICE_AQC_LINK_TOPO_NODE_TYPE_M & + ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL); + +#define SW_PCA9575_SFP_TOPO_IDX 2 +#define SW_PCA9575_QSFP_TOPO_IDX 1 + + /* Check if the SW IO expander controlling SMA exists in the netlist. */ + if (hw->device_id == ICE_DEV_ID_E810C_SFP) + idx = SW_PCA9575_SFP_TOPO_IDX; + else if (hw->device_id == ICE_DEV_ID_E810C_QSFP) + idx = SW_PCA9575_QSFP_TOPO_IDX; + else + return -EOPNOTSUPP; + + cmd->addr.topo_params.index = idx; + + status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); + if (status) + return -EOPNOTSUPP; + + /* Verify if we found the right IO expander type */ + if (desc.params.get_link_topo.node_part_num != + ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575) + return -EOPNOTSUPP; + + /* If present save the handle and return it */ + hw->io_expander_handle = + le16_to_cpu(desc.params.get_link_topo.addr.handle); + *pca9575_handle = hw->io_expander_handle; + + return 0; +} + +/** + * ice_read_sma_ctrl_e810t + * @hw: pointer to the hw struct + * @data: pointer to data to be read from the GPIO controller + * + * Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the + * PCA9575 expander, so only bits 3-7 in data are valid. + */ +int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data) +{ + int status; + u16 handle; + u8 i; + + status = ice_get_pca9575_handle(hw, &handle); + if (status) + return status; + + *data = 0; + + for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { + bool pin; + + status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, + &pin, NULL); + if (status) + break; + *data |= (u8)(!pin) << i; + } + + return status; +} + +/** + * ice_write_sma_ctrl_e810t + * @hw: pointer to the hw struct + * @data: data to be written to the GPIO controller + * + * Write the data to the SMA controller. It is connected to pins 3-7 of Port 1 + * of the PCA9575 expander, so only bits 3-7 in data are valid. + */ +int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data) +{ + int status; + u16 handle; + u8 i; + + status = ice_get_pca9575_handle(hw, &handle); + if (status) + return status; + + for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { + bool pin; + + pin = !(data & (1 << i)); + status = ice_aq_set_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, + pin, NULL); + if (status) + break; + } + + return status; +} + +/** + * ice_read_pca9575_reg_e810t + * @hw: pointer to the hw struct + * @offset: GPIO controller register offset + * @data: pointer to data to be read from the GPIO controller + * + * Read the register from the GPIO controller + */ +int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) +{ + struct ice_aqc_link_topo_addr link_topo; + __le16 addr; + u16 handle; + int err; + + memset(&link_topo, 0, sizeof(link_topo)); + + err = ice_get_pca9575_handle(hw, &handle); + if (err) + return err; + + link_topo.handle = cpu_to_le16(handle); + link_topo.topo_params.node_type_ctx = + FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, + ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED); + + addr = cpu_to_le16((u16)offset); + + return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); +} + /* Device agnostic functions * * The following functions implement shared behavior common to both E822 and @@ -3129,185 +3308,6 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) return ice_clear_phy_tstamp_e822(hw, block, idx); } -/** - * ice_get_phy_tx_tstamp_ready_e810 - Read Tx memory status register - * @hw: pointer to the HW struct - * @port: the PHY port to read - * @tstamp_ready: contents of the Tx memory status register - * - * E810 devices do not use a Tx memory status register. Instead simply - * indicate that all timestamps are currently ready. - */ -static int -ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready) -{ - *tstamp_ready = 0xFFFFFFFFFFFFFFFF; - return 0; -} - -/* E810T SMA functions - * - * The following functions operate specifically on E810T hardware and are used - * to access the extended GPIOs available. - */ - -/** - * ice_get_pca9575_handle - * @hw: pointer to the hw struct - * @pca9575_handle: GPIO controller's handle - * - * Find and return the GPIO controller's handle in the netlist. - * When found - the value will be cached in the hw structure and following calls - * will return cached value - */ -static int -ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle) -{ - struct ice_aqc_get_link_topo *cmd; - struct ice_aq_desc desc; - int status; - u8 idx; - - /* If handle was read previously return cached value */ - if (hw->io_expander_handle) { - *pca9575_handle = hw->io_expander_handle; - return 0; - } - - /* If handle was not detected read it from the netlist */ - cmd = &desc.params.get_link_topo; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); - - /* Set node type to GPIO controller */ - cmd->addr.topo_params.node_type_ctx = - (ICE_AQC_LINK_TOPO_NODE_TYPE_M & - ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL); - -#define SW_PCA9575_SFP_TOPO_IDX 2 -#define SW_PCA9575_QSFP_TOPO_IDX 1 - - /* Check if the SW IO expander controlling SMA exists in the netlist. */ - if (hw->device_id == ICE_DEV_ID_E810C_SFP) - idx = SW_PCA9575_SFP_TOPO_IDX; - else if (hw->device_id == ICE_DEV_ID_E810C_QSFP) - idx = SW_PCA9575_QSFP_TOPO_IDX; - else - return -EOPNOTSUPP; - - cmd->addr.topo_params.index = idx; - - status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); - if (status) - return -EOPNOTSUPP; - - /* Verify if we found the right IO expander type */ - if (desc.params.get_link_topo.node_part_num != - ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575) - return -EOPNOTSUPP; - - /* If present save the handle and return it */ - hw->io_expander_handle = - le16_to_cpu(desc.params.get_link_topo.addr.handle); - *pca9575_handle = hw->io_expander_handle; - - return 0; -} - -/** - * ice_read_sma_ctrl_e810t - * @hw: pointer to the hw struct - * @data: pointer to data to be read from the GPIO controller - * - * Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the - * PCA9575 expander, so only bits 3-7 in data are valid. - */ -int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data) -{ - int status; - u16 handle; - u8 i; - - status = ice_get_pca9575_handle(hw, &handle); - if (status) - return status; - - *data = 0; - - for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { - bool pin; - - status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, - &pin, NULL); - if (status) - break; - *data |= (u8)(!pin) << i; - } - - return status; -} - -/** - * ice_write_sma_ctrl_e810t - * @hw: pointer to the hw struct - * @data: data to be written to the GPIO controller - * - * Write the data to the SMA controller. It is connected to pins 3-7 of Port 1 - * of the PCA9575 expander, so only bits 3-7 in data are valid. - */ -int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data) -{ - int status; - u16 handle; - u8 i; - - status = ice_get_pca9575_handle(hw, &handle); - if (status) - return status; - - for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { - bool pin; - - pin = !(data & (1 << i)); - status = ice_aq_set_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, - pin, NULL); - if (status) - break; - } - - return status; -} - -/** - * ice_read_pca9575_reg_e810t - * @hw: pointer to the hw struct - * @offset: GPIO controller register offset - * @data: pointer to data to be read from the GPIO controller - * - * Read the register from the GPIO controller - */ -int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) -{ - struct ice_aqc_link_topo_addr link_topo; - __le16 addr; - u16 handle; - int err; - - memset(&link_topo, 0, sizeof(link_topo)); - - err = ice_get_pca9575_handle(hw, &handle); - if (err) - return err; - - link_topo.handle = cpu_to_le16(handle); - link_topo.topo_params.node_type_ctx = - FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, - ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED); - - addr = cpu_to_le16((u16)offset); - - return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); -} - /** * ice_ptp_reset_ts_memory - Reset timestamp memory for all blocks * @hw: pointer to the HW struct -- cgit From 467a17eea5c374cc4dd6a827e96dab5963df3793 Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Mon, 31 Jul 2023 04:42:01 +0200 Subject: ice: Remove redundant VSI configuration in eswitch setup Remove a call to disable VLAN stripping on switchdev control plane VSI, as it is disabled by default. Signed-off-by: Marcin Szycik Tested-by: Sujai Buvaneswaran Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index 9a53a5e5d73e..62b54100273f 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -84,10 +84,6 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) struct ice_vsi_vlan_ops *vlan_ops; bool rule_added = false; - vlan_ops = ice_get_compat_vsi_vlan_ops(ctrl_vsi); - if (vlan_ops->dis_stripping(ctrl_vsi)) - return -ENODEV; - ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx); netif_addr_lock_bh(uplink_netdev); -- cgit From 1533b7743d35dc88808291b7f552697c8ee87f22 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 2 Aug 2023 17:07:39 +0800 Subject: ice: use list_for_each_entry() helper Convert list_for_each() to list_for_each_entry() where applicable. No functional changed. Signed-off-by: Yang Yingliang Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 36b7044717e8..a68974c1aa38 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -129,11 +129,9 @@ ice_lag_find_hw_by_lport(struct ice_lag *lag, u8 lport) struct ice_lag_netdev_list *entry; struct net_device *tmp_netdev; struct ice_netdev_priv *np; - struct list_head *tmp; struct ice_hw *hw; - list_for_each(tmp, lag->netdev_head) { - entry = list_entry(tmp, struct ice_lag_netdev_list, node); + list_for_each_entry(entry, lag->netdev_head, node) { tmp_netdev = entry->netdev; if (!tmp_netdev || !netif_is_ice(tmp_netdev)) continue; @@ -1535,11 +1533,9 @@ static void ice_lag_disable_sriov_bond(struct ice_lag *lag) struct ice_lag_netdev_list *entry; struct ice_netdev_priv *np; struct net_device *netdev; - struct list_head *tmp; struct ice_pf *pf; - list_for_each(tmp, lag->netdev_head) { - entry = list_entry(tmp, struct ice_lag_netdev_list, node); + list_for_each_entry(entry, lag->netdev_head, node) { netdev = entry->netdev; np = netdev_priv(netdev); pf = np->vsi->back; -- cgit From 52da2fb2693a7525fc3a0474978b4441ee272492 Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Mon, 31 Jul 2023 11:01:52 -0400 Subject: ice: drop two params from ice_aq_alloc_free_res() Drop @num_entries and @cd params, latter of which was always NULL. Number of entities to alloc is passed in internal buffer, the outer layer (that @num_entries was assigned to) meaning is closer to "the number of requests", which was =1 in all cases. ice_free_hw_res() was always called with 1 as its @num arg. Signed-off-by: Przemek Kitszel Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_common.c | 24 ++++++++---------------- drivers/net/ethernet/intel/ice/ice_common.h | 7 +++---- drivers/net/ethernet/intel/ice/ice_lag.c | 9 ++++----- drivers/net/ethernet/intel/ice/ice_switch.c | 16 +++++++--------- 4 files changed, 22 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index a86255b529a0..80deca45ab59 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2000,37 +2000,31 @@ void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res) /** * ice_aq_alloc_free_res - command to allocate/free resources * @hw: pointer to the HW struct - * @num_entries: number of resource entries in buffer * @buf: Indirect buffer to hold data parameters and response * @buf_size: size of buffer for indirect commands * @opc: pass in the command opcode - * @cd: pointer to command details structure or NULL * * Helper function to allocate/free resources using the admin queue commands */ -int -ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, - struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, - enum ice_adminq_opc opc, struct ice_sq_cd *cd) +int ice_aq_alloc_free_res(struct ice_hw *hw, + struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, + enum ice_adminq_opc opc) { struct ice_aqc_alloc_free_res_cmd *cmd; struct ice_aq_desc desc; cmd = &desc.params.sw_res_ctrl; - if (!buf) - return -EINVAL; - - if (buf_size < flex_array_size(buf, elem, num_entries)) + if (!buf || buf_size < flex_array_size(buf, elem, 1)) return -EINVAL; ice_fill_dflt_direct_cmd_desc(&desc, opc); desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - cmd->num_entries = cpu_to_le16(num_entries); + cmd->num_entries = cpu_to_le16(1); - return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); + return ice_aq_send_cmd(hw, &desc, buf, buf_size, NULL); } /** @@ -2060,8 +2054,7 @@ ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res) if (btm) buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM); - status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, - ice_aqc_opc_alloc_res, NULL); + status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res); if (status) goto ice_alloc_res_exit; @@ -2095,8 +2088,7 @@ int ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res) buf->res_type = cpu_to_le16(type); memcpy(buf->elem, res, sizeof(*buf->elem) * num); - status = ice_aq_alloc_free_res(hw, num, buf, buf_len, - ice_aqc_opc_free_res, NULL); + status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res); if (status) ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 71b82cdf4a6d..226b81f97a92 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -38,10 +38,9 @@ int ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res); int ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res); -int -ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, - struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, - enum ice_adminq_opc opc, struct ice_sq_cd *cd); +int ice_aq_alloc_free_res(struct ice_hw *hw, + struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, + enum ice_adminq_opc opc); bool ice_is_sbq_supported(struct ice_hw *hw); struct ice_ctl_q_info *ice_get_sbq(struct ice_hw *hw); int diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index a68974c1aa38..4f39863b5537 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -983,9 +983,8 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, /* if unlinnking need to free the shared resource */ if (!link && local_lag->bond_swid) { buf->elem[0].e.sw_resp = cpu_to_le16(local_lag->bond_swid); - status = ice_aq_alloc_free_res(&local_lag->pf->hw, 1, buf, - buf_len, ice_aqc_opc_free_res, - NULL); + status = ice_aq_alloc_free_res(&local_lag->pf->hw, buf, + buf_len, ice_aqc_opc_free_res); if (status) dev_err(ice_pf_to_dev(local_lag->pf), "Error freeing SWID during LAG unlink\n"); local_lag->bond_swid = 0; @@ -1002,8 +1001,8 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag, cpu_to_le16(local_lag->pf->hw.port_info->sw_id); } - status = ice_aq_alloc_free_res(&local_lag->pf->hw, 1, buf, buf_len, - ice_aqc_opc_alloc_res, NULL); + status = ice_aq_alloc_free_res(&local_lag->pf->hw, buf, buf_len, + ice_aqc_opc_alloc_res); if (status) dev_err(ice_pf_to_dev(local_lag->pf), "Error subscribing to SWID 0x%04X\n", local_lag->bond_swid); diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 24c3f481848b..2f77b684ff76 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1847,7 +1847,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, if (opc == ice_aqc_opc_free_res) sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id); - status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); + status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, opc); if (status) goto ice_aq_alloc_free_vsi_list_exit; @@ -2101,8 +2101,8 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid) sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE << ICE_AQC_RES_TYPE_S) | ICE_AQC_RES_TYPE_FLAG_SHARED); - status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, - ice_aqc_opc_alloc_res, NULL); + status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, + ice_aqc_opc_alloc_res); if (!status) *rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp); kfree(sw_buf); @@ -4448,8 +4448,7 @@ ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & ICE_AQC_RES_TYPE_M) | alloc_shared); - status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, - ice_aqc_opc_alloc_res, NULL); + status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res); if (status) goto exit; @@ -4487,8 +4486,7 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, ICE_AQC_RES_TYPE_M) | alloc_shared); buf->elem[0].e.sw_resp = cpu_to_le16(counter_id); - status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, - ice_aqc_opc_free_res, NULL); + status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res); if (status) ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n"); @@ -4530,8 +4528,8 @@ int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id) ~ICE_AQC_RES_TYPE_FLAG_SHARED); buf->elem[0].e.sw_resp = cpu_to_le16(res_id); - status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, - ice_aqc_opc_share_res, NULL); + status = ice_aq_alloc_free_res(hw, buf, buf_len, + ice_aqc_opc_share_res); if (status) ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n", type, res_id, shared ? "SHARED" : "DEDICATED"); -- cgit From e1e8a142c43336e3d25bfa1cb3a4ae7d00875c48 Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Tue, 8 Aug 2023 17:54:15 -0400 Subject: ice: ice_aq_check_events: fix off-by-one check when filling buffer Allow task's event buffer to be filled also in the case that it's size is exactly the size of the message. Fixes: d69ea414c9b4 ("ice: implement device flash update via devlink") Reviewed-by: Jacob Keller Signed-off-by: Przemek Kitszel Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 0f04347eda39..872bd5572294 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1357,6 +1357,7 @@ int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, static void ice_aq_check_events(struct ice_pf *pf, u16 opcode, struct ice_rq_event_info *event) { + struct ice_rq_event_info *task_ev; struct ice_aq_task *task; bool found = false; @@ -1365,15 +1366,15 @@ static void ice_aq_check_events(struct ice_pf *pf, u16 opcode, if (task->state || task->opcode != opcode) continue; - memcpy(&task->event->desc, &event->desc, sizeof(event->desc)); - task->event->msg_len = event->msg_len; + task_ev = task->event; + memcpy(&task_ev->desc, &event->desc, sizeof(event->desc)); + task_ev->msg_len = event->msg_len; /* Only copy the data buffer if a destination was set */ - if (task->event->msg_buf && - task->event->buf_len > event->buf_len) { - memcpy(task->event->msg_buf, event->msg_buf, + if (task_ev->msg_buf && task_ev->buf_len >= event->buf_len) { + memcpy(task_ev->msg_buf, event->msg_buf, event->buf_len); - task->event->buf_len = event->buf_len; + task_ev->buf_len = event->buf_len; } task->state = ICE_AQ_TASK_COMPLETE; -- cgit From b214b98a7fc4dfcce7b67b2e08a22b7fe62c55d0 Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Tue, 8 Aug 2023 17:54:16 -0400 Subject: ice: embed &ice_rq_event_info event into struct ice_aq_task Expose struct ice_aq_task to callers, what takes burden of memory ownership out from AQ-wait family of functions, and reduces need for heap-based allocations. Embed struct ice_rq_event_info event into struct ice_aq_task (instead of it being a ptr) to remove some more code from the callers. Subsequent commit will improve more based on this one. Reviewed-by: Jacob Keller Signed-off-by: Przemek Kitszel Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 18 +++++++++-- drivers/net/ethernet/intel/ice/ice_fw_update.c | 42 ++++++++++++-------------- drivers/net/ethernet/intel/ice/ice_main.c | 29 +++--------------- 3 files changed, 40 insertions(+), 49 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 5ac0ad12f9f1..9a334287bd92 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -917,8 +917,22 @@ void ice_fdir_release_flows(struct ice_hw *hw); void ice_fdir_replay_flows(struct ice_hw *hw); void ice_fdir_replay_fltrs(struct ice_pf *pf); int ice_fdir_create_dflt_rules(struct ice_pf *pf); -int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, - struct ice_rq_event_info *event); + +enum ice_aq_task_state { + ICE_AQ_TASK_WAITING, + ICE_AQ_TASK_COMPLETE, + ICE_AQ_TASK_CANCELED, +}; + +struct ice_aq_task { + struct hlist_node entry; + struct ice_rq_event_info event; + enum ice_aq_task_state state; + u16 opcode; +}; + +int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, + u16 opcode, unsigned long timeout); int ice_open(struct net_device *netdev); int ice_open_internal(struct net_device *netdev); int ice_stop(struct net_device *netdev); diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c index 3dc5662d62a6..819b70823e9c 100644 --- a/drivers/net/ethernet/intel/ice/ice_fw_update.c +++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c @@ -293,13 +293,12 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, { u16 completion_module, completion_retval; struct device *dev = ice_pf_to_dev(pf); - struct ice_rq_event_info event; + struct ice_aq_task task = {}; struct ice_hw *hw = &pf->hw; + struct ice_aq_desc *desc; u32 completion_offset; int err; - memset(&event, 0, sizeof(event)); - dev_dbg(dev, "Writing block of %u bytes for module 0x%02x at offset %u\n", block_size, module, offset); @@ -319,7 +318,7 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, * is conservative and is intended to prevent failure to update when * firmware is slow to respond. */ - err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write, 15 * HZ, &event); + err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_write, 15 * HZ); if (err) { dev_err(dev, "Timed out while trying to flash module 0x%02x with block of size %u at offset %u, err %d\n", module, block_size, offset, err); @@ -327,11 +326,12 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, return -EIO; } - completion_module = le16_to_cpu(event.desc.params.nvm.module_typeid); - completion_retval = le16_to_cpu(event.desc.retval); + desc = &task.event.desc; + completion_module = le16_to_cpu(desc->params.nvm.module_typeid); + completion_retval = le16_to_cpu(desc->retval); - completion_offset = le16_to_cpu(event.desc.params.nvm.offset_low); - completion_offset |= event.desc.params.nvm.offset_high << 16; + completion_offset = le16_to_cpu(desc->params.nvm.offset_low); + completion_offset |= desc->params.nvm.offset_high << 16; if (completion_module != module) { dev_err(dev, "Unexpected module_typeid in write completion: got 0x%x, expected 0x%x\n", @@ -363,8 +363,8 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, */ if (reset_level && last_cmd && module == ICE_SR_1ST_NVM_BANK_PTR) { if (hw->dev_caps.common_cap.pcie_reset_avoidance) { - *reset_level = (event.desc.params.nvm.cmd_flags & - ICE_AQC_NVM_RESET_LVL_M); + *reset_level = desc->params.nvm.cmd_flags & + ICE_AQC_NVM_RESET_LVL_M; dev_dbg(dev, "Firmware reported required reset level as %u\n", *reset_level); } else { @@ -479,15 +479,14 @@ ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, { u16 completion_module, completion_retval; struct device *dev = ice_pf_to_dev(pf); - struct ice_rq_event_info event; + struct ice_aq_task task = {}; struct ice_hw *hw = &pf->hw; + struct ice_aq_desc *desc; struct devlink *devlink; int err; dev_dbg(dev, "Beginning erase of flash component '%s', module 0x%02x\n", component, module); - memset(&event, 0, sizeof(event)); - devlink = priv_to_devlink(pf); devlink_flash_update_timeout_notify(devlink, "Erasing", component, ICE_FW_ERASE_TIMEOUT); @@ -502,7 +501,7 @@ ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, goto out_notify_devlink; } - err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_erase, ICE_FW_ERASE_TIMEOUT * HZ, &event); + err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_erase, ICE_FW_ERASE_TIMEOUT * HZ); if (err) { dev_err(dev, "Timed out waiting for firmware to respond with erase completion for %s (module 0x%02x), err %d\n", component, module, err); @@ -510,8 +509,9 @@ ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, goto out_notify_devlink; } - completion_module = le16_to_cpu(event.desc.params.nvm.module_typeid); - completion_retval = le16_to_cpu(event.desc.retval); + desc = &task.event.desc; + completion_module = le16_to_cpu(desc->params.nvm.module_typeid); + completion_retval = le16_to_cpu(desc->retval); if (completion_module != module) { dev_err(dev, "Unexpected module_typeid in erase completion for %s: got 0x%x, expected 0x%x\n", @@ -560,14 +560,12 @@ ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, u8 *emp_reset_available, struct netlink_ext_ack *extack) { struct device *dev = ice_pf_to_dev(pf); - struct ice_rq_event_info event; + struct ice_aq_task task = {}; struct ice_hw *hw = &pf->hw; u16 completion_retval; u8 response_flags; int err; - memset(&event, 0, sizeof(event)); - err = ice_nvm_write_activate(hw, activate_flags, &response_flags); if (err) { dev_err(dev, "Failed to switch active flash banks, err %d aq_err %s\n", @@ -592,8 +590,8 @@ ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, } } - err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write_activate, 30 * HZ, - &event); + err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_write_activate, + 30 * HZ); if (err) { dev_err(dev, "Timed out waiting for firmware to switch active flash banks, err %d\n", err); @@ -601,7 +599,7 @@ ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, return err; } - completion_retval = le16_to_cpu(event.desc.retval); + completion_retval = le16_to_cpu(task.event.desc.retval); if (completion_retval) { dev_err(dev, "Firmware failed to switch active flash banks aq_err %s\n", ice_aq_str((enum ice_aq_err)completion_retval)); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 872bd5572294..b08be6700b2a 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1250,26 +1250,12 @@ ice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event) return status; } -enum ice_aq_task_state { - ICE_AQ_TASK_WAITING = 0, - ICE_AQ_TASK_COMPLETE, - ICE_AQ_TASK_CANCELED, -}; - -struct ice_aq_task { - struct hlist_node entry; - - u16 opcode; - struct ice_rq_event_info *event; - enum ice_aq_task_state state; -}; - /** * ice_aq_wait_for_event - Wait for an AdminQ event from firmware * @pf: pointer to the PF private structure + * @task: ptr to task structure * @opcode: the opcode to wait for * @timeout: how long to wait, in jiffies - * @event: storage for the event info * * Waits for a specific AdminQ completion event on the ARQ for a given PF. The * current thread will be put to sleep until the specified event occurs or @@ -1281,22 +1267,16 @@ struct ice_aq_task { * * Returns: zero on success, or a negative error code on failure. */ -int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, - struct ice_rq_event_info *event) +int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, + u16 opcode, unsigned long timeout) { struct device *dev = ice_pf_to_dev(pf); - struct ice_aq_task *task; unsigned long start; long ret; int err; - task = kzalloc(sizeof(*task), GFP_KERNEL); - if (!task) - return -ENOMEM; - INIT_HLIST_NODE(&task->entry); task->opcode = opcode; - task->event = event; task->state = ICE_AQ_TASK_WAITING; spin_lock_bh(&pf->aq_wait_lock); @@ -1331,7 +1311,6 @@ int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, spin_lock_bh(&pf->aq_wait_lock); hlist_del(&task->entry); spin_unlock_bh(&pf->aq_wait_lock); - kfree(task); return err; } @@ -1366,7 +1345,7 @@ static void ice_aq_check_events(struct ice_pf *pf, u16 opcode, if (task->state || task->opcode != opcode) continue; - task_ev = task->event; + task_ev = &task->event; memcpy(&task_ev->desc, &event->desc, sizeof(event->desc)); task_ev->msg_len = event->msg_len; -- cgit From fb9840c4ec13629f36c5e0e88a5df78ca2acc3e0 Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Tue, 8 Aug 2023 17:54:17 -0400 Subject: ice: split ice_aq_wait_for_event() func into two Mitigate race between registering on wait list and receiving AQ Response from FW. ice_aq_prep_for_event() should be called before sending AQ command, ice_aq_wait_for_event() should be called after sending AQ command, to wait for AQ Response. Please note, that this was found by reading the code, an actual race has not yet materialized. Reviewed-by: Jacob Keller Signed-off-by: Przemek Kitszel Reviewed-by: Simon Horman Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 5 +- drivers/net/ethernet/intel/ice/ice_fw_update.c | 13 +++-- drivers/net/ethernet/intel/ice/ice_main.c | 67 +++++++++++++++++--------- 3 files changed, 57 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 9a334287bd92..5022b036ca4f 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -919,6 +919,7 @@ void ice_fdir_replay_fltrs(struct ice_pf *pf); int ice_fdir_create_dflt_rules(struct ice_pf *pf); enum ice_aq_task_state { + ICE_AQ_TASK_NOT_PREPARED, ICE_AQ_TASK_WAITING, ICE_AQ_TASK_COMPLETE, ICE_AQ_TASK_CANCELED, @@ -931,8 +932,10 @@ struct ice_aq_task { u16 opcode; }; +void ice_aq_prep_for_event(struct ice_pf *pf, struct ice_aq_task *task, + u16 opcode); int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, - u16 opcode, unsigned long timeout); + unsigned long timeout); int ice_open(struct net_device *netdev); int ice_open_internal(struct net_device *netdev); int ice_stop(struct net_device *netdev); diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c index 819b70823e9c..319a2d6fe26c 100644 --- a/drivers/net/ethernet/intel/ice/ice_fw_update.c +++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c @@ -302,6 +302,8 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, dev_dbg(dev, "Writing block of %u bytes for module 0x%02x at offset %u\n", block_size, module, offset); + ice_aq_prep_for_event(pf, &task, ice_aqc_opc_nvm_write); + err = ice_aq_update_nvm(hw, module, offset, block_size, block, last_cmd, 0, NULL); if (err) { @@ -318,7 +320,7 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, * is conservative and is intended to prevent failure to update when * firmware is slow to respond. */ - err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_write, 15 * HZ); + err = ice_aq_wait_for_event(pf, &task, 15 * HZ); if (err) { dev_err(dev, "Timed out while trying to flash module 0x%02x with block of size %u at offset %u, err %d\n", module, block_size, offset, err); @@ -491,6 +493,8 @@ ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, devlink_flash_update_timeout_notify(devlink, "Erasing", component, ICE_FW_ERASE_TIMEOUT); + ice_aq_prep_for_event(pf, &task, ice_aqc_opc_nvm_erase); + err = ice_aq_erase_nvm(hw, module, NULL); if (err) { dev_err(dev, "Failed to erase %s (module 0x%02x), err %d aq_err %s\n", @@ -501,7 +505,7 @@ ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, goto out_notify_devlink; } - err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_erase, ICE_FW_ERASE_TIMEOUT * HZ); + err = ice_aq_wait_for_event(pf, &task, ICE_FW_ERASE_TIMEOUT * HZ); if (err) { dev_err(dev, "Timed out waiting for firmware to respond with erase completion for %s (module 0x%02x), err %d\n", component, module, err); @@ -566,6 +570,8 @@ ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, u8 response_flags; int err; + ice_aq_prep_for_event(pf, &task, ice_aqc_opc_nvm_write_activate); + err = ice_nvm_write_activate(hw, activate_flags, &response_flags); if (err) { dev_err(dev, "Failed to switch active flash banks, err %d aq_err %s\n", @@ -590,8 +596,7 @@ ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, } } - err = ice_aq_wait_for_event(pf, &task, ice_aqc_opc_nvm_write_activate, - 30 * HZ); + err = ice_aq_wait_for_event(pf, &task, 30 * HZ); if (err) { dev_err(dev, "Timed out waiting for firmware to switch active flash banks, err %d\n", err); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index b08be6700b2a..81c1018b57d1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1251,30 +1251,24 @@ ice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event) } /** - * ice_aq_wait_for_event - Wait for an AdminQ event from firmware + * ice_aq_prep_for_event - Prepare to wait for an AdminQ event from firmware * @pf: pointer to the PF private structure - * @task: ptr to task structure + * @task: intermediate helper storage and identifier for waiting * @opcode: the opcode to wait for - * @timeout: how long to wait, in jiffies * - * Waits for a specific AdminQ completion event on the ARQ for a given PF. The - * current thread will be put to sleep until the specified event occurs or - * until the given timeout is reached. + * Prepares to wait for a specific AdminQ completion event on the ARQ for + * a given PF. Actual wait would be done by a call to ice_aq_wait_for_event(). * - * To obtain only the descriptor contents, pass an event without an allocated - * msg_buf. If the complete data buffer is desired, allocate the - * event->msg_buf with enough space ahead of time. + * Calls are separated to allow caller registering for event before sending + * the command, which mitigates a race between registering and FW responding. * - * Returns: zero on success, or a negative error code on failure. + * To obtain only the descriptor contents, pass an task->event with null + * msg_buf. If the complete data buffer is desired, allocate the + * task->event.msg_buf with enough space ahead of time. */ -int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, - u16 opcode, unsigned long timeout) +void ice_aq_prep_for_event(struct ice_pf *pf, struct ice_aq_task *task, + u16 opcode) { - struct device *dev = ice_pf_to_dev(pf); - unsigned long start; - long ret; - int err; - INIT_HLIST_NODE(&task->entry); task->opcode = opcode; task->state = ICE_AQ_TASK_WAITING; @@ -1282,12 +1276,37 @@ int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, spin_lock_bh(&pf->aq_wait_lock); hlist_add_head(&task->entry, &pf->aq_wait_list); spin_unlock_bh(&pf->aq_wait_lock); +} - start = jiffies; +/** + * ice_aq_wait_for_event - Wait for an AdminQ event from firmware + * @pf: pointer to the PF private structure + * @task: ptr prepared by ice_aq_prep_for_event() + * @timeout: how long to wait, in jiffies + * + * Waits for a specific AdminQ completion event on the ARQ for a given PF. The + * current thread will be put to sleep until the specified event occurs or + * until the given timeout is reached. + * + * Returns: zero on success, or a negative error code on failure. + */ +int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, + unsigned long timeout) +{ + enum ice_aq_task_state *state = &task->state; + struct device *dev = ice_pf_to_dev(pf); + unsigned long start = jiffies; + long ret; + int err; - ret = wait_event_interruptible_timeout(pf->aq_wait_queue, task->state, + ret = wait_event_interruptible_timeout(pf->aq_wait_queue, + *state != ICE_AQ_TASK_WAITING, timeout); - switch (task->state) { + switch (*state) { + case ICE_AQ_TASK_NOT_PREPARED: + WARN(1, "call to %s without ice_aq_prep_for_event()", __func__); + err = -EINVAL; + break; case ICE_AQ_TASK_WAITING: err = ret < 0 ? ret : -ETIMEDOUT; break; @@ -1298,7 +1317,7 @@ int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, err = ret < 0 ? ret : 0; break; default: - WARN(1, "Unexpected AdminQ wait task state %u", task->state); + WARN(1, "Unexpected AdminQ wait task state %u", *state); err = -EINVAL; break; } @@ -1306,7 +1325,7 @@ int ice_aq_wait_for_event(struct ice_pf *pf, struct ice_aq_task *task, dev_dbg(dev, "Waited %u msecs (max %u msecs) for firmware response to op 0x%04x\n", jiffies_to_msecs(jiffies - start), jiffies_to_msecs(timeout), - opcode); + task->opcode); spin_lock_bh(&pf->aq_wait_lock); hlist_del(&task->entry); @@ -1342,7 +1361,9 @@ static void ice_aq_check_events(struct ice_pf *pf, u16 opcode, spin_lock_bh(&pf->aq_wait_lock); hlist_for_each_entry(task, &pf->aq_wait_list, entry) { - if (task->state || task->opcode != opcode) + if (task->state != ICE_AQ_TASK_WAITING) + continue; + if (task->opcode != opcode) continue; task_ev = &task->event; -- cgit From b2f8323364abf1b6fcd828851ea8be2f757c052a Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Mon, 14 Aug 2023 16:30:00 +0800 Subject: tun: add __exit annotations to module exit func tun_cleanup() Add missing __exit annotations to module exit func tun_cleanup(). Signed-off-by: Ziyang Xuan Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230814083000.3893589-1-william.xuanziyang@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d4bd76297a2a..89ab9efe522c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3743,7 +3743,7 @@ err_linkops: return ret; } -static void tun_cleanup(void) +static void __exit tun_cleanup(void) { misc_deregister(&tun_miscdev); rtnl_link_unregister(&tun_link_ops); -- cgit From a5e5b2cd47bc7ac853b3ae9d4af97d08caaf585d Mon Sep 17 00:00:00 2001 From: Jialin Zhang Date: Tue, 15 Aug 2023 10:42:48 +0800 Subject: net: ena: Use pci_dev_id() to simplify the code PCI core API pci_dev_id() can be used to get the BDF number for a pci device. We don't need to compose it manually. Use pci_dev_id() to simplify the code a little bit. Signed-off-by: Jialin Zhang Reviewed-by: Leon Romanovsky Reviewed-by: Shay Agroskin Link: https://lore.kernel.org/r/20230815024248.3519068-1-zhangjialin11@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index d19593fae226..ad32ca81f7ef 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3267,7 +3267,7 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd host_info = ena_dev->host_attr.host_info; - host_info->bdf = (pdev->bus->number << 8) | pdev->devfn; + host_info->bdf = pci_dev_id(pdev); host_info->os_type = ENA_ADMIN_OS_LINUX; host_info->kernel_ver = LINUX_VERSION_CODE; strscpy(host_info->kernel_ver_str, utsname()->version, -- cgit From f3add6dec36d9d747929918ba1d7ce8866e1c054 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Tue, 15 Aug 2023 20:35:59 +0000 Subject: net: mdio: fix -Wvoid-pointer-to-enum-cast warning When building with clang 18 I see the following warning: | drivers/net/mdio/mdio-xgene.c:338:13: warning: cast to smaller integer | type 'enum xgene_mdio_id' from 'const void *' [-Wvoid-pointer-to-enum-cast] | 338 | mdio_id = (enum xgene_mdio_id)of_id->data; This is due to the fact that `of_id->data` is a void* while `enum xgene_mdio_id` has the size of an int. This leads to truncation and possible data loss. Link: https://github.com/ClangBuiltLinux/linux/issues/1910 Reported-by: Nathan Chancellor Signed-off-by: Justin Stitt Reviewed-by: Andrew Lunn Reviewed-by: Russell King (Oracle) Link: https://lore.kernel.org/r/20230815-void-drivers-net-mdio-mdio-xgene-v1-1-5304342e0659@google.com Signed-off-by: Jakub Kicinski --- drivers/net/mdio/mdio-xgene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c index 683e8f8319ab..1af7a4d9f86c 100644 --- a/drivers/net/mdio/mdio-xgene.c +++ b/drivers/net/mdio/mdio-xgene.c @@ -335,7 +335,7 @@ static int xgene_mdio_probe(struct platform_device *pdev) of_id = of_match_device(xgene_mdio_of_match, &pdev->dev); if (of_id) { - mdio_id = (enum xgene_mdio_id)of_id->data; + mdio_id = (uintptr_t)of_id->data; } else { #ifdef CONFIG_ACPI const struct acpi_device_id *acpi_id; -- cgit From b0a9e2c9a99f64e3c59e8a32a11b90c667201203 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 11 Aug 2023 02:31:57 -0700 Subject: netconsole: Create a allocation helper De-duplicate the initialization and allocation code for struct netconsole_target. The same allocation and initialization code is duplicated in two different places in the netconsole subsystem, when the netconsole target is initialized by command line parameters (alloc_param_target()), and dynamically by sysfs (make_netconsole_target()). Create a helper function, and call it from the two different functions. Suggested-by: Eric Dumazet Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230811093158.1678322-2-leitao@debian.org Signed-off-by: Jakub Kicinski --- drivers/net/netconsole.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 87f18aedd3bd..670b6f0a054c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -167,19 +167,16 @@ static void netconsole_target_put(struct netconsole_target *nt) #endif /* CONFIG_NETCONSOLE_DYNAMIC */ -/* Allocate new target (from boot/module param) and setup netpoll for it */ -static struct netconsole_target *alloc_param_target(char *target_config) +/* Allocate and initialize with defaults. + * Note that these targets get their config_item fields zeroed-out. + */ +static struct netconsole_target *alloc_and_init(void) { - int err = -ENOMEM; struct netconsole_target *nt; - /* - * Allocate and initialize with defaults. - * Note that these targets get their config_item fields zeroed-out. - */ nt = kzalloc(sizeof(*nt), GFP_KERNEL); if (!nt) - goto fail; + return nt; nt->np.name = "netconsole"; strscpy(nt->np.dev_name, "eth0", IFNAMSIZ); @@ -187,6 +184,21 @@ static struct netconsole_target *alloc_param_target(char *target_config) nt->np.remote_port = 6666; eth_broadcast_addr(nt->np.remote_mac); + return nt; +} + +/* Allocate new target (from boot/module param) and setup netpoll for it */ +static struct netconsole_target *alloc_param_target(char *target_config) +{ + struct netconsole_target *nt; + int err; + + nt = alloc_and_init(); + if (!nt) { + err = -ENOMEM; + goto fail; + } + if (*target_config == '+') { nt->extended = true; target_config++; @@ -195,6 +207,7 @@ static struct netconsole_target *alloc_param_target(char *target_config) if (*target_config == 'r') { if (!nt->extended) { pr_err("Netconsole configuration error. Release feature requires extended log message"); + err = -EINVAL; goto fail; } nt->release = true; @@ -664,23 +677,13 @@ static const struct config_item_type netconsole_target_type = { static struct config_item *make_netconsole_target(struct config_group *group, const char *name) { - unsigned long flags; struct netconsole_target *nt; + unsigned long flags; - /* - * Allocate and initialize with defaults. - * Target is disabled at creation (!enabled). - */ - nt = kzalloc(sizeof(*nt), GFP_KERNEL); + nt = alloc_and_init(); if (!nt) return ERR_PTR(-ENOMEM); - nt->np.name = "netconsole"; - strscpy(nt->np.dev_name, "eth0", IFNAMSIZ); - nt->np.local_port = 6665; - nt->np.remote_port = 6666; - eth_broadcast_addr(nt->np.remote_mac); - /* Initialize the config_item member */ config_item_init_type_name(&nt->item, name, &netconsole_target_type); -- cgit From fad361a2ee9099028774ff9081bf9abf08bd2ff0 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 11 Aug 2023 02:31:58 -0700 Subject: netconsole: Enable compile time configuration Enable netconsole features to be set at compilation time. Create two Kconfig options that allow users to set extended logs and release prepending features at compilation time. Right now, the user needs to pass command line parameters to netconsole, such as "+"/"r" to enable extended logs and version prepending features. With these two options, the user could set the default values for the features at compile time, and don't need to pass it in the command line to get them enabled, simplifying the command line. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230811093158.1678322-3-leitao@debian.org Signed-off-by: Jakub Kicinski --- drivers/net/Kconfig | 22 ++++++++++++++++++++++ drivers/net/netconsole.c | 5 +++++ 2 files changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index be43cd08027b..44eeb5d61ba9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -332,6 +332,28 @@ config NETCONSOLE_DYNAMIC at runtime through a userspace interface exported using configfs. See for details. +config NETCONSOLE_EXTENDED_LOG + bool "Set kernel extended message by default" + depends on NETCONSOLE + default n + help + Set extended log support for netconsole message. If this option is + set, log messages are transmitted with extended metadata header in a + format similar to /dev/kmsg. See + for details. + +config NETCONSOLE_PREPEND_RELEASE + bool "Prepend kernel release version in the message by default" + depends on NETCONSOLE_EXTENDED_LOG + default n + help + Set kernel release to be prepended to each netconsole message by + default. If this option is set, the kernel release is prepended into + the first field of every netconsole message, so, the netconsole + server/peer can easily identify what kernel release is logging each + message. See for + details. + config NETPOLL def_bool NETCONSOLE diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 670b6f0a054c..3111e1648592 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -178,6 +178,11 @@ static struct netconsole_target *alloc_and_init(void) if (!nt) return nt; + if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG)) + nt->extended = true; + if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE)) + nt->release = true; + nt->np.name = "netconsole"; strscpy(nt->np.dev_name, "eth0", IFNAMSIZ); nt->np.local_port = 6665; -- cgit From 5cce781484cec087de22f730278eed7a3388f962 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 16 Aug 2023 08:49:44 +0800 Subject: sfc: Remove unneeded semicolon ./drivers/net/ethernet/sfc/tc_conntrack.c:464:2-3: Unneeded semicolon Signed-off-by: Yang Li Acked-by: Martin Habets Link: https://lore.kernel.org/r/20230816004944.10841-1-yang.lee@linux.alibaba.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sfc/tc_conntrack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c index 54ed288543d0..8e06bfbcbea1 100644 --- a/drivers/net/ethernet/sfc/tc_conntrack.c +++ b/drivers/net/ethernet/sfc/tc_conntrack.c @@ -461,7 +461,7 @@ static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, return efx_tc_ct_stats(ct_zone, tcb); default: break; - }; + } return -EOPNOTSUPP; } -- cgit From 91a10efc89dc510edf57cb1d3a7ad480ef5160b8 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Wed, 16 Aug 2023 17:02:42 +0800 Subject: net: fec: use napi_consume_skb() in fec_enet_tx_queue() Now that the "budget" is passed into fec_enet_tx_queue(), one optimization we can do is to use napi_consume_skb() to instead of dev_kfree_skb_any(). Signed-off-by: Wei Fang Suggested-by: Alexander H Duyck Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230816090242.463822-1-wei.fang@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index f77105f017c1..e23a55977183 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1494,7 +1494,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget) } /* Free the sk buffer associated with this last transmit */ - dev_kfree_skb_any(skb); + napi_consume_skb(skb, budget); } else if (txq->tx_buf[index].type == FEC_TXBUF_T_XDP_NDO) { xdp_return_frame_rx_napi(xdpf); } else { /* recycle pages of XDP_TX frames */ -- cgit From 2f48b1d854e853b243fcd7e4f3f11d6ab5431bd7 Mon Sep 17 00:00:00 2001 From: Yu Liao Date: Thu, 17 Aug 2023 10:57:09 +0800 Subject: pds_core: remove redundant pci_clear_master() do_pci_disable_device() disable PCI bus-mastering as following: static void do_pci_disable_device(struct pci_dev *dev) { u16 pci_command; pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } pcibios_disable_device(dev); } And pci_disable_device() sets dev->is_busmaster to 0. pci_enable_device() is called only once before calling to pci_disable_device() and such pci_clear_master() is not needed. So remove redundant pci_clear_master(). Also rename goto label 'err_out_clear_master' to 'err_out_disable_device'. Signed-off-by: Yu Liao Reviewed-by: Simon Horman Reviewed-by: Leon Romanovsky Acked-by: Shannon Nelson Link: https://lore.kernel.org/r/20230817025709.2023553-1-liaoyu15@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c index 672757932246..3a45bf474a19 100644 --- a/drivers/net/ethernet/amd/pds_core/main.c +++ b/drivers/net/ethernet/amd/pds_core/main.c @@ -367,14 +367,13 @@ static int pdsc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pdsc_init_vf(pdsc); if (err) { dev_err(dev, "Cannot init device: %pe\n", ERR_PTR(err)); - goto err_out_clear_master; + goto err_out_disable_device; } clear_bit(PDSC_S_INITING_DRIVER, &pdsc->state); return 0; -err_out_clear_master: - pci_clear_master(pdev); +err_out_disable_device: pci_disable_device(pdev); err_out_free_ida: ida_free(&pdsc_ida, pdsc->uid); @@ -439,7 +438,6 @@ static void pdsc_remove(struct pci_dev *pdev) pci_release_regions(pdev); } - pci_clear_master(pdev); pci_disable_device(pdev); ida_free(&pdsc_ida, pdsc->uid); -- cgit From ee09e9deefac842a66cbbd39fd2f03aff6e2a656 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Thu, 17 Aug 2023 15:30:17 +0800 Subject: sky2: Remove redundant NULL check for debugfs_create_dir Since debugfs_create_dir() returns ERR_PTR, IS_ERR() is enough to check whether the directory is successfully created. So remove the redundant NULL check. Signed-off-by: Ruan Jinjie Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230817073017.350002-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index c4cca27fb0d5..07720841a8d7 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4528,7 +4528,7 @@ static __init void sky2_debug_init(void) struct dentry *ent; ent = debugfs_create_dir("sky2", NULL); - if (!ent || IS_ERR(ent)) + if (IS_ERR(ent)) return; sky2_debug = ent; -- cgit From 829b3357dd9737d45b3724b5378adf8cf8334ea1 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Thu, 17 Aug 2023 10:24:18 +0800 Subject: net: dm9051: Use PTR_ERR_OR_ZERO() to simplify code Return PTR_ERR_OR_ZERO() instead of return 0 or PTR_ERR() to simplify code. Signed-off-by: Ruan Jinjie Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230817022418.3588831-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/davicom/dm9051.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/davicom/dm9051.c b/drivers/net/ethernet/davicom/dm9051.c index 70728b2e5f18..2caaf1e9f42f 100644 --- a/drivers/net/ethernet/davicom/dm9051.c +++ b/drivers/net/ethernet/davicom/dm9051.c @@ -510,10 +510,7 @@ static int dm9051_map_init(struct spi_device *spi, struct board_info *db) regconfigdmbulk.lock_arg = db; db->regmap_dmbulk = devm_regmap_init_spi(db->spidev, ®configdmbulk); - if (IS_ERR(db->regmap_dmbulk)) - return PTR_ERR(db->regmap_dmbulk); - - return 0; + return PTR_ERR_OR_ZERO(db->regmap_dmbulk); } static int dm9051_map_chipid(struct board_info *db) -- cgit From 86b05508f7759f41b530c6fec8858124745eada4 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Thu, 17 Aug 2023 16:19:06 -0700 Subject: bnxt_en: Use the unified RX page pool buffers for XDP and non-XDP Convert to use the page pool buffers for the aggregation ring when running in non-XDP mode. This simplifies the driver and we benefit from the recycling of pages. Adjust the page pool size to account for the aggregation ring size. Signed-off-by: Somnath Kotur Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-2-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 71 ++++++------------------------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 -- 2 files changed, 14 insertions(+), 60 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7be917a8da48..6b815a2288e2 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -877,48 +877,15 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp, struct rx_bd *rxbd = &rxr->rx_agg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; struct bnxt_sw_rx_agg_bd *rx_agg_buf; - struct pci_dev *pdev = bp->pdev; struct page *page; dma_addr_t mapping; u16 sw_prod = rxr->rx_sw_agg_prod; unsigned int offset = 0; - if (BNXT_RX_PAGE_MODE(bp)) { - page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp); - - if (!page) - return -ENOMEM; - - } else { - if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) { - page = rxr->rx_page; - if (!page) { - page = alloc_page(gfp); - if (!page) - return -ENOMEM; - rxr->rx_page = page; - rxr->rx_page_offset = 0; - } - offset = rxr->rx_page_offset; - rxr->rx_page_offset += BNXT_RX_PAGE_SIZE; - if (rxr->rx_page_offset == PAGE_SIZE) - rxr->rx_page = NULL; - else - get_page(page); - } else { - page = alloc_page(gfp); - if (!page) - return -ENOMEM; - } + page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp); - mapping = dma_map_page_attrs(&pdev->dev, page, offset, - BNXT_RX_PAGE_SIZE, DMA_FROM_DEVICE, - DMA_ATTR_WEAK_ORDERING); - if (dma_mapping_error(&pdev->dev, mapping)) { - __free_page(page); - return -EIO; - } - } + if (!page) + return -ENOMEM; if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap))) sw_prod = bnxt_find_next_agg_idx(rxr, sw_prod); @@ -1204,6 +1171,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp, total_frag_len = __bnxt_rx_agg_pages(bp, cpr, shinfo, idx, agg_bufs, tpa, NULL); if (!total_frag_len) { + skb_mark_for_recycle(skb); dev_kfree_skb(skb); return NULL; } @@ -1794,6 +1762,7 @@ static void bnxt_deliver_skb(struct bnxt *bp, struct bnxt_napi *bnapi, return; } skb_record_rx_queue(skb, bnapi->index); + skb_mark_for_recycle(skb); napi_gro_receive(&bnapi->napi, skb); } @@ -3002,30 +2971,16 @@ skip_rx_buf_free: if (!page) continue; - if (BNXT_RX_PAGE_MODE(bp)) { - dma_unmap_page_attrs(&pdev->dev, rx_agg_buf->mapping, - BNXT_RX_PAGE_SIZE, bp->rx_dir, - DMA_ATTR_WEAK_ORDERING); - rx_agg_buf->page = NULL; - __clear_bit(i, rxr->rx_agg_bmap); - - page_pool_recycle_direct(rxr->page_pool, page); - } else { - dma_unmap_page_attrs(&pdev->dev, rx_agg_buf->mapping, - BNXT_RX_PAGE_SIZE, DMA_FROM_DEVICE, - DMA_ATTR_WEAK_ORDERING); - rx_agg_buf->page = NULL; - __clear_bit(i, rxr->rx_agg_bmap); + dma_unmap_page_attrs(&pdev->dev, rx_agg_buf->mapping, + BNXT_RX_PAGE_SIZE, bp->rx_dir, + DMA_ATTR_WEAK_ORDERING); + rx_agg_buf->page = NULL; + __clear_bit(i, rxr->rx_agg_bmap); - __free_page(page); - } + page_pool_recycle_direct(rxr->page_pool, page); } skip_rx_agg_free: - if (rxr->rx_page) { - __free_page(rxr->rx_page); - rxr->rx_page = NULL; - } map = rxr->rx_tpa_idx_map; if (map) memset(map->agg_idx_bmap, 0, sizeof(map->agg_idx_bmap)); @@ -3244,7 +3199,9 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, { struct page_pool_params pp = { 0 }; - pp.pool_size = bp->rx_ring_size; + pp.pool_size = bp->rx_agg_ring_size; + if (BNXT_RX_PAGE_MODE(bp)) + pp.pool_size += bp->rx_ring_size; pp.nid = dev_to_node(&bp->pdev->dev); pp.napi = &rxr->bnapi->napi; pp.dev = &bp->pdev->dev; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 362918876d3c..d6a1eaa69774 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -919,9 +919,6 @@ struct bnxt_rx_ring_info { unsigned long *rx_agg_bmap; u16 rx_agg_bmap_size; - struct page *rx_page; - unsigned int rx_page_offset; - dma_addr_t rx_desc_mapping[MAX_RX_PAGES]; dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; -- cgit From 578fcfd26e2a1d0e687b347057959228567e2af8 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Thu, 17 Aug 2023 16:19:07 -0700 Subject: bnxt_en: Let the page pool manage the DMA mapping Use the page pool's ability to maintain DMA mappings for us. This avoids re-mapping of the recycled pages. Link: https://lore.kernel.org/netdev/20230728231829.235716-4-michael.chan@broadcom.com/ Signed-off-by: Somnath Kotur Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-3-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 32 ++++++++++--------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6b815a2288e2..73a3936ee498 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -761,7 +761,6 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, unsigned int *offset, gfp_t gfp) { - struct device *dev = &bp->pdev->dev; struct page *page; if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) { @@ -774,12 +773,7 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, if (!page) return NULL; - *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE, - bp->rx_dir, DMA_ATTR_WEAK_ORDERING); - if (dma_mapping_error(dev, *mapping)) { - page_pool_recycle_direct(rxr->page_pool, page); - return NULL; - } + *mapping = page_pool_get_dma_addr(page) + *offset; return page; } @@ -998,8 +992,8 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, return NULL; } dma_addr -= bp->rx_dma_offset; - dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, - bp->rx_dir, DMA_ATTR_WEAK_ORDERING); + dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, + bp->rx_dir); skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE); if (!skb) { page_pool_recycle_direct(rxr->page_pool, page); @@ -1032,8 +1026,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, return NULL; } dma_addr -= bp->rx_dma_offset; - dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, - bp->rx_dir, DMA_ATTR_WEAK_ORDERING); + dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, + bp->rx_dir); if (unlikely(!payload)) payload = eth_get_headlen(bp->dev, data_ptr, len); @@ -1149,9 +1143,8 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp, return 0; } - dma_unmap_page_attrs(&pdev->dev, mapping, BNXT_RX_PAGE_SIZE, - bp->rx_dir, - DMA_ATTR_WEAK_ORDERING); + dma_sync_single_for_cpu(&pdev->dev, mapping, BNXT_RX_PAGE_SIZE, + bp->rx_dir); total_frag_len += frag_len; prod = NEXT_RX_AGG(prod); @@ -2947,10 +2940,6 @@ skip_rx_tpa_free: rx_buf->data = NULL; if (BNXT_RX_PAGE_MODE(bp)) { - mapping -= bp->rx_dma_offset; - dma_unmap_page_attrs(&pdev->dev, mapping, - BNXT_RX_PAGE_SIZE, bp->rx_dir, - DMA_ATTR_WEAK_ORDERING); page_pool_recycle_direct(rxr->page_pool, data); } else { dma_unmap_single_attrs(&pdev->dev, mapping, @@ -2971,9 +2960,6 @@ skip_rx_buf_free: if (!page) continue; - dma_unmap_page_attrs(&pdev->dev, rx_agg_buf->mapping, - BNXT_RX_PAGE_SIZE, bp->rx_dir, - DMA_ATTR_WEAK_ORDERING); rx_agg_buf->page = NULL; __clear_bit(i, rxr->rx_agg_bmap); @@ -3205,7 +3191,9 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, pp.nid = dev_to_node(&bp->pdev->dev); pp.napi = &rxr->bnapi->napi; pp.dev = &bp->pdev->dev; - pp.dma_dir = DMA_BIDIRECTIONAL; + pp.dma_dir = bp->rx_dir; + pp.max_len = PAGE_SIZE; + pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) pp.flags |= PP_FLAG_PAGE_FRAG; -- cgit From d38c19b13b1087890973ac24ae2798797b8a411b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 17 Aug 2023 16:19:08 -0700 Subject: bnxt_en: Increment rx_resets counter in bnxt_disable_napi() If we are doing a complete reset with irq_re_init set to true in bnxt_close_nic(), all the ring structures will be freed. New structures will be allocated in bnxt_open_nic(). The current code increments rx_resets counter in bnxt_enable_napi() if bnapi->in_reset is true. In a complete reset, bnapi->in_reset will never be true since the structure is just allocated. Increment the rx_resets counter in bnxt_disable_napi() instead. This will allow us to save all the ring error counters including the rx_resets counters in the next patch. Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-4-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 73a3936ee498..34c3d231946e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9393,10 +9393,14 @@ static void bnxt_disable_napi(struct bnxt *bp) return; for (i = 0; i < bp->cp_nr_rings; i++) { - struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring; + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr; - napi_disable(&bp->bnapi[i]->napi); - if (bp->bnapi[i]->rx_ring) + cpr = &bnapi->cp_ring; + if (bnapi->in_reset) + cpr->sw_stats.rx.rx_resets++; + napi_disable(&bnapi->napi); + if (bnapi->rx_ring) cancel_work_sync(&cpr->dim.work); } } @@ -9413,8 +9417,6 @@ static void bnxt_enable_napi(struct bnxt *bp) bnapi->tx_fault = 0; cpr = &bnapi->cp_ring; - if (bnapi->in_reset) - cpr->sw_stats.rx.rx_resets++; bnapi->in_reset = false; bnapi->tx_pkts = 0; -- cgit From 4c70dbe3c0087b439b9e5015057e3e378cf5d8b1 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 17 Aug 2023 16:19:09 -0700 Subject: bnxt_en: Save ring error counters across reset Currently, the ring counters are stored in the per ring datastructure. During reset, all the rings are freed together with the associated datastructures. As a result, all the ring error counters will be reset to zero. Add logic to keep track of the total error counts of all the rings and save them before reset (including ifdown). The next patch will display these total ring error counters under ethtool -S. Link: https://lore.kernel.org/netdev/CACKFLimD-bKmJ1tGZOLYRjWzEwxkri-Mw7iFme1x2Dr0twdCeg@mail.gmail.com/ Reviewed-by: Ajit Khaparde Reviewed-by: Andy Gospodarek Reviewed-by: Somnath Kotur Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-5-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 32 ++++++++++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 15 +++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 34c3d231946e..bea562d08d6c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -10685,8 +10685,10 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bnxt_free_skbs(bp); /* Save ring stats before shutdown */ - if (bp->bnapi && irq_re_init) + if (bp->bnapi && irq_re_init) { bnxt_get_ring_stats(bp, &bp->net_stats_prev); + bnxt_get_ring_err_stats(bp, &bp->ring_err_stats_prev); + } if (irq_re_init) { bnxt_free_irq(bp); bnxt_del_napi(bp); @@ -10935,6 +10937,34 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) clear_bit(BNXT_STATE_READ_STATS, &bp->state); } +static void bnxt_get_one_ring_err_stats(struct bnxt *bp, + struct bnxt_total_ring_err_stats *stats, + struct bnxt_cp_ring_info *cpr) +{ + struct bnxt_sw_stats *sw_stats = &cpr->sw_stats; + u64 *hw_stats = cpr->stats.sw_stats; + + stats->rx_total_l4_csum_errors += sw_stats->rx.rx_l4_csum_errors; + stats->rx_total_resets += sw_stats->rx.rx_resets; + stats->rx_total_buf_errors += sw_stats->rx.rx_buf_errors; + stats->rx_total_oom_discards += sw_stats->rx.rx_oom_discards; + stats->rx_total_netpoll_discards += sw_stats->rx.rx_netpoll_discards; + stats->rx_total_ring_discards += + BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts); + stats->tx_total_ring_discards += + BNXT_GET_RING_STATS64(hw_stats, tx_discard_pkts); + stats->total_missed_irqs += sw_stats->cmn.missed_irqs; +} + +void bnxt_get_ring_err_stats(struct bnxt *bp, + struct bnxt_total_ring_err_stats *stats) +{ + int i; + + for (i = 0; i < bp->cp_nr_rings; i++) + bnxt_get_one_ring_err_stats(bp, stats, &bp->bnapi[i]->cp_ring); +} + static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask) { struct net_device *dev = bp->dev; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index d6a1eaa69774..7287fd3c0763 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -948,6 +948,17 @@ struct bnxt_sw_stats { struct bnxt_cmn_sw_stats cmn; }; +struct bnxt_total_ring_err_stats { + u64 rx_total_l4_csum_errors; + u64 rx_total_resets; + u64 rx_total_buf_errors; + u64 rx_total_oom_discards; + u64 rx_total_netpoll_discards; + u64 rx_total_ring_discards; + u64 tx_total_ring_discards; + u64 total_missed_irqs; +}; + struct bnxt_stats_mem { u64 *sw_stats; u64 *hw_masks; @@ -2018,6 +2029,8 @@ struct bnxt { u8 pri2cos_idx[8]; u8 pri2cos_valid; + struct bnxt_total_ring_err_stats ring_err_stats_prev; + u16 hwrm_max_req_len; u16 hwrm_max_ext_req_len; unsigned int hwrm_cmd_timeout; @@ -2344,6 +2357,8 @@ int bnxt_half_open_nic(struct bnxt *bp); void bnxt_half_close_nic(struct bnxt *bp); void bnxt_reenable_sriov(struct bnxt *bp); int bnxt_close_nic(struct bnxt *, bool, bool); +void bnxt_get_ring_err_stats(struct bnxt *bp, + struct bnxt_total_ring_err_stats *stats); int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words, u32 *reg_buf); void bnxt_fw_exception(struct bnxt *bp); -- cgit From a080b47a04c503674c30dfe697b6fa1b98c3bb6b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 17 Aug 2023 16:19:10 -0700 Subject: bnxt_en: Display the ring error counters under ethtool -S The existing driver displays the sum of 4 ring counters under ethtool -S. These counters are in the array bnxt_sw_func_stats. These counters are summed at the time of ethtool -S and will be lost when the device is reset. Replace these counters with the new total ring error counters added in the last patch. These new counters are saved before reset. ethtool -S will now display the sum of the saved counters plus the current counters. Link: https://lore.kernel.org/netdev/CACKFLimD-bKmJ1tGZOLYRjWzEwxkri-Mw7iFme1x2Dr0twdCeg@mail.gmail.com/ Reviewed-by: Andy Gospodarek Reviewed-by: Ajit Khaparde Reviewed-by: Somnath Kotur Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-6-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 48 +++++++++++------------ 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 8fd5071d8b09..a9f1eede24e9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -339,13 +339,15 @@ enum { RX_NETPOLL_DISCARDS, }; -static struct { - u64 counter; - char string[ETH_GSTRING_LEN]; -} bnxt_sw_func_stats[] = { - {0, "rx_total_discard_pkts"}, - {0, "tx_total_discard_pkts"}, - {0, "rx_total_netpoll_discards"}, +static const char *const bnxt_ring_err_stats_arr[] = { + "rx_total_l4_csum_errors", + "rx_total_resets", + "rx_total_buf_errors", + "rx_total_oom_discards", + "rx_total_netpoll_discards", + "rx_total_ring_discards", + "tx_total_ring_discards", + "total_missed_irqs", }; #define NUM_RING_RX_SW_STATS ARRAY_SIZE(bnxt_rx_sw_stats_str) @@ -495,7 +497,7 @@ static const struct { BNXT_TX_STATS_PRI_ENTRIES(tx_packets), }; -#define BNXT_NUM_SW_FUNC_STATS ARRAY_SIZE(bnxt_sw_func_stats) +#define BNXT_NUM_RING_ERR_STATS ARRAY_SIZE(bnxt_ring_err_stats_arr) #define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr) #define BNXT_NUM_STATS_PRI \ (ARRAY_SIZE(bnxt_rx_bytes_pri_arr) + \ @@ -532,7 +534,7 @@ static int bnxt_get_num_stats(struct bnxt *bp) { int num_stats = bnxt_get_num_ring_stats(bp); - num_stats += BNXT_NUM_SW_FUNC_STATS; + num_stats += BNXT_NUM_RING_ERR_STATS; if (bp->flags & BNXT_FLAG_PORT_STATS) num_stats += BNXT_NUM_PORT_STATS; @@ -583,18 +585,17 @@ static bool is_tx_ring(struct bnxt *bp, int ring_num) static void bnxt_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *buf) { - u32 i, j = 0; + struct bnxt_total_ring_err_stats ring_err_stats = {0}; struct bnxt *bp = netdev_priv(dev); + u64 *curr, *prev; u32 tpa_stats; + u32 i, j = 0; if (!bp->bnapi) { - j += bnxt_get_num_ring_stats(bp) + BNXT_NUM_SW_FUNC_STATS; + j += bnxt_get_num_ring_stats(bp); goto skip_ring_stats; } - for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) - bnxt_sw_func_stats[i].counter = 0; - tpa_stats = bnxt_get_num_tpa_ring_stats(bp); for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; @@ -631,19 +632,16 @@ skip_tpa_ring_stats: sw = (u64 *)&cpr->sw_stats.cmn; for (k = 0; k < NUM_RING_CMN_SW_STATS; j++, k++) buf[j] = sw[k]; - - bnxt_sw_func_stats[RX_TOTAL_DISCARDS].counter += - BNXT_GET_RING_STATS64(sw_stats, rx_discard_pkts); - bnxt_sw_func_stats[TX_TOTAL_DISCARDS].counter += - BNXT_GET_RING_STATS64(sw_stats, tx_discard_pkts); - bnxt_sw_func_stats[RX_NETPOLL_DISCARDS].counter += - cpr->sw_stats.rx.rx_netpoll_discards; } - for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++, j++) - buf[j] = bnxt_sw_func_stats[i].counter; + bnxt_get_ring_err_stats(bp, &ring_err_stats); skip_ring_stats: + curr = &ring_err_stats.rx_total_l4_csum_errors; + prev = &bp->ring_err_stats_prev.rx_total_l4_csum_errors; + for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++, j++, curr++, prev++) + buf[j] = *curr + *prev; + if (bp->flags & BNXT_FLAG_PORT_STATS) { u64 *port_stats = bp->port_stats.sw_stats; @@ -745,8 +743,8 @@ skip_tpa_stats: buf += ETH_GSTRING_LEN; } } - for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) { - strcpy(buf, bnxt_sw_func_stats[i].string); + for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++) { + strscpy(buf, bnxt_ring_err_stats_arr[i], ETH_GSTRING_LEN); buf += ETH_GSTRING_LEN; } -- cgit From 8becd1961c734cb4bf96e3f98c50a644e8b8be2a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 17 Aug 2023 16:19:11 -0700 Subject: bnxt_en: Add tx_resets ring counter Add a new tx_resets ring counter. This counter will be saved as tx_total_resets across any reset. Since we currently do a full reset in bnxt_sched_reset_txr(), the per ring counter will always be cleared during reset. Only the tx_total_resets count will be meaningful and we only display this under ethtool -S. Link: https://lore.kernel.org/netdev/CACKFLimD-bKmJ1tGZOLYRjWzEwxkri-Mw7iFme1x2Dr0twdCeg@mail.gmail.com/ Signed-off-by: Michael Chan Link: https://lore.kernel.org/r/20230817231911.165035-7-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 6 ++++++ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 1 + 3 files changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index bea562d08d6c..5d6ea2782c2f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9397,6 +9397,8 @@ static void bnxt_disable_napi(struct bnxt *bp) struct bnxt_cp_ring_info *cpr; cpr = &bnapi->cp_ring; + if (bnapi->tx_fault) + cpr->sw_stats.tx.tx_resets++; if (bnapi->in_reset) cpr->sw_stats.rx.rx_resets++; napi_disable(&bnapi->napi); @@ -10951,6 +10953,7 @@ static void bnxt_get_one_ring_err_stats(struct bnxt *bp, stats->rx_total_netpoll_discards += sw_stats->rx.rx_netpoll_discards; stats->rx_total_ring_discards += BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts); + stats->tx_total_resets += sw_stats->tx.tx_resets; stats->tx_total_ring_discards += BNXT_GET_RING_STATS64(hw_stats, tx_discard_pkts); stats->total_missed_irqs += sw_stats->cmn.missed_irqs; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 7287fd3c0763..84cbcfa61bc1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -939,12 +939,17 @@ struct bnxt_rx_sw_stats { u64 rx_netpoll_discards; }; +struct bnxt_tx_sw_stats { + u64 tx_resets; +}; + struct bnxt_cmn_sw_stats { u64 missed_irqs; }; struct bnxt_sw_stats { struct bnxt_rx_sw_stats rx; + struct bnxt_tx_sw_stats tx; struct bnxt_cmn_sw_stats cmn; }; @@ -955,6 +960,7 @@ struct bnxt_total_ring_err_stats { u64 rx_total_oom_discards; u64 rx_total_netpoll_discards; u64 rx_total_ring_discards; + u64 tx_total_resets; u64 tx_total_ring_discards; u64 total_missed_irqs; }; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index a9f1eede24e9..547247d98eba 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -346,6 +346,7 @@ static const char *const bnxt_ring_err_stats_arr[] = { "rx_total_oom_discards", "rx_total_netpoll_discards", "rx_total_ring_discards", + "tx_total_resets", "tx_total_ring_discards", "total_missed_irqs", }; -- cgit From cb49ec0349240a112d6dd50b04466eaa2188b76c Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Thu, 17 Aug 2023 21:41:59 +0800 Subject: net: freescale: Remove unused declarations Commit 5d93cfcf7360 ("net: dpaa: Convert to phylink") removed fman_set_mac_active_pause()/fman_get_pause_cfg() but not declarations. Commit 48257c4f168e ("Add fs_enet ethernet network driver, for several embedded platforms.") declared but never implemented fs_enet_platform_init() and fs_enet_platform_cleanup(). Signed-off-by: Yue Haibing Reviewed-by: Sean Anderson Acked-by: Madalin Bucur Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/20230817134159.38484-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fman/mac.h | 4 ---- drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 5 ----- 2 files changed, 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h index ad06f8d7924b..fe747915cc73 100644 --- a/drivers/net/ethernet/freescale/fman/mac.h +++ b/drivers/net/ethernet/freescale/fman/mac.h @@ -68,10 +68,6 @@ struct dpaa_eth_data { extern const char *mac_driver_description; -int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx); - -void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, - bool *tx_pause); int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev); #endif /* __MAC_H */ diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h index d371072fff60..759bb7080e22 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h @@ -208,11 +208,6 @@ void fs_cleanup_bds(struct net_device *dev); #define DRV_MODULE_NAME "fs_enet" #define PFX DRV_MODULE_NAME ": " -/***************************************************************************/ - -int fs_enet_platform_init(void); -void fs_enet_platform_cleanup(void); - /***************************************************************************/ /* buffer descriptor access macros */ -- cgit From 58f2ffdedf7b05b318f2cdafaca69e4435c8478e Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Fri, 18 Aug 2023 13:14:01 +0200 Subject: stmmac: intel: Enable correction of MAC propagation delay All captured timestamps should be corrected by PHY, MAC and CDC introduced latency/errors. The CDC correction is already used. Enable MAC propagation delay correction as well which is available since commit 26cfb838aa00 ("net: stmmac: correct MAC propagation delay"). Before: |ptp4l[390.458]: rms 7 max 21 freq +177 +/- 14 delay 357 +/- 1 After: |ptp4l[620.012]: rms 7 max 20 freq +195 +/- 14 delay 345 +/- 1 Tested on Intel Elkhart Lake. Signed-off-by: Kurt Kanzenbach Reviewed-by: Johannes Zink Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 979c755964b1..a3a249c63598 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -627,6 +627,7 @@ static int ehl_common_data(struct pci_dev *pdev, plat->rx_queues_to_use = 8; plat->tx_queues_to_use = 8; plat->flags |= STMMAC_FLAG_USE_PHY_WOL; + plat->flags |= STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY; plat->safety_feat_cfg->tsoee = 1; plat->safety_feat_cfg->mrxpee = 1; -- cgit From 44a696de720d6917f1d1844a05757624295b81c0 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 18 Aug 2023 12:33:24 +0100 Subject: net: mdio: xgene: remove useless xgene_mdio_status xgene_mdio_status is declared static, and is only written once by the driver. It appears to have been this way since the driver was first added to the kernel tree. No other users can be found, so let's remove it. Signed-off-by: Russell King (Oracle) Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/mdio/mdio-xgene.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c index 1af7a4d9f86c..1190a793555a 100644 --- a/drivers/net/mdio/mdio-xgene.c +++ b/drivers/net/mdio/mdio-xgene.c @@ -20,8 +20,6 @@ #include #include -static bool xgene_mdio_status; - u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr) { void __iomem *addr, *rd, *cmd, *cmd_done; @@ -421,7 +419,6 @@ static int xgene_mdio_probe(struct platform_device *pdev) goto out_mdiobus; pdata->mdio_bus = mdio_bus; - xgene_mdio_status = true; return 0; -- cgit From 093db9cda7b695f963cd7b468ed1488063548ce2 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 13:05:03 +0800 Subject: net: microchip: vcap api: Always return ERR_PTR for vcap_get_rule() As Simon Horman suggests, update vcap_get_rule() to always return an ERR_PTR() and update the error detection conditions to use IS_ERR(), which would be more cleaner in this case. Signed-off-by: Ruan Jinjie Suggested-by: Simon Horman Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/vcap/vcap_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index a7b43f99bc80..300fe1a93dce 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -2429,7 +2429,7 @@ struct vcap_rule *vcap_get_rule(struct vcap_control *vctrl, u32 id) elem = vcap_get_locked_rule(vctrl, id); if (!elem) - return NULL; + return ERR_PTR(-ENOENT); rule = vcap_decode_rule(elem); mutex_unlock(&elem->admin->lock); -- cgit From ab104318f63997113b0ce7ac288e51359925ed79 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 13:05:04 +0800 Subject: net: lan966x: Fix return value check for vcap_get_rule() As Simon Horman suggests, update vcap_get_rule() to always return an ERR_PTR() and update the error detection conditions to use IS_ERR(), so use IS_ERR() to fix the return value issue. Fixes: 72df3489fb10 ("net: lan966x: Add ptp trap rules") Signed-off-by: Ruan Jinjie Suggested-by: Simon Horman Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c index 60bd0cff6677..63905bb5a63a 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c @@ -59,7 +59,7 @@ static int lan966x_ptp_add_trap(struct lan966x_port *port, int err; vrule = vcap_get_rule(lan966x->vcap_ctrl, rule_id); - if (vrule) { + if (!IS_ERR(vrule)) { u32 value, mask; /* Just modify the ingress port mask and exit */ @@ -106,7 +106,7 @@ static int lan966x_ptp_del_trap(struct lan966x_port *port, int err; vrule = vcap_get_rule(lan966x->vcap_ctrl, rule_id); - if (!vrule) + if (IS_ERR(vrule)) return -EEXIST; vcap_rule_get_key_u32(vrule, VCAP_KF_IF_IGR_PORT_MASK, &value, &mask); -- cgit From 95b358e4d9c7caad3a787f810265458ee477d0ef Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 13:05:05 +0800 Subject: net: microchip: sparx5: Update return value check for vcap_get_rule() As Simon Horman suggests, update vcap_get_rule() to always return an ERR_PTR() and update the error detection conditions to use IS_ERR(), so use IS_ERR() to check the return value. Signed-off-by: Ruan Jinjie Suggested-by: Simon Horman Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c index 906299ad8425..523e0c470894 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c @@ -1274,7 +1274,7 @@ static int sparx5_tc_free_rule_resources(struct net_device *ndev, int ret = 0; vrule = vcap_get_rule(vctrl, rule_id); - if (!vrule || IS_ERR(vrule)) + if (IS_ERR(vrule)) return -EINVAL; sparx5_tc_free_psfp_resources(sparx5, vrule); -- cgit From f132fdd9dc81e045bcf95005d418a31fbe9d942f Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Mon, 2 May 2022 14:40:56 +0300 Subject: macsec: add functions to get macsec real netdevice and check offload Given a macsec net_device add two functions to return the real net_device for that device, and check if that macsec device is offloaded or not. This is needed for auxiliary drivers that implement MACsec offload, but have flows which are triggered over the macsec net_device, this allows the drivers in such cases to verify if the device is offloaded or not, and to access the real device of that macsec device, which would belong to the driver, and would be needed for the offload procedure. Signed-off-by: Patrisious Haddad Reviewed-by: Raed Salem Reviewed-by: Mark Zhang Signed-off-by: Leon Romanovsky --- drivers/net/macsec.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 984dfa5d6c11..4895af1c5b7b 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4240,6 +4240,18 @@ static struct net *macsec_get_link_net(const struct net_device *dev) return dev_net(macsec_priv(dev)->real_dev); } +struct net_device *macsec_get_real_dev(const struct net_device *dev) +{ + return macsec_priv(dev)->real_dev; +} +EXPORT_SYMBOL_GPL(macsec_get_real_dev); + +bool macsec_netdev_is_offloaded(struct net_device *dev) +{ + return macsec_is_offloaded(macsec_priv(dev)); +} +EXPORT_SYMBOL_GPL(macsec_netdev_is_offloaded); + static size_t macsec_get_size(const struct net_device *dev) { return nla_total_size_64bit(8) + /* IFLA_MACSEC_SCI */ -- cgit From 7390762a073743f936bd1b392ec42161d9f2d23e Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Tue, 29 Nov 2022 14:50:22 +0200 Subject: net/mlx5e: Move MACsec flow steering operations to be used as core library Move MACsec flow steering operations(macsec_fs) from core/en_accel to core/lib, this mandates moving MACsec statistics structure from the general MACsec code header(en_accel/macsec.h) to macsec_fs header to remove macsec_fs.h dependency over en_accel/macsec.h. This to lay the ground for RoCE MACsec by moving all the data that will need to be accessed by both ethernet MACsec and RoCE MACsec to be shared at core. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 2 +- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +- .../mellanox/mlx5/core/en_accel/en_accel.h | 4 +- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 1 - .../ethernet/mellanox/mlx5/core/en_accel/macsec.h | 22 +- .../mellanox/mlx5/core/en_accel/macsec_fs.c | 1393 -------------------- .../mellanox/mlx5/core/en_accel/macsec_fs.h | 47 - drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | 2 +- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 1393 ++++++++++++++++++++ .../ethernet/mellanox/mlx5/core/lib/macsec_fs.h | 62 + 11 files changed, 1464 insertions(+), 1466 deletions(-) delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index bb1d7b039a7e..f3b284db1b5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -139,7 +139,7 @@ config MLX5_CORE_IPOIB help MLX5 IPoIB offloads & acceleration support. -config MLX5_EN_MACSEC +config MLX5_MACSEC bool "Connect-X support for MACSec offload" depends on MLX5_CORE_EN depends on MACSEC diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 35f00700a4d6..ade063b57cd5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -94,7 +94,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib # mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o -mlx5_core-$(CONFIG_MLX5_EN_MACSEC) += en_accel/macsec.o en_accel/macsec_fs.o \ +mlx5_core-$(CONFIG_MLX5_MACSEC) += en_accel/macsec.o lib/macsec_fs.o \ en_accel/macsec_stats.o mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index b1807bfb815f..b82217de9e9f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -917,7 +917,7 @@ struct mlx5e_priv { const struct mlx5e_profile *profile; void *ppriv; -#ifdef CONFIG_MLX5_EN_MACSEC +#ifdef CONFIG_MLX5_MACSEC struct mlx5e_macsec *macsec; #endif #ifdef CONFIG_MLX5_EN_IPSEC diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h index bac4717548c6..caa34b9c161e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h @@ -138,7 +138,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev, } #endif -#ifdef CONFIG_MLX5_EN_MACSEC +#ifdef CONFIG_MLX5_MACSEC if (unlikely(mlx5e_macsec_skb_is_offload(skb))) { struct mlx5e_priv *priv = netdev_priv(dev); @@ -173,7 +173,7 @@ static inline void mlx5e_accel_tx_eseg(struct mlx5e_priv *priv, mlx5e_ipsec_tx_build_eseg(priv, skb, eseg); #endif -#ifdef CONFIG_MLX5_EN_MACSEC +#ifdef CONFIG_MLX5_MACSEC if (unlikely(mlx5e_macsec_skb_is_offload(skb))) mlx5e_macsec_tx_build_eseg(priv->macsec, skb, eseg); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 592b165530ff..b26044efdec6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -10,7 +10,6 @@ #include "lib/aso.h" #include "lib/crypto.h" #include "en_accel/macsec.h" -#include "en_accel/macsec_fs.h" #define MLX5_MACSEC_EPN_SCOPE_MID 0x80000000L #define MLX5E_MACSEC_ASO_CTX_SZ MLX5_ST_SZ_BYTES(macsec_aso) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h index 347380a2cd9c..1f9c4a2723b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h @@ -4,32 +4,16 @@ #ifndef __MLX5_EN_ACCEL_MACSEC_H__ #define __MLX5_EN_ACCEL_MACSEC_H__ -#ifdef CONFIG_MLX5_EN_MACSEC +#ifdef CONFIG_MLX5_MACSEC #include #include #include - -/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */ -#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */ -#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX -#define MLX5_MACSEC_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x1) -#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata) ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK) +#include "lib/macsec_fs.h" struct mlx5e_priv; struct mlx5e_macsec; -struct mlx5e_macsec_stats { - u64 macsec_rx_pkts; - u64 macsec_rx_bytes; - u64 macsec_rx_pkts_drop; - u64 macsec_rx_bytes_drop; - u64 macsec_tx_pkts; - u64 macsec_tx_bytes; - u64 macsec_tx_pkts_drop; - u64 macsec_tx_bytes_drop; -}; - void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv); int mlx5e_macsec_init(struct mlx5e_priv *priv); void mlx5e_macsec_cleanup(struct mlx5e_priv *priv); @@ -68,6 +52,6 @@ static inline void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct mlx5_cqe64 *cqe) {} static inline bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) { return false; } -#endif /* CONFIG_MLX5_EN_MACSEC */ +#endif /* CONFIG_MLX5_MACSEC */ #endif /* __MLX5_ACCEL_EN_MACSEC_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c deleted file mode 100644 index 7fc901a6ec5f..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c +++ /dev/null @@ -1,1393 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB -/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ - -#include -#include -#include -#include -#include "fs_core.h" -#include "en/fs.h" -#include "en_accel/macsec_fs.h" -#include "mlx5_core.h" - -/* MACsec TX flow steering */ -#define CRYPTO_NUM_MAXSEC_FTE BIT(15) -#define CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE 1 - -#define TX_CRYPTO_TABLE_LEVEL 0 -#define TX_CRYPTO_TABLE_NUM_GROUPS 3 -#define TX_CRYPTO_TABLE_MKE_GROUP_SIZE 1 -#define TX_CRYPTO_TABLE_SA_GROUP_SIZE \ - (CRYPTO_NUM_MAXSEC_FTE - (TX_CRYPTO_TABLE_MKE_GROUP_SIZE + \ - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE)) -#define TX_CHECK_TABLE_LEVEL 1 -#define TX_CHECK_TABLE_NUM_FTE 2 -#define RX_CRYPTO_TABLE_LEVEL 0 -#define RX_CHECK_TABLE_LEVEL 1 -#define RX_CHECK_TABLE_NUM_FTE 3 -#define RX_CRYPTO_TABLE_NUM_GROUPS 3 -#define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \ - ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2) -#define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \ - (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE) -#define RX_NUM_OF_RULES_PER_SA 2 - -#define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */ -#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23 -#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8 -#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET 0x5 -#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT (0x1 << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) -#define MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI 0x8 -#define MLX5_SECTAG_HEADER_SIZE_WITH_SCI (MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI + MACSEC_SCI_LEN) - -/* MACsec RX flow steering */ -#define MLX5_ETH_WQE_FT_META_MACSEC_MASK 0x3E - -struct mlx5_sectag_header { - __be16 ethertype; - u8 tci_an; - u8 sl; - u32 pn; - u8 sci[MACSEC_SCI_LEN]; /* optional */ -} __packed; - -struct mlx5e_macsec_tx_rule { - struct mlx5_flow_handle *rule; - struct mlx5_pkt_reformat *pkt_reformat; - u32 fs_id; -}; - -struct mlx5e_macsec_tables { - struct mlx5e_flow_table ft_crypto; - struct mlx5_flow_handle *crypto_miss_rule; - - struct mlx5_flow_table *ft_check; - struct mlx5_flow_group *ft_check_group; - struct mlx5_fc *check_miss_rule_counter; - struct mlx5_flow_handle *check_miss_rule; - struct mlx5_fc *check_rule_counter; - - u32 refcnt; -}; - -struct mlx5e_macsec_tx { - struct mlx5_flow_handle *crypto_mke_rule; - struct mlx5_flow_handle *check_rule; - - struct ida tx_halloc; - - struct mlx5e_macsec_tables tables; -}; - -struct mlx5e_macsec_rx_rule { - struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA]; - struct mlx5_modify_hdr *meta_modhdr; -}; - -struct mlx5e_macsec_rx { - struct mlx5_flow_handle *check_rule[2]; - struct mlx5_pkt_reformat *check_rule_pkt_reformat[2]; - - struct mlx5e_macsec_tables tables; -}; - -union mlx5e_macsec_rule { - struct mlx5e_macsec_tx_rule tx_rule; - struct mlx5e_macsec_rx_rule rx_rule; -}; - -struct mlx5e_macsec_fs { - struct mlx5_core_dev *mdev; - struct net_device *netdev; - struct mlx5e_macsec_tx *tx_fs; - struct mlx5e_macsec_rx *rx_fs; -}; - -static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct mlx5e_macsec_tables *tx_tables; - - tx_tables = &tx_fs->tables; - - /* Tx check table */ - if (tx_fs->check_rule) { - mlx5_del_flow_rules(tx_fs->check_rule); - tx_fs->check_rule = NULL; - } - - if (tx_tables->check_miss_rule) { - mlx5_del_flow_rules(tx_tables->check_miss_rule); - tx_tables->check_miss_rule = NULL; - } - - if (tx_tables->ft_check_group) { - mlx5_destroy_flow_group(tx_tables->ft_check_group); - tx_tables->ft_check_group = NULL; - } - - if (tx_tables->ft_check) { - mlx5_destroy_flow_table(tx_tables->ft_check); - tx_tables->ft_check = NULL; - } - - /* Tx crypto table */ - if (tx_fs->crypto_mke_rule) { - mlx5_del_flow_rules(tx_fs->crypto_mke_rule); - tx_fs->crypto_mke_rule = NULL; - } - - if (tx_tables->crypto_miss_rule) { - mlx5_del_flow_rules(tx_tables->crypto_miss_rule); - tx_tables->crypto_miss_rule = NULL; - } - - mlx5e_destroy_flow_table(&tx_tables->ft_crypto); -} - -static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft) -{ - int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - int mclen = MLX5_ST_SZ_BYTES(fte_match_param); - int ix = 0; - u32 *in; - int err; - u8 *mc; - - ft->g = kcalloc(TX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL); - if (!ft->g) - return -ENOMEM; - in = kvzalloc(inlen, GFP_KERNEL); - - if (!in) { - kfree(ft->g); - return -ENOMEM; - } - - mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); - - /* Flow Group for MKE match */ - MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); - MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); - - MLX5_SET_CFG(in, start_flow_index, ix); - ix += TX_CRYPTO_TABLE_MKE_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - /* Flow Group for SA rules */ - memset(in, 0, inlen); - memset(mc, 0, mclen); - MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2); - MLX5_SET(fte_match_param, mc, misc_parameters_2.metadata_reg_a, - MLX5_ETH_WQE_FT_META_MACSEC_MASK); - - MLX5_SET_CFG(in, start_flow_index, ix); - ix += TX_CRYPTO_TABLE_SA_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - /* Flow Group for l2 traps */ - memset(in, 0, inlen); - memset(mc, 0, mclen); - MLX5_SET_CFG(in, start_flow_index, ix); - ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - kvfree(in); - return 0; - -err: - err = PTR_ERR(ft->g[ft->num_groups]); - ft->g[ft->num_groups] = NULL; - kvfree(in); - - return err; -} - -static struct mlx5_flow_table - *macsec_fs_auto_group_table_create(struct mlx5_flow_namespace *ns, int flags, - int level, int max_fte) -{ - struct mlx5_flow_table_attr ft_attr = {}; - struct mlx5_flow_table *fdb = NULL; - - /* reserve entry for the match all miss group and rule */ - ft_attr.autogroup.num_reserved_entries = 1; - ft_attr.autogroup.max_num_groups = 1; - ft_attr.prio = 0; - ft_attr.flags = flags; - ft_attr.level = level; - ft_attr.max_fte = max_fte; - - fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); - - return fdb; -} - -static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs) -{ - int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct net_device *netdev = macsec_fs->netdev; - struct mlx5_flow_table_attr ft_attr = {}; - struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *tx_tables; - struct mlx5_flow_act flow_act = {}; - struct mlx5e_flow_table *ft_crypto; - struct mlx5_flow_table *flow_table; - struct mlx5_flow_group *flow_group; - struct mlx5_flow_namespace *ns; - struct mlx5_flow_handle *rule; - struct mlx5_flow_spec *spec; - u32 *flow_group_in; - int err; - - ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); - if (!ns) - return -ENOMEM; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - - flow_group_in = kvzalloc(inlen, GFP_KERNEL); - if (!flow_group_in) { - err = -ENOMEM; - goto out_spec; - } - - tx_tables = &tx_fs->tables; - ft_crypto = &tx_tables->ft_crypto; - - /* Tx crypto table */ - ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - ft_attr.level = TX_CRYPTO_TABLE_LEVEL; - ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; - - flow_table = mlx5_create_flow_table(ns, &ft_attr); - if (IS_ERR(flow_table)) { - err = PTR_ERR(flow_table); - netdev_err(netdev, "Failed to create MACsec Tx crypto table err(%d)\n", err); - goto out_flow_group; - } - ft_crypto->t = flow_table; - - /* Tx crypto table groups */ - err = macsec_fs_tx_create_crypto_table_groups(ft_crypto); - if (err) { - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); - goto err; - } - - /* Tx crypto table MKE rule - MKE packets shouldn't be offloaded */ - spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; - - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype); - MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_PAE); - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; - - rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec TX MKE rule, err=%d\n", err); - goto err; - } - tx_fs->crypto_mke_rule = rule; - - /* Tx crypto table Default miss rule */ - memset(&flow_act, 0, sizeof(flow_act)); - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; - rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec Tx table default miss rule %d\n", err); - goto err; - } - tx_tables->crypto_miss_rule = rule; - - /* Tx check table */ - flow_table = macsec_fs_auto_group_table_create(ns, 0, TX_CHECK_TABLE_LEVEL, - TX_CHECK_TABLE_NUM_FTE); - if (IS_ERR(flow_table)) { - err = PTR_ERR(flow_table); - netdev_err(netdev, "fail to create MACsec TX check table, err(%d)\n", err); - goto err; - } - tx_tables->ft_check = flow_table; - - /* Tx check table Default miss group/rule */ - memset(flow_group_in, 0, inlen); - MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1); - flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in); - if (IS_ERR(flow_group)) { - err = PTR_ERR(flow_group); - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); - goto err; - } - tx_tables->ft_check_group = flow_group; - - /* Tx check table default drop rule */ - memset(&dest, 0, sizeof(struct mlx5_flow_destination)); - memset(&flow_act, 0, sizeof(flow_act)); - dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest.counter_id = mlx5_fc_id(tx_tables->check_miss_rule_counter); - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; - rule = mlx5_add_flow_rules(tx_tables->ft_check, NULL, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err); - goto err; - } - tx_tables->check_miss_rule = rule; - - /* Tx check table rule */ - memset(spec, 0, sizeof(struct mlx5_flow_spec)); - memset(&dest, 0, sizeof(struct mlx5_flow_destination)); - memset(&flow_act, 0, sizeof(flow_act)); - - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0); - spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; - - flow_act.flags = FLOW_ACT_NO_APPEND; - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT; - dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest.counter_id = mlx5_fc_id(tx_tables->check_rule_counter); - rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec check rule, err=%d\n", err); - goto err; - } - tx_fs->check_rule = rule; - - goto out_flow_group; - -err: - macsec_fs_tx_destroy(macsec_fs); -out_flow_group: - kvfree(flow_group_in); -out_spec: - kvfree(spec); - return err; -} - -static int macsec_fs_tx_ft_get(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct mlx5e_macsec_tables *tx_tables; - int err = 0; - - tx_tables = &tx_fs->tables; - if (tx_tables->refcnt) - goto out; - - err = macsec_fs_tx_create(macsec_fs); - if (err) - return err; - -out: - tx_tables->refcnt++; - return err; -} - -static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; - - if (--tx_tables->refcnt) - return; - - macsec_fs_tx_destroy(macsec_fs); -} - -static int macsec_fs_tx_setup_fte(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5_flow_spec *spec, - struct mlx5_flow_act *flow_act, - u32 macsec_obj_id, - u32 *fs_id) -{ - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - int err = 0; - u32 id; - - err = ida_alloc_range(&tx_fs->tx_halloc, 1, - MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES, - GFP_KERNEL); - if (err < 0) - return err; - - id = err; - spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; - - /* Metadata match */ - MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a, - MLX5_ETH_WQE_FT_META_MACSEC_MASK); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a, - MLX5_ETH_WQE_FT_META_MACSEC | id << 2); - - *fs_id = id; - flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC; - flow_act->crypto.obj_id = macsec_obj_id; - - mlx5_core_dbg(macsec_fs->mdev, "Tx fte: macsec obj_id %u, fs_id %u\n", macsec_obj_id, id); - return 0; -} - -static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx, - char *reformatbf, - size_t *reformat_size) -{ - const struct macsec_secy *secy = ctx->secy; - bool sci_present = macsec_send_sci(secy); - struct mlx5_sectag_header sectag = {}; - const struct macsec_tx_sc *tx_sc; - - tx_sc = &secy->tx_sc; - sectag.ethertype = htons(ETH_P_MACSEC); - - if (sci_present) { - sectag.tci_an |= MACSEC_TCI_SC; - memcpy(§ag.sci, &secy->sci, - sizeof(sectag.sci)); - } else { - if (tx_sc->end_station) - sectag.tci_an |= MACSEC_TCI_ES; - if (tx_sc->scb) - sectag.tci_an |= MACSEC_TCI_SCB; - } - - /* With GCM, C/E clear for !encrypt, both set for encrypt */ - if (tx_sc->encrypt) - sectag.tci_an |= MACSEC_TCI_CONFID; - else if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN) - sectag.tci_an |= MACSEC_TCI_C; - - sectag.tci_an |= tx_sc->encoding_sa; - - *reformat_size = MLX5_MACSEC_TAG_LEN + (sci_present ? MACSEC_SCI_LEN : 0); - - memcpy(reformatbf, §ag, *reformat_size); -} - -static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5e_macsec_tx_rule *tx_rule) -{ - if (tx_rule->rule) { - mlx5_del_flow_rules(tx_rule->rule); - tx_rule->rule = NULL; - } - - if (tx_rule->pkt_reformat) { - mlx5_packet_reformat_dealloc(macsec_fs->mdev, tx_rule->pkt_reformat); - tx_rule->pkt_reformat = NULL; - } - - if (tx_rule->fs_id) { - ida_free(&macsec_fs->tx_fs->tx_halloc, tx_rule->fs_id); - tx_rule->fs_id = 0; - } - - kfree(tx_rule); - - macsec_fs_tx_ft_put(macsec_fs); -} - -#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1 - -static union mlx5e_macsec_rule * -macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs, - const struct macsec_context *macsec_ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id) -{ - char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; - struct mlx5_pkt_reformat_params reformat_params = {}; - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct net_device *netdev = macsec_fs->netdev; - union mlx5e_macsec_rule *macsec_rule = NULL; - struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *tx_tables; - struct mlx5e_macsec_tx_rule *tx_rule; - struct mlx5_flow_act flow_act = {}; - struct mlx5_flow_handle *rule; - struct mlx5_flow_spec *spec; - size_t reformat_size; - int err = 0; - u32 fs_id; - - tx_tables = &tx_fs->tables; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return NULL; - - err = macsec_fs_tx_ft_get(macsec_fs); - if (err) - goto out_spec; - - macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL); - if (!macsec_rule) { - macsec_fs_tx_ft_put(macsec_fs); - goto out_spec; - } - - tx_rule = &macsec_rule->tx_rule; - - /* Tx crypto table crypto rule */ - macsec_fs_tx_create_sectag_header(macsec_ctx, reformatbf, &reformat_size); - - reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC; - reformat_params.size = reformat_size; - reformat_params.data = reformatbf; - - if (is_vlan_dev(macsec_ctx->netdev)) - reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES; - - flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, - &reformat_params, - MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); - if (IS_ERR(flow_act.pkt_reformat)) { - err = PTR_ERR(flow_act.pkt_reformat); - netdev_err(netdev, "Failed to allocate MACsec Tx reformat context err=%d\n", err); - goto err; - } - tx_rule->pkt_reformat = flow_act.pkt_reformat; - - err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id); - if (err) { - netdev_err(netdev, - "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n", - err); - goto err; - } - - tx_rule->fs_id = fs_id; - *sa_fs_id = fs_id; - - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; - dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest.ft = tx_tables->ft_check; - rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec TX crypto rule, err=%d\n", err); - goto err; - } - tx_rule->rule = rule; - - goto out_spec; - -err: - macsec_fs_tx_del_rule(macsec_fs, tx_rule); - macsec_rule = NULL; -out_spec: - kvfree(spec); - - return macsec_rule; -} - -static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *tx_tables; - - if (!tx_fs) - return; - - tx_tables = &tx_fs->tables; - if (tx_tables->refcnt) { - netdev_err(macsec_fs->netdev, - "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n", - tx_tables->refcnt); - return; - } - - ida_destroy(&tx_fs->tx_halloc); - - if (tx_tables->check_miss_rule_counter) { - mlx5_fc_destroy(mdev, tx_tables->check_miss_rule_counter); - tx_tables->check_miss_rule_counter = NULL; - } - - if (tx_tables->check_rule_counter) { - mlx5_fc_destroy(mdev, tx_tables->check_rule_counter); - tx_tables->check_rule_counter = NULL; - } - - kfree(tx_fs); - macsec_fs->tx_fs = NULL; -} - -static int macsec_fs_tx_init(struct mlx5e_macsec_fs *macsec_fs) -{ - struct net_device *netdev = macsec_fs->netdev; - struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *tx_tables; - struct mlx5e_macsec_tx *tx_fs; - struct mlx5_fc *flow_counter; - int err; - - tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL); - if (!tx_fs) - return -ENOMEM; - - tx_tables = &tx_fs->tables; - - flow_counter = mlx5_fc_create(mdev, false); - if (IS_ERR(flow_counter)) { - err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Tx encrypt flow counter, err(%d)\n", - err); - goto err_encrypt_counter; - } - tx_tables->check_rule_counter = flow_counter; - - flow_counter = mlx5_fc_create(mdev, false); - if (IS_ERR(flow_counter)) { - err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Tx drop flow counter, err(%d)\n", - err); - goto err_drop_counter; - } - tx_tables->check_miss_rule_counter = flow_counter; - - ida_init(&tx_fs->tx_halloc); - - macsec_fs->tx_fs = tx_fs; - - return 0; - -err_drop_counter: - mlx5_fc_destroy(mdev, tx_tables->check_rule_counter); - tx_tables->check_rule_counter = NULL; - -err_encrypt_counter: - kfree(tx_fs); - macsec_fs->tx_fs = NULL; - - return err; -} - -static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct mlx5e_macsec_tables *rx_tables; - int i; - - /* Rx check table */ - for (i = 1; i >= 0; --i) { - if (rx_fs->check_rule[i]) { - mlx5_del_flow_rules(rx_fs->check_rule[i]); - rx_fs->check_rule[i] = NULL; - } - - if (rx_fs->check_rule_pkt_reformat[i]) { - mlx5_packet_reformat_dealloc(macsec_fs->mdev, - rx_fs->check_rule_pkt_reformat[i]); - rx_fs->check_rule_pkt_reformat[i] = NULL; - } - } - - rx_tables = &rx_fs->tables; - - if (rx_tables->check_miss_rule) { - mlx5_del_flow_rules(rx_tables->check_miss_rule); - rx_tables->check_miss_rule = NULL; - } - - if (rx_tables->ft_check_group) { - mlx5_destroy_flow_group(rx_tables->ft_check_group); - rx_tables->ft_check_group = NULL; - } - - if (rx_tables->ft_check) { - mlx5_destroy_flow_table(rx_tables->ft_check); - rx_tables->ft_check = NULL; - } - - /* Rx crypto table */ - if (rx_tables->crypto_miss_rule) { - mlx5_del_flow_rules(rx_tables->crypto_miss_rule); - rx_tables->crypto_miss_rule = NULL; - } - - mlx5e_destroy_flow_table(&rx_tables->ft_crypto); -} - -static int macsec_fs_rx_create_crypto_table_groups(struct mlx5e_flow_table *ft) -{ - int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - int mclen = MLX5_ST_SZ_BYTES(fte_match_param); - int ix = 0; - u32 *in; - int err; - u8 *mc; - - ft->g = kcalloc(RX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL); - if (!ft->g) - return -ENOMEM; - - in = kvzalloc(inlen, GFP_KERNEL); - if (!in) { - kfree(ft->g); - return -ENOMEM; - } - - mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); - - /* Flow group for SA rule with SCI */ - MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS | - MLX5_MATCH_MISC_PARAMETERS_5); - MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); - - MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0, - MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << - MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_2); - MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_3); - - MLX5_SET_CFG(in, start_flow_index, ix); - ix += RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - /* Flow group for SA rule without SCI */ - memset(in, 0, inlen); - memset(mc, 0, mclen); - MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS | - MLX5_MATCH_MISC_PARAMETERS_5); - MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_47_16); - MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_15_0); - MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); - - MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0, - MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - - MLX5_SET_CFG(in, start_flow_index, ix); - ix += RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - /* Flow Group for l2 traps */ - memset(in, 0, inlen); - memset(mc, 0, mclen); - MLX5_SET_CFG(in, start_flow_index, ix); - ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE; - MLX5_SET_CFG(in, end_flow_index, ix - 1); - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); - if (IS_ERR(ft->g[ft->num_groups])) - goto err; - ft->num_groups++; - - kvfree(in); - return 0; - -err: - err = PTR_ERR(ft->g[ft->num_groups]); - ft->g[ft->num_groups] = NULL; - kvfree(in); - - return err; -} - -static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5_flow_destination *dest, - struct mlx5_flow_act *flow_act, - struct mlx5_flow_spec *spec, - int reformat_param_size) -{ - int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1; - u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI]; - struct mlx5_pkt_reformat_params reformat_params = {}; - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5_flow_handle *rule; - int err = 0; - - rx_tables = &rx_fs->tables; - - /* Rx check table decap 16B rule */ - memset(dest, 0, sizeof(*dest)); - memset(flow_act, 0, sizeof(*flow_act)); - memset(spec, 0, sizeof(*spec)); - - reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC; - reformat_params.size = reformat_param_size; - reformat_params.data = mlx5_reformat_buf; - flow_act->pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, - &reformat_params, - MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); - if (IS_ERR(flow_act->pkt_reformat)) { - err = PTR_ERR(flow_act->pkt_reformat); - netdev_err(netdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err); - return err; - } - rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat; - - spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; - /* MACsec syndrome match */ - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.macsec_syndrome); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.macsec_syndrome, 0); - /* ASO return reg syndrome match */ - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0); - - spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5; - /* Sectag TCI SC present bit*/ - MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0, - MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - - if (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0, - MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << - MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - - flow_act->flags = FLOW_ACT_NO_APPEND; - flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO | - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | - MLX5_FLOW_CONTEXT_ACTION_COUNT; - dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter); - rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec Rx check rule, err=%d\n", err); - return err; - } - - rx_fs->check_rule[rule_index] = rule; - - return 0; -} - -static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs) -{ - int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; - struct mlx5_flow_table_attr ft_attr = {}; - struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_flow_table *ft_crypto; - struct mlx5_flow_table *flow_table; - struct mlx5_flow_group *flow_group; - struct mlx5_flow_act flow_act = {}; - struct mlx5_flow_namespace *ns; - struct mlx5_flow_handle *rule; - struct mlx5_flow_spec *spec; - u32 *flow_group_in; - int err; - - ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); - if (!ns) - return -ENOMEM; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - - flow_group_in = kvzalloc(inlen, GFP_KERNEL); - if (!flow_group_in) { - err = -ENOMEM; - goto free_spec; - } - - rx_tables = &rx_fs->tables; - ft_crypto = &rx_tables->ft_crypto; - - /* Rx crypto table */ - ft_attr.level = RX_CRYPTO_TABLE_LEVEL; - ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; - - flow_table = mlx5_create_flow_table(ns, &ft_attr); - if (IS_ERR(flow_table)) { - err = PTR_ERR(flow_table); - netdev_err(netdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); - goto out_flow_group; - } - ft_crypto->t = flow_table; - - /* Rx crypto table groups */ - err = macsec_fs_rx_create_crypto_table_groups(ft_crypto); - if (err) { - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); - goto err; - } - - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; - rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add MACsec Rx crypto table default miss rule %d\n", - err); - goto err; - } - rx_tables->crypto_miss_rule = rule; - - /* Rx check table */ - flow_table = macsec_fs_auto_group_table_create(ns, - MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT, - RX_CHECK_TABLE_LEVEL, - RX_CHECK_TABLE_NUM_FTE); - if (IS_ERR(flow_table)) { - err = PTR_ERR(flow_table); - netdev_err(netdev, "fail to create MACsec RX check table, err(%d)\n", err); - goto err; - } - rx_tables->ft_check = flow_table; - - /* Rx check table Default miss group/rule */ - MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1); - flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in); - if (IS_ERR(flow_group)) { - err = PTR_ERR(flow_group); - netdev_err(netdev, - "Failed to create default flow group for MACsec Rx check table err(%d)\n", - err); - goto err; - } - rx_tables->ft_check_group = flow_group; - - /* Rx check table default drop rule */ - memset(&flow_act, 0, sizeof(flow_act)); - - dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest.counter_id = mlx5_fc_id(rx_tables->check_miss_rule_counter); - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; - rule = mlx5_add_flow_rules(rx_tables->ft_check, NULL, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err); - goto err; - } - rx_tables->check_miss_rule = rule; - - /* Rx check table decap rules */ - err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec, - MLX5_SECTAG_HEADER_SIZE_WITH_SCI); - if (err) - goto err; - - err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec, - MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI); - if (err) - goto err; - - goto out_flow_group; - -err: - macsec_fs_rx_destroy(macsec_fs); -out_flow_group: - kvfree(flow_group_in); -free_spec: - kvfree(spec); - return err; -} - -static int macsec_fs_rx_ft_get(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; - int err = 0; - - if (rx_tables->refcnt) - goto out; - - err = macsec_fs_rx_create(macsec_fs); - if (err) - return err; - -out: - rx_tables->refcnt++; - return err; -} - -static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; - - if (--rx_tables->refcnt) - return; - - macsec_fs_rx_destroy(macsec_fs); -} - -static void macsec_fs_rx_del_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5e_macsec_rx_rule *rx_rule) -{ - int i; - - for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) { - if (rx_rule->rule[i]) { - mlx5_del_flow_rules(rx_rule->rule[i]); - rx_rule->rule[i] = NULL; - } - } - - if (rx_rule->meta_modhdr) { - mlx5_modify_header_dealloc(macsec_fs->mdev, rx_rule->meta_modhdr); - rx_rule->meta_modhdr = NULL; - } - - kfree(rx_rule); - - macsec_fs_rx_ft_put(macsec_fs); -} - -static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec, - struct mlx5_flow_act *flow_act, - struct mlx5_macsec_rule_attrs *attrs, - bool sci_present) -{ - u8 tci_an = (sci_present << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) | attrs->assoc_num; - struct mlx5_flow_act_crypto_params *crypto_params = &flow_act->crypto; - __be32 *sci_p = (__be32 *)(&attrs->sci); - - spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; - - /* MACsec ethertype */ - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype); - MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_MACSEC); - - spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5; - - /* Sectag AN + TCI SC present bit*/ - MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0, - MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0, - tci_an << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); - - if (sci_present) { - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, - misc_parameters_5.macsec_tag_2); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_2, - be32_to_cpu(sci_p[0])); - - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, - misc_parameters_5.macsec_tag_3); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_3, - be32_to_cpu(sci_p[1])); - } else { - /* When SCI isn't present in the Sectag, need to match the source */ - /* MAC address only if the SCI contains the default MACsec PORT */ - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16); - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0); - memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers.smac_47_16), - sci_p, ETH_ALEN); - } - - crypto_params->type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC; - crypto_params->obj_id = attrs->macsec_obj_id; -} - -static union mlx5e_macsec_rule * -macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5_macsec_rule_attrs *attrs, - u32 fs_id) -{ - u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; - union mlx5e_macsec_rule *macsec_rule = NULL; - struct mlx5_modify_hdr *modify_hdr = NULL; - struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_macsec_rx_rule *rx_rule; - struct mlx5_flow_act flow_act = {}; - struct mlx5e_flow_table *ft_crypto; - struct mlx5_flow_handle *rule; - struct mlx5_flow_spec *spec; - int err = 0; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return NULL; - - err = macsec_fs_rx_ft_get(macsec_fs); - if (err) - goto out_spec; - - macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL); - if (!macsec_rule) { - macsec_fs_rx_ft_put(macsec_fs); - goto out_spec; - } - - rx_rule = &macsec_rule->rx_rule; - rx_tables = &rx_fs->tables; - ft_crypto = &rx_tables->ft_crypto; - - /* Set bit[31 - 30] macsec marker - 0x01 */ - /* Set bit[15-0] fs id */ - MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); - MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); - MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30)); - MLX5_SET(set_action_in, action, offset, 0); - MLX5_SET(set_action_in, action, length, 32); - - modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, - 1, action); - if (IS_ERR(modify_hdr)) { - err = PTR_ERR(modify_hdr); - netdev_err(netdev, "fail to alloc MACsec set modify_header_id err=%d\n", err); - modify_hdr = NULL; - goto err; - } - rx_rule->meta_modhdr = modify_hdr; - - /* Rx crypto table with SCI rule */ - macsec_fs_rx_setup_fte(spec, &flow_act, attrs, true); - - flow_act.modify_hdr = modify_hdr; - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | - MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; - - dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest.ft = rx_tables->ft_check; - rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n", - err); - goto err; - } - rx_rule->rule[0] = rule; - - /* Rx crypto table without SCI rule */ - if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) { - memset(spec, 0, sizeof(struct mlx5_flow_spec)); - memset(&dest, 0, sizeof(struct mlx5_flow_destination)); - memset(&flow_act, 0, sizeof(flow_act)); - - macsec_fs_rx_setup_fte(spec, &flow_act, attrs, false); - - flow_act.modify_hdr = modify_hdr; - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | - MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; - - dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest.ft = rx_tables->ft_check; - rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n", - err); - goto err; - } - rx_rule->rule[1] = rule; - } - - kvfree(spec); - return macsec_rule; - -err: - macsec_fs_rx_del_rule(macsec_fs, rx_rule); - macsec_rule = NULL; -out_spec: - kvfree(spec); - return macsec_rule; -} - -static int macsec_fs_rx_init(struct mlx5e_macsec_fs *macsec_fs) -{ - struct net_device *netdev = macsec_fs->netdev; - struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_macsec_rx *rx_fs; - struct mlx5_fc *flow_counter; - int err; - - rx_fs = kzalloc(sizeof(*rx_fs), GFP_KERNEL); - if (!rx_fs) - return -ENOMEM; - - flow_counter = mlx5_fc_create(mdev, false); - if (IS_ERR(flow_counter)) { - err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Rx encrypt flow counter, err(%d)\n", - err); - goto err_encrypt_counter; - } - - rx_tables = &rx_fs->tables; - rx_tables->check_rule_counter = flow_counter; - - flow_counter = mlx5_fc_create(mdev, false); - if (IS_ERR(flow_counter)) { - err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Rx drop flow counter, err(%d)\n", - err); - goto err_drop_counter; - } - rx_tables->check_miss_rule_counter = flow_counter; - - macsec_fs->rx_fs = rx_fs; - - return 0; - -err_drop_counter: - mlx5_fc_destroy(mdev, rx_tables->check_rule_counter); - rx_tables->check_rule_counter = NULL; - -err_encrypt_counter: - kfree(rx_fs); - macsec_fs->rx_fs = NULL; - - return err; -} - -static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs) -{ - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *rx_tables; - - if (!rx_fs) - return; - - rx_tables = &rx_fs->tables; - - if (rx_tables->refcnt) { - netdev_err(macsec_fs->netdev, - "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n", - rx_tables->refcnt); - return; - } - - if (rx_tables->check_miss_rule_counter) { - mlx5_fc_destroy(mdev, rx_tables->check_miss_rule_counter); - rx_tables->check_miss_rule_counter = NULL; - } - - if (rx_tables->check_rule_counter) { - mlx5_fc_destroy(mdev, rx_tables->check_rule_counter); - rx_tables->check_rule_counter = NULL; - } - - kfree(rx_fs); - macsec_fs->rx_fs = NULL; -} - -void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats) -{ - struct mlx5e_macsec_stats *stats = (struct mlx5e_macsec_stats *)macsec_stats; - struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; - struct mlx5_core_dev *mdev = macsec_fs->mdev; - - if (tx_tables->check_rule_counter) - mlx5_fc_query(mdev, tx_tables->check_rule_counter, - &stats->macsec_tx_pkts, &stats->macsec_tx_bytes); - - if (tx_tables->check_miss_rule_counter) - mlx5_fc_query(mdev, tx_tables->check_miss_rule_counter, - &stats->macsec_tx_pkts_drop, &stats->macsec_tx_bytes_drop); - - if (rx_tables->check_rule_counter) - mlx5_fc_query(mdev, rx_tables->check_rule_counter, - &stats->macsec_rx_pkts, &stats->macsec_rx_bytes); - - if (rx_tables->check_miss_rule_counter) - mlx5_fc_query(mdev, rx_tables->check_miss_rule_counter, - &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop); -} - -union mlx5e_macsec_rule * -mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, - const struct macsec_context *macsec_ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id) -{ - return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? - macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) : - macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id); -} - -void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, - union mlx5e_macsec_rule *macsec_rule, - int action) -{ - (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? - macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) : - macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule); -} - -void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs) -{ - macsec_fs_rx_cleanup(macsec_fs); - macsec_fs_tx_cleanup(macsec_fs); - kfree(macsec_fs); -} - -struct mlx5e_macsec_fs * -mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, - struct net_device *netdev) -{ - struct mlx5e_macsec_fs *macsec_fs; - int err; - - macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL); - if (!macsec_fs) - return NULL; - - macsec_fs->mdev = mdev; - macsec_fs->netdev = netdev; - - err = macsec_fs_tx_init(macsec_fs); - if (err) { - netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); - goto err; - } - - err = macsec_fs_rx_init(macsec_fs); - if (err) { - netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); - goto tx_cleanup; - } - - return macsec_fs; - -tx_cleanup: - macsec_fs_tx_cleanup(macsec_fs); -err: - kfree(macsec_fs); - return NULL; -} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h deleted file mode 100644 index b429648d4ee7..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ -/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ - -#ifndef __MLX5_MACSEC_STEERING_H__ -#define __MLX5_MACSEC_STEERING_H__ - -#ifdef CONFIG_MLX5_EN_MACSEC - -#include "en_accel/macsec.h" - -#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16 - -struct mlx5e_macsec_fs; -union mlx5e_macsec_rule; - -struct mlx5_macsec_rule_attrs { - sci_t sci; - u32 macsec_obj_id; - u8 assoc_num; - int action; -}; - -enum mlx5_macsec_action { - MLX5_ACCEL_MACSEC_ACTION_ENCRYPT, - MLX5_ACCEL_MACSEC_ACTION_DECRYPT, -}; - -void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs); - -struct mlx5e_macsec_fs * -mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev); - -union mlx5e_macsec_rule * -mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, - const struct macsec_context *ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id); - -void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, - union mlx5e_macsec_rule *macsec_rule, - int action); - -void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats); - -#endif - -#endif /* __MLX5_MACSEC_STEERING_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 4d77055abd4b..8d7a5a815162 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -2490,7 +2490,7 @@ mlx5e_stats_grp_t mlx5e_nic_stats_grps[] = { &MLX5E_STATS_GRP(per_port_buff_congest), &MLX5E_STATS_GRP(ptp), &MLX5E_STATS_GRP(qos), -#ifdef CONFIG_MLX5_EN_MACSEC +#ifdef CONFIG_MLX5_MACSEC &MLX5E_STATS_GRP(macsec_hw), #endif }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c new file mode 100644 index 000000000000..3d816ee382e3 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -0,0 +1,1393 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#include +#include +#include +#include +#include "fs_core.h" +#include "en/fs.h" +#include "lib/macsec_fs.h" +#include "mlx5_core.h" + +/* MACsec TX flow steering */ +#define CRYPTO_NUM_MAXSEC_FTE BIT(15) +#define CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE 1 + +#define TX_CRYPTO_TABLE_LEVEL 0 +#define TX_CRYPTO_TABLE_NUM_GROUPS 3 +#define TX_CRYPTO_TABLE_MKE_GROUP_SIZE 1 +#define TX_CRYPTO_TABLE_SA_GROUP_SIZE \ + (CRYPTO_NUM_MAXSEC_FTE - (TX_CRYPTO_TABLE_MKE_GROUP_SIZE + \ + CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE)) +#define TX_CHECK_TABLE_LEVEL 1 +#define TX_CHECK_TABLE_NUM_FTE 2 +#define RX_CRYPTO_TABLE_LEVEL 0 +#define RX_CHECK_TABLE_LEVEL 1 +#define RX_CHECK_TABLE_NUM_FTE 3 +#define RX_CRYPTO_TABLE_NUM_GROUPS 3 +#define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \ + ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2) +#define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \ + (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE) +#define RX_NUM_OF_RULES_PER_SA 2 + +#define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */ +#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23 +#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8 +#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET 0x5 +#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT (0x1 << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) +#define MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI 0x8 +#define MLX5_SECTAG_HEADER_SIZE_WITH_SCI (MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI + MACSEC_SCI_LEN) + +/* MACsec RX flow steering */ +#define MLX5_ETH_WQE_FT_META_MACSEC_MASK 0x3E + +struct mlx5_sectag_header { + __be16 ethertype; + u8 tci_an; + u8 sl; + u32 pn; + u8 sci[MACSEC_SCI_LEN]; /* optional */ +} __packed; + +struct mlx5e_macsec_tx_rule { + struct mlx5_flow_handle *rule; + struct mlx5_pkt_reformat *pkt_reformat; + u32 fs_id; +}; + +struct mlx5e_macsec_tables { + struct mlx5e_flow_table ft_crypto; + struct mlx5_flow_handle *crypto_miss_rule; + + struct mlx5_flow_table *ft_check; + struct mlx5_flow_group *ft_check_group; + struct mlx5_fc *check_miss_rule_counter; + struct mlx5_flow_handle *check_miss_rule; + struct mlx5_fc *check_rule_counter; + + u32 refcnt; +}; + +struct mlx5e_macsec_tx { + struct mlx5_flow_handle *crypto_mke_rule; + struct mlx5_flow_handle *check_rule; + + struct ida tx_halloc; + + struct mlx5e_macsec_tables tables; +}; + +struct mlx5e_macsec_rx_rule { + struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA]; + struct mlx5_modify_hdr *meta_modhdr; +}; + +struct mlx5e_macsec_rx { + struct mlx5_flow_handle *check_rule[2]; + struct mlx5_pkt_reformat *check_rule_pkt_reformat[2]; + + struct mlx5e_macsec_tables tables; +}; + +union mlx5e_macsec_rule { + struct mlx5e_macsec_tx_rule tx_rule; + struct mlx5e_macsec_rx_rule rx_rule; +}; + +struct mlx5e_macsec_fs { + struct mlx5_core_dev *mdev; + struct net_device *netdev; + struct mlx5e_macsec_tx *tx_fs; + struct mlx5e_macsec_rx *rx_fs; +}; + +static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5e_macsec_tables *tx_tables; + + tx_tables = &tx_fs->tables; + + /* Tx check table */ + if (tx_fs->check_rule) { + mlx5_del_flow_rules(tx_fs->check_rule); + tx_fs->check_rule = NULL; + } + + if (tx_tables->check_miss_rule) { + mlx5_del_flow_rules(tx_tables->check_miss_rule); + tx_tables->check_miss_rule = NULL; + } + + if (tx_tables->ft_check_group) { + mlx5_destroy_flow_group(tx_tables->ft_check_group); + tx_tables->ft_check_group = NULL; + } + + if (tx_tables->ft_check) { + mlx5_destroy_flow_table(tx_tables->ft_check); + tx_tables->ft_check = NULL; + } + + /* Tx crypto table */ + if (tx_fs->crypto_mke_rule) { + mlx5_del_flow_rules(tx_fs->crypto_mke_rule); + tx_fs->crypto_mke_rule = NULL; + } + + if (tx_tables->crypto_miss_rule) { + mlx5_del_flow_rules(tx_tables->crypto_miss_rule); + tx_tables->crypto_miss_rule = NULL; + } + + mlx5e_destroy_flow_table(&tx_tables->ft_crypto); +} + +static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft) +{ + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); + int mclen = MLX5_ST_SZ_BYTES(fte_match_param); + int ix = 0; + u32 *in; + int err; + u8 *mc; + + ft->g = kcalloc(TX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL); + if (!ft->g) + return -ENOMEM; + in = kvzalloc(inlen, GFP_KERNEL); + + if (!in) { + kfree(ft->g); + return -ENOMEM; + } + + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); + + /* Flow Group for MKE match */ + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); + MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); + + MLX5_SET_CFG(in, start_flow_index, ix); + ix += TX_CRYPTO_TABLE_MKE_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + /* Flow Group for SA rules */ + memset(in, 0, inlen); + memset(mc, 0, mclen); + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2); + MLX5_SET(fte_match_param, mc, misc_parameters_2.metadata_reg_a, + MLX5_ETH_WQE_FT_META_MACSEC_MASK); + + MLX5_SET_CFG(in, start_flow_index, ix); + ix += TX_CRYPTO_TABLE_SA_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + /* Flow Group for l2 traps */ + memset(in, 0, inlen); + memset(mc, 0, mclen); + MLX5_SET_CFG(in, start_flow_index, ix); + ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + kvfree(in); + return 0; + +err: + err = PTR_ERR(ft->g[ft->num_groups]); + ft->g[ft->num_groups] = NULL; + kvfree(in); + + return err; +} + +static struct mlx5_flow_table + *macsec_fs_auto_group_table_create(struct mlx5_flow_namespace *ns, int flags, + int level, int max_fte) +{ + struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_table *fdb = NULL; + + /* reserve entry for the match all miss group and rule */ + ft_attr.autogroup.num_reserved_entries = 1; + ft_attr.autogroup.max_num_groups = 1; + ft_attr.prio = 0; + ft_attr.flags = flags; + ft_attr.level = level; + ft_attr.max_fte = max_fte; + + fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); + + return fdb; +} + +static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs) +{ + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct net_device *netdev = macsec_fs->netdev; + struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_destination dest = {}; + struct mlx5e_macsec_tables *tx_tables; + struct mlx5_flow_act flow_act = {}; + struct mlx5e_flow_table *ft_crypto; + struct mlx5_flow_table *flow_table; + struct mlx5_flow_group *flow_group; + struct mlx5_flow_namespace *ns; + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + u32 *flow_group_in; + int err; + + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); + if (!ns) + return -ENOMEM; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + flow_group_in = kvzalloc(inlen, GFP_KERNEL); + if (!flow_group_in) { + err = -ENOMEM; + goto out_spec; + } + + tx_tables = &tx_fs->tables; + ft_crypto = &tx_tables->ft_crypto; + + /* Tx crypto table */ + ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + ft_attr.level = TX_CRYPTO_TABLE_LEVEL; + ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; + + flow_table = mlx5_create_flow_table(ns, &ft_attr); + if (IS_ERR(flow_table)) { + err = PTR_ERR(flow_table); + netdev_err(netdev, "Failed to create MACsec Tx crypto table err(%d)\n", err); + goto out_flow_group; + } + ft_crypto->t = flow_table; + + /* Tx crypto table groups */ + err = macsec_fs_tx_create_crypto_table_groups(ft_crypto); + if (err) { + netdev_err(netdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); + goto err; + } + + /* Tx crypto table MKE rule - MKE packets shouldn't be offloaded */ + spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype); + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_PAE); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + + rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to add MACsec TX MKE rule, err=%d\n", err); + goto err; + } + tx_fs->crypto_mke_rule = rule; + + /* Tx crypto table Default miss rule */ + memset(&flow_act, 0, sizeof(flow_act)); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to add MACsec Tx table default miss rule %d\n", err); + goto err; + } + tx_tables->crypto_miss_rule = rule; + + /* Tx check table */ + flow_table = macsec_fs_auto_group_table_create(ns, 0, TX_CHECK_TABLE_LEVEL, + TX_CHECK_TABLE_NUM_FTE); + if (IS_ERR(flow_table)) { + err = PTR_ERR(flow_table); + netdev_err(netdev, "fail to create MACsec TX check table, err(%d)\n", err); + goto err; + } + tx_tables->ft_check = flow_table; + + /* Tx check table Default miss group/rule */ + memset(flow_group_in, 0, inlen); + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1); + flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in); + if (IS_ERR(flow_group)) { + err = PTR_ERR(flow_group); + netdev_err(netdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); + goto err; + } + tx_tables->ft_check_group = flow_group; + + /* Tx check table default drop rule */ + memset(&dest, 0, sizeof(struct mlx5_flow_destination)); + memset(&flow_act, 0, sizeof(flow_act)); + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest.counter_id = mlx5_fc_id(tx_tables->check_miss_rule_counter); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; + rule = mlx5_add_flow_rules(tx_tables->ft_check, NULL, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err); + goto err; + } + tx_tables->check_miss_rule = rule; + + /* Tx check table rule */ + memset(spec, 0, sizeof(struct mlx5_flow_spec)); + memset(&dest, 0, sizeof(struct mlx5_flow_destination)); + memset(&flow_act, 0, sizeof(flow_act)); + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0); + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; + + flow_act.flags = FLOW_ACT_NO_APPEND; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest.counter_id = mlx5_fc_id(tx_tables->check_rule_counter); + rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to add MACsec check rule, err=%d\n", err); + goto err; + } + tx_fs->check_rule = rule; + + goto out_flow_group; + +err: + macsec_fs_tx_destroy(macsec_fs); +out_flow_group: + kvfree(flow_group_in); +out_spec: + kvfree(spec); + return err; +} + +static int macsec_fs_tx_ft_get(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5e_macsec_tables *tx_tables; + int err = 0; + + tx_tables = &tx_fs->tables; + if (tx_tables->refcnt) + goto out; + + err = macsec_fs_tx_create(macsec_fs); + if (err) + return err; + +out: + tx_tables->refcnt++; + return err; +} + +static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; + + if (--tx_tables->refcnt) + return; + + macsec_fs_tx_destroy(macsec_fs); +} + +static int macsec_fs_tx_setup_fte(struct mlx5e_macsec_fs *macsec_fs, + struct mlx5_flow_spec *spec, + struct mlx5_flow_act *flow_act, + u32 macsec_obj_id, + u32 *fs_id) +{ + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + int err = 0; + u32 id; + + err = ida_alloc_range(&tx_fs->tx_halloc, 1, + MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES, + GFP_KERNEL); + if (err < 0) + return err; + + id = err; + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; + + /* Metadata match */ + MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a, + MLX5_ETH_WQE_FT_META_MACSEC_MASK); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a, + MLX5_ETH_WQE_FT_META_MACSEC | id << 2); + + *fs_id = id; + flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC; + flow_act->crypto.obj_id = macsec_obj_id; + + mlx5_core_dbg(macsec_fs->mdev, "Tx fte: macsec obj_id %u, fs_id %u\n", macsec_obj_id, id); + return 0; +} + +static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx, + char *reformatbf, + size_t *reformat_size) +{ + const struct macsec_secy *secy = ctx->secy; + bool sci_present = macsec_send_sci(secy); + struct mlx5_sectag_header sectag = {}; + const struct macsec_tx_sc *tx_sc; + + tx_sc = &secy->tx_sc; + sectag.ethertype = htons(ETH_P_MACSEC); + + if (sci_present) { + sectag.tci_an |= MACSEC_TCI_SC; + memcpy(§ag.sci, &secy->sci, + sizeof(sectag.sci)); + } else { + if (tx_sc->end_station) + sectag.tci_an |= MACSEC_TCI_ES; + if (tx_sc->scb) + sectag.tci_an |= MACSEC_TCI_SCB; + } + + /* With GCM, C/E clear for !encrypt, both set for encrypt */ + if (tx_sc->encrypt) + sectag.tci_an |= MACSEC_TCI_CONFID; + else if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN) + sectag.tci_an |= MACSEC_TCI_C; + + sectag.tci_an |= tx_sc->encoding_sa; + + *reformat_size = MLX5_MACSEC_TAG_LEN + (sci_present ? MACSEC_SCI_LEN : 0); + + memcpy(reformatbf, §ag, *reformat_size); +} + +static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs, + struct mlx5e_macsec_tx_rule *tx_rule) +{ + if (tx_rule->rule) { + mlx5_del_flow_rules(tx_rule->rule); + tx_rule->rule = NULL; + } + + if (tx_rule->pkt_reformat) { + mlx5_packet_reformat_dealloc(macsec_fs->mdev, tx_rule->pkt_reformat); + tx_rule->pkt_reformat = NULL; + } + + if (tx_rule->fs_id) { + ida_free(&macsec_fs->tx_fs->tx_halloc, tx_rule->fs_id); + tx_rule->fs_id = 0; + } + + kfree(tx_rule); + + macsec_fs_tx_ft_put(macsec_fs); +} + +#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1 + +static union mlx5e_macsec_rule * +macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs, + const struct macsec_context *macsec_ctx, + struct mlx5_macsec_rule_attrs *attrs, + u32 *sa_fs_id) +{ + char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; + struct mlx5_pkt_reformat_params reformat_params = {}; + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct net_device *netdev = macsec_fs->netdev; + union mlx5e_macsec_rule *macsec_rule = NULL; + struct mlx5_flow_destination dest = {}; + struct mlx5e_macsec_tables *tx_tables; + struct mlx5e_macsec_tx_rule *tx_rule; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + size_t reformat_size; + int err = 0; + u32 fs_id; + + tx_tables = &tx_fs->tables; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return NULL; + + err = macsec_fs_tx_ft_get(macsec_fs); + if (err) + goto out_spec; + + macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL); + if (!macsec_rule) { + macsec_fs_tx_ft_put(macsec_fs); + goto out_spec; + } + + tx_rule = &macsec_rule->tx_rule; + + /* Tx crypto table crypto rule */ + macsec_fs_tx_create_sectag_header(macsec_ctx, reformatbf, &reformat_size); + + reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC; + reformat_params.size = reformat_size; + reformat_params.data = reformatbf; + + if (is_vlan_dev(macsec_ctx->netdev)) + reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES; + + flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, + &reformat_params, + MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); + if (IS_ERR(flow_act.pkt_reformat)) { + err = PTR_ERR(flow_act.pkt_reformat); + netdev_err(netdev, "Failed to allocate MACsec Tx reformat context err=%d\n", err); + goto err; + } + tx_rule->pkt_reformat = flow_act.pkt_reformat; + + err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id); + if (err) { + netdev_err(netdev, + "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n", + err); + goto err; + } + + tx_rule->fs_id = fs_id; + *sa_fs_id = fs_id; + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | + MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest.ft = tx_tables->ft_check; + rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to add MACsec TX crypto rule, err=%d\n", err); + goto err; + } + tx_rule->rule = rule; + + goto out_spec; + +err: + macsec_fs_tx_del_rule(macsec_fs, tx_rule); + macsec_rule = NULL; +out_spec: + kvfree(spec); + + return macsec_rule; +} + +static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5e_macsec_tables *tx_tables; + + if (!tx_fs) + return; + + tx_tables = &tx_fs->tables; + if (tx_tables->refcnt) { + netdev_err(macsec_fs->netdev, + "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n", + tx_tables->refcnt); + return; + } + + ida_destroy(&tx_fs->tx_halloc); + + if (tx_tables->check_miss_rule_counter) { + mlx5_fc_destroy(mdev, tx_tables->check_miss_rule_counter); + tx_tables->check_miss_rule_counter = NULL; + } + + if (tx_tables->check_rule_counter) { + mlx5_fc_destroy(mdev, tx_tables->check_rule_counter); + tx_tables->check_rule_counter = NULL; + } + + kfree(tx_fs); + macsec_fs->tx_fs = NULL; +} + +static int macsec_fs_tx_init(struct mlx5e_macsec_fs *macsec_fs) +{ + struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5e_macsec_tables *tx_tables; + struct mlx5e_macsec_tx *tx_fs; + struct mlx5_fc *flow_counter; + int err; + + tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL); + if (!tx_fs) + return -ENOMEM; + + tx_tables = &tx_fs->tables; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + err = PTR_ERR(flow_counter); + netdev_err(netdev, + "Failed to create MACsec Tx encrypt flow counter, err(%d)\n", + err); + goto err_encrypt_counter; + } + tx_tables->check_rule_counter = flow_counter; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + err = PTR_ERR(flow_counter); + netdev_err(netdev, + "Failed to create MACsec Tx drop flow counter, err(%d)\n", + err); + goto err_drop_counter; + } + tx_tables->check_miss_rule_counter = flow_counter; + + ida_init(&tx_fs->tx_halloc); + + macsec_fs->tx_fs = tx_fs; + + return 0; + +err_drop_counter: + mlx5_fc_destroy(mdev, tx_tables->check_rule_counter); + tx_tables->check_rule_counter = NULL; + +err_encrypt_counter: + kfree(tx_fs); + macsec_fs->tx_fs = NULL; + + return err; +} + +static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5e_macsec_tables *rx_tables; + int i; + + /* Rx check table */ + for (i = 1; i >= 0; --i) { + if (rx_fs->check_rule[i]) { + mlx5_del_flow_rules(rx_fs->check_rule[i]); + rx_fs->check_rule[i] = NULL; + } + + if (rx_fs->check_rule_pkt_reformat[i]) { + mlx5_packet_reformat_dealloc(macsec_fs->mdev, + rx_fs->check_rule_pkt_reformat[i]); + rx_fs->check_rule_pkt_reformat[i] = NULL; + } + } + + rx_tables = &rx_fs->tables; + + if (rx_tables->check_miss_rule) { + mlx5_del_flow_rules(rx_tables->check_miss_rule); + rx_tables->check_miss_rule = NULL; + } + + if (rx_tables->ft_check_group) { + mlx5_destroy_flow_group(rx_tables->ft_check_group); + rx_tables->ft_check_group = NULL; + } + + if (rx_tables->ft_check) { + mlx5_destroy_flow_table(rx_tables->ft_check); + rx_tables->ft_check = NULL; + } + + /* Rx crypto table */ + if (rx_tables->crypto_miss_rule) { + mlx5_del_flow_rules(rx_tables->crypto_miss_rule); + rx_tables->crypto_miss_rule = NULL; + } + + mlx5e_destroy_flow_table(&rx_tables->ft_crypto); +} + +static int macsec_fs_rx_create_crypto_table_groups(struct mlx5e_flow_table *ft) +{ + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); + int mclen = MLX5_ST_SZ_BYTES(fte_match_param); + int ix = 0; + u32 *in; + int err; + u8 *mc; + + ft->g = kcalloc(RX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL); + if (!ft->g) + return -ENOMEM; + + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + kfree(ft->g); + return -ENOMEM; + } + + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); + + /* Flow group for SA rule with SCI */ + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS | + MLX5_MATCH_MISC_PARAMETERS_5); + MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); + + MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0, + MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << + MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_2); + MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_3); + + MLX5_SET_CFG(in, start_flow_index, ix); + ix += RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + /* Flow group for SA rule without SCI */ + memset(in, 0, inlen); + memset(mc, 0, mclen); + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS | + MLX5_MATCH_MISC_PARAMETERS_5); + MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_47_16); + MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_15_0); + MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype); + + MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0, + MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + + MLX5_SET_CFG(in, start_flow_index, ix); + ix += RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + /* Flow Group for l2 traps */ + memset(in, 0, inlen); + memset(mc, 0, mclen); + MLX5_SET_CFG(in, start_flow_index, ix); + ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); + if (IS_ERR(ft->g[ft->num_groups])) + goto err; + ft->num_groups++; + + kvfree(in); + return 0; + +err: + err = PTR_ERR(ft->g[ft->num_groups]); + ft->g[ft->num_groups] = NULL; + kvfree(in); + + return err; +} + +static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_fs, + struct mlx5_flow_destination *dest, + struct mlx5_flow_act *flow_act, + struct mlx5_flow_spec *spec, + int reformat_param_size) +{ + int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1; + u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI]; + struct mlx5_pkt_reformat_params reformat_params = {}; + struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct net_device *netdev = macsec_fs->netdev; + struct mlx5e_macsec_tables *rx_tables; + struct mlx5_flow_handle *rule; + int err = 0; + + rx_tables = &rx_fs->tables; + + /* Rx check table decap 16B rule */ + memset(dest, 0, sizeof(*dest)); + memset(flow_act, 0, sizeof(*flow_act)); + memset(spec, 0, sizeof(*spec)); + + reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC; + reformat_params.size = reformat_param_size; + reformat_params.data = mlx5_reformat_buf; + flow_act->pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, + &reformat_params, + MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); + if (IS_ERR(flow_act->pkt_reformat)) { + err = PTR_ERR(flow_act->pkt_reformat); + netdev_err(netdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err); + return err; + } + rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat; + + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; + /* MACsec syndrome match */ + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.macsec_syndrome); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.macsec_syndrome, 0); + /* ASO return reg syndrome match */ + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5; + /* Sectag TCI SC present bit*/ + MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0, + MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + + if (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0, + MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << + MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + + flow_act->flags = FLOW_ACT_NO_APPEND; + flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO | + MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter); + rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to add MACsec Rx check rule, err=%d\n", err); + return err; + } + + rx_fs->check_rule[rule_index] = rule; + + return 0; +} + +static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs) +{ + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); + struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct net_device *netdev = macsec_fs->netdev; + struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_destination dest = {}; + struct mlx5e_macsec_tables *rx_tables; + struct mlx5e_flow_table *ft_crypto; + struct mlx5_flow_table *flow_table; + struct mlx5_flow_group *flow_group; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_namespace *ns; + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + u32 *flow_group_in; + int err; + + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); + if (!ns) + return -ENOMEM; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + flow_group_in = kvzalloc(inlen, GFP_KERNEL); + if (!flow_group_in) { + err = -ENOMEM; + goto free_spec; + } + + rx_tables = &rx_fs->tables; + ft_crypto = &rx_tables->ft_crypto; + + /* Rx crypto table */ + ft_attr.level = RX_CRYPTO_TABLE_LEVEL; + ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; + + flow_table = mlx5_create_flow_table(ns, &ft_attr); + if (IS_ERR(flow_table)) { + err = PTR_ERR(flow_table); + netdev_err(netdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); + goto out_flow_group; + } + ft_crypto->t = flow_table; + + /* Rx crypto table groups */ + err = macsec_fs_rx_create_crypto_table_groups(ft_crypto); + if (err) { + netdev_err(netdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); + goto err; + } + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, + "Failed to add MACsec Rx crypto table default miss rule %d\n", + err); + goto err; + } + rx_tables->crypto_miss_rule = rule; + + /* Rx check table */ + flow_table = macsec_fs_auto_group_table_create(ns, + MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT, + RX_CHECK_TABLE_LEVEL, + RX_CHECK_TABLE_NUM_FTE); + if (IS_ERR(flow_table)) { + err = PTR_ERR(flow_table); + netdev_err(netdev, "fail to create MACsec RX check table, err(%d)\n", err); + goto err; + } + rx_tables->ft_check = flow_table; + + /* Rx check table Default miss group/rule */ + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1); + flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in); + if (IS_ERR(flow_group)) { + err = PTR_ERR(flow_group); + netdev_err(netdev, + "Failed to create default flow group for MACsec Rx check table err(%d)\n", + err); + goto err; + } + rx_tables->ft_check_group = flow_group; + + /* Rx check table default drop rule */ + memset(&flow_act, 0, sizeof(flow_act)); + + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest.counter_id = mlx5_fc_id(rx_tables->check_miss_rule_counter); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; + rule = mlx5_add_flow_rules(rx_tables->ft_check, NULL, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err); + goto err; + } + rx_tables->check_miss_rule = rule; + + /* Rx check table decap rules */ + err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec, + MLX5_SECTAG_HEADER_SIZE_WITH_SCI); + if (err) + goto err; + + err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec, + MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI); + if (err) + goto err; + + goto out_flow_group; + +err: + macsec_fs_rx_destroy(macsec_fs); +out_flow_group: + kvfree(flow_group_in); +free_spec: + kvfree(spec); + return err; +} + +static int macsec_fs_rx_ft_get(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + int err = 0; + + if (rx_tables->refcnt) + goto out; + + err = macsec_fs_rx_create(macsec_fs); + if (err) + return err; + +out: + rx_tables->refcnt++; + return err; +} + +static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + + if (--rx_tables->refcnt) + return; + + macsec_fs_rx_destroy(macsec_fs); +} + +static void macsec_fs_rx_del_rule(struct mlx5e_macsec_fs *macsec_fs, + struct mlx5e_macsec_rx_rule *rx_rule) +{ + int i; + + for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) { + if (rx_rule->rule[i]) { + mlx5_del_flow_rules(rx_rule->rule[i]); + rx_rule->rule[i] = NULL; + } + } + + if (rx_rule->meta_modhdr) { + mlx5_modify_header_dealloc(macsec_fs->mdev, rx_rule->meta_modhdr); + rx_rule->meta_modhdr = NULL; + } + + kfree(rx_rule); + + macsec_fs_rx_ft_put(macsec_fs); +} + +static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec, + struct mlx5_flow_act *flow_act, + struct mlx5_macsec_rule_attrs *attrs, + bool sci_present) +{ + u8 tci_an = (sci_present << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) | attrs->assoc_num; + struct mlx5_flow_act_crypto_params *crypto_params = &flow_act->crypto; + __be32 *sci_p = (__be32 *)(&attrs->sci); + + spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; + + /* MACsec ethertype */ + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype); + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_MACSEC); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5; + + /* Sectag AN + TCI SC present bit*/ + MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0, + MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0, + tci_an << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); + + if (sci_present) { + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + misc_parameters_5.macsec_tag_2); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_2, + be32_to_cpu(sci_p[0])); + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + misc_parameters_5.macsec_tag_3); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_3, + be32_to_cpu(sci_p[1])); + } else { + /* When SCI isn't present in the Sectag, need to match the source */ + /* MAC address only if the SCI contains the default MACsec PORT */ + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16); + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0); + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers.smac_47_16), + sci_p, ETH_ALEN); + } + + crypto_params->type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC; + crypto_params->obj_id = attrs->macsec_obj_id; +} + +static union mlx5e_macsec_rule * +macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs, + struct mlx5_macsec_rule_attrs *attrs, + u32 fs_id) +{ + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; + struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct net_device *netdev = macsec_fs->netdev; + union mlx5e_macsec_rule *macsec_rule = NULL; + struct mlx5_modify_hdr *modify_hdr = NULL; + struct mlx5_flow_destination dest = {}; + struct mlx5e_macsec_tables *rx_tables; + struct mlx5e_macsec_rx_rule *rx_rule; + struct mlx5_flow_act flow_act = {}; + struct mlx5e_flow_table *ft_crypto; + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + int err = 0; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return NULL; + + err = macsec_fs_rx_ft_get(macsec_fs); + if (err) + goto out_spec; + + macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL); + if (!macsec_rule) { + macsec_fs_rx_ft_put(macsec_fs); + goto out_spec; + } + + rx_rule = &macsec_rule->rx_rule; + rx_tables = &rx_fs->tables; + ft_crypto = &rx_tables->ft_crypto; + + /* Set bit[31 - 30] macsec marker - 0x01 */ + /* Set bit[15-0] fs id */ + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); + MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); + MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30)); + MLX5_SET(set_action_in, action, offset, 0); + MLX5_SET(set_action_in, action, length, 32); + + modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, + 1, action); + if (IS_ERR(modify_hdr)) { + err = PTR_ERR(modify_hdr); + netdev_err(netdev, "fail to alloc MACsec set modify_header_id err=%d\n", err); + modify_hdr = NULL; + goto err; + } + rx_rule->meta_modhdr = modify_hdr; + + /* Rx crypto table with SCI rule */ + macsec_fs_rx_setup_fte(spec, &flow_act, attrs, true); + + flow_act.modify_hdr = modify_hdr; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | + MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest.ft = rx_tables->ft_check; + rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, + "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n", + err); + goto err; + } + rx_rule->rule[0] = rule; + + /* Rx crypto table without SCI rule */ + if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) { + memset(spec, 0, sizeof(struct mlx5_flow_spec)); + memset(&dest, 0, sizeof(struct mlx5_flow_destination)); + memset(&flow_act, 0, sizeof(flow_act)); + + macsec_fs_rx_setup_fte(spec, &flow_act, attrs, false); + + flow_act.modify_hdr = modify_hdr; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | + MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest.ft = rx_tables->ft_check; + rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + netdev_err(netdev, + "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n", + err); + goto err; + } + rx_rule->rule[1] = rule; + } + + kvfree(spec); + return macsec_rule; + +err: + macsec_fs_rx_del_rule(macsec_fs, rx_rule); + macsec_rule = NULL; +out_spec: + kvfree(spec); + return macsec_rule; +} + +static int macsec_fs_rx_init(struct mlx5e_macsec_fs *macsec_fs) +{ + struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5e_macsec_tables *rx_tables; + struct mlx5e_macsec_rx *rx_fs; + struct mlx5_fc *flow_counter; + int err; + + rx_fs = kzalloc(sizeof(*rx_fs), GFP_KERNEL); + if (!rx_fs) + return -ENOMEM; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + err = PTR_ERR(flow_counter); + netdev_err(netdev, + "Failed to create MACsec Rx encrypt flow counter, err(%d)\n", + err); + goto err_encrypt_counter; + } + + rx_tables = &rx_fs->tables; + rx_tables->check_rule_counter = flow_counter; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + err = PTR_ERR(flow_counter); + netdev_err(netdev, + "Failed to create MACsec Rx drop flow counter, err(%d)\n", + err); + goto err_drop_counter; + } + rx_tables->check_miss_rule_counter = flow_counter; + + macsec_fs->rx_fs = rx_fs; + + return 0; + +err_drop_counter: + mlx5_fc_destroy(mdev, rx_tables->check_rule_counter); + rx_tables->check_rule_counter = NULL; + +err_encrypt_counter: + kfree(rx_fs); + macsec_fs->rx_fs = NULL; + + return err; +} + +static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs) +{ + struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5e_macsec_tables *rx_tables; + + if (!rx_fs) + return; + + rx_tables = &rx_fs->tables; + + if (rx_tables->refcnt) { + netdev_err(macsec_fs->netdev, + "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n", + rx_tables->refcnt); + return; + } + + if (rx_tables->check_miss_rule_counter) { + mlx5_fc_destroy(mdev, rx_tables->check_miss_rule_counter); + rx_tables->check_miss_rule_counter = NULL; + } + + if (rx_tables->check_rule_counter) { + mlx5_fc_destroy(mdev, rx_tables->check_rule_counter); + rx_tables->check_rule_counter = NULL; + } + + kfree(rx_fs); + macsec_fs->rx_fs = NULL; +} + +void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats) +{ + struct mlx5e_macsec_stats *stats = (struct mlx5e_macsec_stats *)macsec_stats; + struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; + struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + + if (tx_tables->check_rule_counter) + mlx5_fc_query(mdev, tx_tables->check_rule_counter, + &stats->macsec_tx_pkts, &stats->macsec_tx_bytes); + + if (tx_tables->check_miss_rule_counter) + mlx5_fc_query(mdev, tx_tables->check_miss_rule_counter, + &stats->macsec_tx_pkts_drop, &stats->macsec_tx_bytes_drop); + + if (rx_tables->check_rule_counter) + mlx5_fc_query(mdev, rx_tables->check_rule_counter, + &stats->macsec_rx_pkts, &stats->macsec_rx_bytes); + + if (rx_tables->check_miss_rule_counter) + mlx5_fc_query(mdev, rx_tables->check_miss_rule_counter, + &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop); +} + +union mlx5e_macsec_rule * +mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, + const struct macsec_context *macsec_ctx, + struct mlx5_macsec_rule_attrs *attrs, + u32 *sa_fs_id) +{ + return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? + macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) : + macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id); +} + +void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, + union mlx5e_macsec_rule *macsec_rule, + int action) +{ + (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? + macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) : + macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule); +} + +void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs) +{ + macsec_fs_rx_cleanup(macsec_fs); + macsec_fs_tx_cleanup(macsec_fs); + kfree(macsec_fs); +} + +struct mlx5e_macsec_fs * +mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, + struct net_device *netdev) +{ + struct mlx5e_macsec_fs *macsec_fs; + int err; + + macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL); + if (!macsec_fs) + return NULL; + + macsec_fs->mdev = mdev; + macsec_fs->netdev = netdev; + + err = macsec_fs_tx_init(macsec_fs); + if (err) { + netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); + goto err; + } + + err = macsec_fs_rx_init(macsec_fs); + if (err) { + netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); + goto tx_cleanup; + } + + return macsec_fs; + +tx_cleanup: + macsec_fs_tx_cleanup(macsec_fs); +err: + kfree(macsec_fs); + return NULL; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h new file mode 100644 index 000000000000..b282c0850e16 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#ifndef __MLX5_MACSEC_STEERING_H__ +#define __MLX5_MACSEC_STEERING_H__ + +#ifdef CONFIG_MLX5_MACSEC + +/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */ +#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */ +#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX +#define MLX5_MACSEC_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x1) +#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata) ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK) + +#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16 + +struct mlx5e_macsec_fs; +union mlx5e_macsec_rule; + +struct mlx5_macsec_rule_attrs { + sci_t sci; + u32 macsec_obj_id; + u8 assoc_num; + int action; +}; + +struct mlx5e_macsec_stats { + u64 macsec_rx_pkts; + u64 macsec_rx_bytes; + u64 macsec_rx_pkts_drop; + u64 macsec_rx_bytes_drop; + u64 macsec_tx_pkts; + u64 macsec_tx_bytes; + u64 macsec_tx_pkts_drop; + u64 macsec_tx_bytes_drop; +}; + +enum mlx5_macsec_action { + MLX5_ACCEL_MACSEC_ACTION_ENCRYPT, + MLX5_ACCEL_MACSEC_ACTION_DECRYPT, +}; + +void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs); + +struct mlx5e_macsec_fs * +mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev); + +union mlx5e_macsec_rule * +mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, + const struct macsec_context *ctx, + struct mlx5_macsec_rule_attrs *attrs, + u32 *sa_fs_id); + +void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, + union mlx5e_macsec_rule *macsec_rule, + int action); + +void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats); + +#endif + +#endif /* __MLX5_MACSEC_STEERING_H__ */ -- cgit From 88ff18c01a0a3d2ee262c9c99979e0451af2c7af Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Mon, 1 May 2023 15:11:53 +0300 Subject: net/mlx5: Remove dependency of macsec flow steering on ethernet Since macsec flow steering was moved to core, it should be independent of all ethernet code and structures hence we remove all ethernet header includes and redefine ethernet structs internally for macsec_fs usage where needed. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 43 +++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 3d816ee382e3..40883d2b78c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -6,7 +6,6 @@ #include #include #include "fs_core.h" -#include "en/fs.h" #include "lib/macsec_fs.h" #include "mlx5_core.h" @@ -57,8 +56,14 @@ struct mlx5e_macsec_tx_rule { u32 fs_id; }; +struct mlx5_macsec_flow_table { + int num_groups; + struct mlx5_flow_table *t; + struct mlx5_flow_group **g; +}; + struct mlx5e_macsec_tables { - struct mlx5e_flow_table ft_crypto; + struct mlx5_macsec_flow_table ft_crypto; struct mlx5_flow_handle *crypto_miss_rule; struct mlx5_flow_table *ft_check; @@ -103,6 +108,26 @@ struct mlx5e_macsec_fs { struct mlx5e_macsec_rx *rx_fs; }; +static void macsec_fs_destroy_groups(struct mlx5_macsec_flow_table *ft) +{ + int i; + + for (i = ft->num_groups - 1; i >= 0; i--) { + if (!IS_ERR_OR_NULL(ft->g[i])) + mlx5_destroy_flow_group(ft->g[i]); + ft->g[i] = NULL; + } + ft->num_groups = 0; +} + +static void macsec_fs_destroy_flow_table(struct mlx5_macsec_flow_table *ft) +{ + macsec_fs_destroy_groups(ft); + kfree(ft->g); + mlx5_destroy_flow_table(ft->t); + ft->t = NULL; +} + static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs) { struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; @@ -142,10 +167,10 @@ static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs) tx_tables->crypto_miss_rule = NULL; } - mlx5e_destroy_flow_table(&tx_tables->ft_crypto); + macsec_fs_destroy_flow_table(&tx_tables->ft_crypto); } -static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft) +static int macsec_fs_tx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); int mclen = MLX5_ST_SZ_BYTES(fte_match_param); @@ -244,7 +269,7 @@ static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs) struct mlx5_flow_destination dest = {}; struct mlx5e_macsec_tables *tx_tables; struct mlx5_flow_act flow_act = {}; - struct mlx5e_flow_table *ft_crypto; + struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_table *flow_table; struct mlx5_flow_group *flow_group; struct mlx5_flow_namespace *ns; @@ -733,10 +758,10 @@ static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs) rx_tables->crypto_miss_rule = NULL; } - mlx5e_destroy_flow_table(&rx_tables->ft_crypto); + macsec_fs_destroy_flow_table(&rx_tables->ft_crypto); } -static int macsec_fs_rx_create_crypto_table_groups(struct mlx5e_flow_table *ft) +static int macsec_fs_rx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); int mclen = MLX5_ST_SZ_BYTES(fte_match_param); @@ -894,10 +919,10 @@ static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs) int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; struct net_device *netdev = macsec_fs->netdev; + struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_flow_destination dest = {}; struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_flow_table *ft_crypto; struct mlx5_flow_table *flow_table; struct mlx5_flow_group *flow_group; struct mlx5_flow_act flow_act = {}; @@ -1122,11 +1147,11 @@ macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs, struct net_device *netdev = macsec_fs->netdev; union mlx5e_macsec_rule *macsec_rule = NULL; struct mlx5_modify_hdr *modify_hdr = NULL; + struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_destination dest = {}; struct mlx5e_macsec_tables *rx_tables; struct mlx5e_macsec_rx_rule *rx_rule; struct mlx5_flow_act flow_act = {}; - struct mlx5e_flow_table *ft_crypto; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; int err = 0; -- cgit From 8603efbd18b091273876b72e6d9973df8b0a428a Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Tue, 29 Nov 2022 16:22:33 +0200 Subject: net/mlx5e: Rename MACsec flow steering functions/parameters to suit core naming style Rename MACsec flow steering(macsec_fs) functions and parameters from ethernet(core/en_accel) naming convention to core naming convention. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 22 +-- .../ethernet/mellanox/mlx5/core/en_accel/macsec.h | 2 +- .../mellanox/mlx5/core/en_accel/macsec_stats.c | 16 +- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 168 ++++++++++----------- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.h | 30 ++-- 5 files changed, 119 insertions(+), 119 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index b26044efdec6..831d83094abd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -67,7 +67,7 @@ struct mlx5e_macsec_sa { struct rhash_head hash; u32 fs_id; - union mlx5e_macsec_rule *macsec_rule; + union mlx5_macsec_rule *macsec_rule; struct rcu_head rcu_head; struct mlx5e_macsec_epn_state epn_state; }; @@ -124,7 +124,7 @@ struct mlx5e_macsec_device { struct mlx5e_macsec { struct list_head macsec_device_list_head; int num_of_devices; - struct mlx5e_macsec_fs *macsec_fs; + struct mlx5_macsec_fs *macsec_fs; struct mutex lock; /* Protects mlx5e_macsec internal contexts */ /* Tx sci -> fs id mapping handling */ @@ -136,7 +136,7 @@ struct mlx5e_macsec { struct mlx5_core_dev *mdev; /* Stats manage */ - struct mlx5e_macsec_stats stats; + struct mlx5_macsec_stats stats; /* ASO */ struct mlx5e_macsec_aso aso; @@ -343,7 +343,7 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec, if (!sa->macsec_rule) return; - mlx5e_macsec_fs_del_rule(macsec->macsec_fs, sa->macsec_rule, action); + mlx5_macsec_fs_del_rule(macsec->macsec_fs, sa->macsec_rule, action); mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id); sa->macsec_rule = NULL; } @@ -358,7 +358,7 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, struct mlx5_macsec_rule_attrs rule_attrs; struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_macsec_obj_attrs obj_attrs; - union mlx5e_macsec_rule *macsec_rule; + union mlx5_macsec_rule *macsec_rule; int err; obj_attrs.next_pn = sa->next_pn; @@ -386,7 +386,7 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : MLX5_ACCEL_MACSEC_ACTION_DECRYPT; - macsec_rule = mlx5e_macsec_fs_add_rule(macsec->macsec_fs, ctx, &rule_attrs, &sa->fs_id); + macsec_rule = mlx5_macsec_fs_add_rule(macsec->macsec_fs, ctx, &rule_attrs, &sa->fs_id); if (!macsec_rule) { err = -ENOMEM; goto destroy_macsec_object; @@ -1679,10 +1679,10 @@ bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats) { - mlx5e_macsec_fs_get_stats_fill(macsec->macsec_fs, macsec_stats); + mlx5_macsec_fs_get_stats_fill(macsec->macsec_fs, macsec_stats); } -struct mlx5e_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec) +struct mlx5_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec) { if (!macsec) return NULL; @@ -1781,7 +1781,7 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv) { struct mlx5_core_dev *mdev = priv->mdev; struct mlx5e_macsec *macsec = NULL; - struct mlx5e_macsec_fs *macsec_fs; + struct mlx5_macsec_fs *macsec_fs; int err; if (!mlx5e_is_macsec_device(priv->mdev)) { @@ -1821,7 +1821,7 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv) macsec->mdev = mdev; - macsec_fs = mlx5e_macsec_fs_init(mdev, priv->netdev); + macsec_fs = mlx5_macsec_fs_init(mdev, priv->netdev); if (!macsec_fs) { err = -ENOMEM; goto err_out; @@ -1857,7 +1857,7 @@ void mlx5e_macsec_cleanup(struct mlx5e_priv *priv) return; mlx5_notifier_unregister(mdev, &macsec->nb); - mlx5e_macsec_fs_cleanup(macsec->macsec_fs); + mlx5_macsec_fs_cleanup(macsec->macsec_fs); destroy_workqueue(macsec->wq); mlx5e_macsec_aso_cleanup(&macsec->aso, mdev); rhashtable_destroy(&macsec->sci_hash); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h index 1f9c4a2723b2..47dc1d4448d9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h @@ -38,7 +38,7 @@ void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buf struct mlx5_cqe64 *cqe); bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev); void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats); -struct mlx5e_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec); +struct mlx5_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec); #else diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c index e50a2e3f3d18..8326a593b3fb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c @@ -8,14 +8,14 @@ #include "en_accel/macsec.h" static const struct counter_desc mlx5e_macsec_hw_stats_desc[] = { - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_pkts) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_bytes) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_pkts_drop) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_rx_bytes_drop) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_pkts) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_bytes) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_pkts_drop) }, - { MLX5E_DECLARE_STAT(struct mlx5e_macsec_stats, macsec_tx_bytes_drop) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_pkts) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_pkts_drop) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_rx_bytes_drop) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_pkts) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_pkts_drop) }, + { MLX5E_DECLARE_STAT(struct mlx5_macsec_stats, macsec_tx_bytes_drop) }, }; #define NUM_MACSEC_HW_COUNTERS ARRAY_SIZE(mlx5e_macsec_hw_stats_desc) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 40883d2b78c7..c585d61324bf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -50,7 +50,7 @@ struct mlx5_sectag_header { u8 sci[MACSEC_SCI_LEN]; /* optional */ } __packed; -struct mlx5e_macsec_tx_rule { +struct mlx5_macsec_tx_rule { struct mlx5_flow_handle *rule; struct mlx5_pkt_reformat *pkt_reformat; u32 fs_id; @@ -62,7 +62,7 @@ struct mlx5_macsec_flow_table { struct mlx5_flow_group **g; }; -struct mlx5e_macsec_tables { +struct mlx5_macsec_tables { struct mlx5_macsec_flow_table ft_crypto; struct mlx5_flow_handle *crypto_miss_rule; @@ -75,37 +75,37 @@ struct mlx5e_macsec_tables { u32 refcnt; }; -struct mlx5e_macsec_tx { +struct mlx5_macsec_tx { struct mlx5_flow_handle *crypto_mke_rule; struct mlx5_flow_handle *check_rule; struct ida tx_halloc; - struct mlx5e_macsec_tables tables; + struct mlx5_macsec_tables tables; }; -struct mlx5e_macsec_rx_rule { +struct mlx5_macsec_rx_rule { struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA]; struct mlx5_modify_hdr *meta_modhdr; }; -struct mlx5e_macsec_rx { +struct mlx5_macsec_rx { struct mlx5_flow_handle *check_rule[2]; struct mlx5_pkt_reformat *check_rule_pkt_reformat[2]; - struct mlx5e_macsec_tables tables; + struct mlx5_macsec_tables tables; }; -union mlx5e_macsec_rule { - struct mlx5e_macsec_tx_rule tx_rule; - struct mlx5e_macsec_rx_rule rx_rule; +union mlx5_macsec_rule { + struct mlx5_macsec_tx_rule tx_rule; + struct mlx5_macsec_rx_rule rx_rule; }; -struct mlx5e_macsec_fs { +struct mlx5_macsec_fs { struct mlx5_core_dev *mdev; struct net_device *netdev; - struct mlx5e_macsec_tx *tx_fs; - struct mlx5e_macsec_rx *rx_fs; + struct mlx5_macsec_tx *tx_fs; + struct mlx5_macsec_rx *rx_fs; }; static void macsec_fs_destroy_groups(struct mlx5_macsec_flow_table *ft) @@ -128,10 +128,10 @@ static void macsec_fs_destroy_flow_table(struct mlx5_macsec_flow_table *ft) ft->t = NULL; } -static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_tx_destroy(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct mlx5e_macsec_tables *tx_tables; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tables *tx_tables; tx_tables = &tx_fs->tables; @@ -260,14 +260,14 @@ static struct mlx5_flow_table return fdb; } -static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; struct net_device *netdev = macsec_fs->netdev; struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *tx_tables; + struct mlx5_macsec_tables *tx_tables; struct mlx5_flow_act flow_act = {}; struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_table *flow_table; @@ -413,10 +413,10 @@ out_spec: return err; } -static int macsec_fs_tx_ft_get(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_tx_ft_get(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct mlx5e_macsec_tables *tx_tables; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tables *tx_tables; int err = 0; tx_tables = &tx_fs->tables; @@ -432,9 +432,9 @@ out: return err; } -static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_tx_ft_put(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; + struct mlx5_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; if (--tx_tables->refcnt) return; @@ -442,13 +442,13 @@ static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs) macsec_fs_tx_destroy(macsec_fs); } -static int macsec_fs_tx_setup_fte(struct mlx5e_macsec_fs *macsec_fs, +static int macsec_fs_tx_setup_fte(struct mlx5_macsec_fs *macsec_fs, struct mlx5_flow_spec *spec, struct mlx5_flow_act *flow_act, u32 macsec_obj_id, u32 *fs_id) { - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; int err = 0; u32 id; @@ -511,8 +511,8 @@ static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx, memcpy(reformatbf, §ag, *reformat_size); } -static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5e_macsec_tx_rule *tx_rule) +static void macsec_fs_tx_del_rule(struct mlx5_macsec_fs *macsec_fs, + struct mlx5_macsec_tx_rule *tx_rule) { if (tx_rule->rule) { mlx5_del_flow_rules(tx_rule->rule); @@ -536,20 +536,20 @@ static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs, #define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1 -static union mlx5e_macsec_rule * -macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs, +static union mlx5_macsec_rule * +macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, const struct macsec_context *macsec_ctx, struct mlx5_macsec_rule_attrs *attrs, u32 *sa_fs_id) { char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; struct mlx5_pkt_reformat_params reformat_params = {}; - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; struct net_device *netdev = macsec_fs->netdev; - union mlx5e_macsec_rule *macsec_rule = NULL; + union mlx5_macsec_rule *macsec_rule = NULL; struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *tx_tables; - struct mlx5e_macsec_tx_rule *tx_rule; + struct mlx5_macsec_tables *tx_tables; + struct mlx5_macsec_tx_rule *tx_rule; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; @@ -630,11 +630,11 @@ out_spec: return macsec_rule; } -static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_tx_cleanup(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *tx_tables; + struct mlx5_macsec_tables *tx_tables; if (!tx_fs) return; @@ -663,12 +663,12 @@ static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs) macsec_fs->tx_fs = NULL; } -static int macsec_fs_tx_init(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs) { struct net_device *netdev = macsec_fs->netdev; struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *tx_tables; - struct mlx5e_macsec_tx *tx_fs; + struct mlx5_macsec_tables *tx_tables; + struct mlx5_macsec_tx *tx_fs; struct mlx5_fc *flow_counter; int err; @@ -715,10 +715,10 @@ err_encrypt_counter: return err; } -static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_rx_destroy(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct mlx5e_macsec_tables *rx_tables; + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_macsec_tables *rx_tables; int i; /* Rx check table */ @@ -843,7 +843,7 @@ err: return err; } -static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_fs, +static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs, struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, struct mlx5_flow_spec *spec, @@ -852,9 +852,9 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_f int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1; u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI]; struct mlx5_pkt_reformat_params reformat_params = {}; - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; struct net_device *netdev = macsec_fs->netdev; - struct mlx5e_macsec_tables *rx_tables; + struct mlx5_macsec_tables *rx_tables; struct mlx5_flow_handle *rule; int err = 0; @@ -914,15 +914,15 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_f return 0; } -static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; struct net_device *netdev = macsec_fs->netdev; struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *rx_tables; + struct mlx5_macsec_tables *rx_tables; struct mlx5_flow_table *flow_table; struct mlx5_flow_group *flow_group; struct mlx5_flow_act flow_act = {}; @@ -1042,9 +1042,9 @@ free_spec: return err; } -static int macsec_fs_rx_ft_get(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_rx_ft_get(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; int err = 0; if (rx_tables->refcnt) @@ -1059,9 +1059,9 @@ out: return err; } -static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_rx_ft_put(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; if (--rx_tables->refcnt) return; @@ -1069,8 +1069,8 @@ static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs) macsec_fs_rx_destroy(macsec_fs); } -static void macsec_fs_rx_del_rule(struct mlx5e_macsec_fs *macsec_fs, - struct mlx5e_macsec_rx_rule *rx_rule) +static void macsec_fs_rx_del_rule(struct mlx5_macsec_fs *macsec_fs, + struct mlx5_macsec_rx_rule *rx_rule) { int i; @@ -1137,20 +1137,20 @@ static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec, crypto_params->obj_id = attrs->macsec_obj_id; } -static union mlx5e_macsec_rule * -macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs, +static union mlx5_macsec_rule * +macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, struct mlx5_macsec_rule_attrs *attrs, u32 fs_id) { u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; struct net_device *netdev = macsec_fs->netdev; - union mlx5e_macsec_rule *macsec_rule = NULL; + union mlx5_macsec_rule *macsec_rule = NULL; struct mlx5_modify_hdr *modify_hdr = NULL; struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_destination dest = {}; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_macsec_rx_rule *rx_rule; + struct mlx5_macsec_tables *rx_tables; + struct mlx5_macsec_rx_rule *rx_rule; struct mlx5_flow_act flow_act = {}; struct mlx5_flow_handle *rule; struct mlx5_flow_spec *spec; @@ -1249,12 +1249,12 @@ out_spec: return macsec_rule; } -static int macsec_fs_rx_init(struct mlx5e_macsec_fs *macsec_fs) +static int macsec_fs_rx_init(struct mlx5_macsec_fs *macsec_fs) { struct net_device *netdev = macsec_fs->netdev; struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *rx_tables; - struct mlx5e_macsec_rx *rx_fs; + struct mlx5_macsec_tables *rx_tables; + struct mlx5_macsec_rx *rx_fs; struct mlx5_fc *flow_counter; int err; @@ -1299,11 +1299,11 @@ err_encrypt_counter: return err; } -static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs) +static void macsec_fs_rx_cleanup(struct mlx5_macsec_fs *macsec_fs) { - struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; struct mlx5_core_dev *mdev = macsec_fs->mdev; - struct mlx5e_macsec_tables *rx_tables; + struct mlx5_macsec_tables *rx_tables; if (!rx_fs) return; @@ -1331,11 +1331,11 @@ static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs) macsec_fs->rx_fs = NULL; } -void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats) +void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats) { - struct mlx5e_macsec_stats *stats = (struct mlx5e_macsec_stats *)macsec_stats; - struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; - struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; + struct mlx5_macsec_stats *stats = (struct mlx5_macsec_stats *)macsec_stats; + struct mlx5_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables; + struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables; struct mlx5_core_dev *mdev = macsec_fs->mdev; if (tx_tables->check_rule_counter) @@ -1355,38 +1355,38 @@ void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *mac &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop); } -union mlx5e_macsec_rule * -mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, - const struct macsec_context *macsec_ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id) +union mlx5_macsec_rule * +mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, + const struct macsec_context *macsec_ctx, + struct mlx5_macsec_rule_attrs *attrs, + u32 *sa_fs_id) { return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) : macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id); } -void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, - union mlx5e_macsec_rule *macsec_rule, - int action) +void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, + union mlx5_macsec_rule *macsec_rule, + int action) { (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) : macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule); } -void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs) +void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs) { macsec_fs_rx_cleanup(macsec_fs); macsec_fs_tx_cleanup(macsec_fs); kfree(macsec_fs); } -struct mlx5e_macsec_fs * -mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, - struct net_device *netdev) +struct mlx5_macsec_fs * +mlx5_macsec_fs_init(struct mlx5_core_dev *mdev, + struct net_device *netdev) { - struct mlx5e_macsec_fs *macsec_fs; + struct mlx5_macsec_fs *macsec_fs; int err; macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h index b282c0850e16..6a749e036e68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h @@ -14,8 +14,8 @@ #define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16 -struct mlx5e_macsec_fs; -union mlx5e_macsec_rule; +struct mlx5_macsec_fs; +union mlx5_macsec_rule; struct mlx5_macsec_rule_attrs { sci_t sci; @@ -24,7 +24,7 @@ struct mlx5_macsec_rule_attrs { int action; }; -struct mlx5e_macsec_stats { +struct mlx5_macsec_stats { u64 macsec_rx_pkts; u64 macsec_rx_bytes; u64 macsec_rx_pkts_drop; @@ -40,22 +40,22 @@ enum mlx5_macsec_action { MLX5_ACCEL_MACSEC_ACTION_DECRYPT, }; -void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs); +void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs); -struct mlx5e_macsec_fs * -mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev); +struct mlx5_macsec_fs * +mlx5_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev); -union mlx5e_macsec_rule * -mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs, - const struct macsec_context *ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id); +union mlx5_macsec_rule * +mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, + const struct macsec_context *ctx, + struct mlx5_macsec_rule_attrs *attrs, + u32 *sa_fs_id); -void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs, - union mlx5e_macsec_rule *macsec_rule, - int action); +void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, + union mlx5_macsec_rule *macsec_rule, + int action); -void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats); +void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats); #endif -- cgit From 2e92f669b86d70a26a77b088c74e1cb6d26322e1 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Tue, 6 Dec 2022 14:33:49 +0200 Subject: net/mlx5e: Move MACsec flow steering and statistics database from ethernet to core Since now MACsec flow steering (macsec_fs) and MACsec statistics (stats) are maintained by the core driver, move their data as well to be saved inside core structures instead of staying part of ethernet MACsec database. In addition cleanup all MACsec stats functions from the ethernet MACsec code and move what's needed to be part of macsec_fs instead. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 25 ++++------------------ .../ethernet/mellanox/mlx5/core/en_accel/macsec.h | 2 -- .../mellanox/mlx5/core/en_accel/macsec_stats.c | 6 ++++-- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 11 ++++++++++ .../ethernet/mellanox/mlx5/core/lib/macsec_fs.h | 1 + 5 files changed, 20 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 831d83094abd..5e8ad355c67f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -124,7 +124,6 @@ struct mlx5e_macsec_device { struct mlx5e_macsec { struct list_head macsec_device_list_head; int num_of_devices; - struct mlx5_macsec_fs *macsec_fs; struct mutex lock; /* Protects mlx5e_macsec internal contexts */ /* Tx sci -> fs id mapping handling */ @@ -135,9 +134,6 @@ struct mlx5e_macsec { struct mlx5_core_dev *mdev; - /* Stats manage */ - struct mlx5_macsec_stats stats; - /* ASO */ struct mlx5e_macsec_aso aso; @@ -343,7 +339,7 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec, if (!sa->macsec_rule) return; - mlx5_macsec_fs_del_rule(macsec->macsec_fs, sa->macsec_rule, action); + mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action); mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id); sa->macsec_rule = NULL; } @@ -386,7 +382,7 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : MLX5_ACCEL_MACSEC_ACTION_DECRYPT; - macsec_rule = mlx5_macsec_fs_add_rule(macsec->macsec_fs, ctx, &rule_attrs, &sa->fs_id); + macsec_rule = mlx5_macsec_fs_add_rule(mdev->macsec_fs, ctx, &rule_attrs, &sa->fs_id); if (!macsec_rule) { err = -ENOMEM; goto destroy_macsec_object; @@ -1677,19 +1673,6 @@ bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) return true; } -void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats) -{ - mlx5_macsec_fs_get_stats_fill(macsec->macsec_fs, macsec_stats); -} - -struct mlx5_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec) -{ - if (!macsec) - return NULL; - - return &macsec->stats; -} - static const struct macsec_ops macsec_offload_ops = { .mdo_add_txsa = mlx5e_macsec_add_txsa, .mdo_upd_txsa = mlx5e_macsec_upd_txsa, @@ -1827,7 +1810,7 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv) goto err_out; } - macsec->macsec_fs = macsec_fs; + mdev->macsec_fs = macsec_fs; macsec->nb.notifier_call = macsec_obj_change_event; mlx5_notifier_register(mdev, &macsec->nb); @@ -1857,7 +1840,7 @@ void mlx5e_macsec_cleanup(struct mlx5e_priv *priv) return; mlx5_notifier_unregister(mdev, &macsec->nb); - mlx5_macsec_fs_cleanup(macsec->macsec_fs); + mlx5_macsec_fs_cleanup(mdev->macsec_fs); destroy_workqueue(macsec->wq); mlx5e_macsec_aso_cleanup(&macsec->aso, mdev); rhashtable_destroy(&macsec->sci_hash); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h index 47dc1d4448d9..2ecd769585f4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h @@ -37,8 +37,6 @@ static inline bool mlx5e_macsec_is_rx_flow(struct mlx5_cqe64 *cqe) void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, struct mlx5_cqe64 *cqe); bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev); -void mlx5e_macsec_get_stats_fill(struct mlx5e_macsec *macsec, void *macsec_stats); -struct mlx5_macsec_stats *mlx5e_macsec_get_stats(struct mlx5e_macsec *macsec); #else diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c index 8326a593b3fb..4559ee16a11a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_stats.c @@ -52,6 +52,7 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(macsec_hw) static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(macsec_hw) { + struct mlx5_macsec_fs *macsec_fs; int i; if (!priv->macsec) @@ -60,9 +61,10 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(macsec_hw) if (!mlx5e_is_macsec_device(priv->mdev)) return idx; - mlx5e_macsec_get_stats_fill(priv->macsec, mlx5e_macsec_get_stats(priv->macsec)); + macsec_fs = priv->mdev->macsec_fs; + mlx5_macsec_fs_get_stats_fill(macsec_fs, mlx5_macsec_fs_get_stats(macsec_fs)); for (i = 0; i < NUM_MACSEC_HW_COUNTERS; i++) - data[idx++] = MLX5E_READ_CTR64_CPU(mlx5e_macsec_get_stats(priv->macsec), + data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_macsec_fs_get_stats(macsec_fs), mlx5e_macsec_hw_stats_desc, i); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index c585d61324bf..11f9c5a8e43a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -106,6 +106,9 @@ struct mlx5_macsec_fs { struct net_device *netdev; struct mlx5_macsec_tx *tx_fs; struct mlx5_macsec_rx *rx_fs; + + /* Stats manage */ + struct mlx5_macsec_stats stats; }; static void macsec_fs_destroy_groups(struct mlx5_macsec_flow_table *ft) @@ -1355,6 +1358,14 @@ void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macse &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop); } +struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec_fs) +{ + if (!macsec_fs) + return NULL; + + return &macsec_fs->stats; +} + union mlx5_macsec_rule * mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, const struct macsec_context *macsec_ctx, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h index 6a749e036e68..c0c28d08eae5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h @@ -56,6 +56,7 @@ void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, int action); void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats); +struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec_fs); #endif -- cgit From 7e2304f5bf1c9f4e22d8dce473fd9a8961e6a7b4 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Thu, 5 Jan 2023 13:28:11 +0200 Subject: net/mlx5: Remove netdevice from MACsec steering Since MACsec steering was moved from ethernet private code to core, remove the netdevice from the MACsec steering, and use core device methods for error reporting instead. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 2 +- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 144 ++++++++++----------- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.h | 2 +- 3 files changed, 71 insertions(+), 77 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 5e8ad355c67f..fb599bacbe30 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1804,7 +1804,7 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv) macsec->mdev = mdev; - macsec_fs = mlx5_macsec_fs_init(mdev, priv->netdev); + macsec_fs = mlx5_macsec_fs_init(mdev); if (!macsec_fs) { err = -ENOMEM; goto err_out; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 11f9c5a8e43a..8ecc91f30da1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -2,7 +2,6 @@ /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #include -#include #include #include #include "fs_core.h" @@ -103,7 +102,6 @@ union mlx5_macsec_rule { struct mlx5_macsec_fs { struct mlx5_core_dev *mdev; - struct net_device *netdev; struct mlx5_macsec_tx *tx_fs; struct mlx5_macsec_rx *rx_fs; @@ -267,7 +265,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_flow_destination dest = {}; struct mlx5_macsec_tables *tx_tables; @@ -281,7 +279,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) u32 *flow_group_in; int err; - ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); if (!ns) return -ENOMEM; @@ -306,7 +304,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) flow_table = mlx5_create_flow_table(ns, &ft_attr); if (IS_ERR(flow_table)) { err = PTR_ERR(flow_table); - netdev_err(netdev, "Failed to create MACsec Tx crypto table err(%d)\n", err); + mlx5_core_err(mdev, "Failed to create MACsec Tx crypto table err(%d)\n", err); goto out_flow_group; } ft_crypto->t = flow_table; @@ -314,9 +312,9 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) /* Tx crypto table groups */ err = macsec_fs_tx_create_crypto_table_groups(ft_crypto); if (err) { - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); goto err; } @@ -330,7 +328,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec TX MKE rule, err=%d\n", err); + mlx5_core_err(mdev, "Failed to add MACsec TX MKE rule, err=%d\n", err); goto err; } tx_fs->crypto_mke_rule = rule; @@ -341,7 +339,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec Tx table default miss rule %d\n", err); + mlx5_core_err(mdev, "Failed to add MACsec Tx table default miss rule %d\n", err); goto err; } tx_tables->crypto_miss_rule = rule; @@ -351,7 +349,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) TX_CHECK_TABLE_NUM_FTE); if (IS_ERR(flow_table)) { err = PTR_ERR(flow_table); - netdev_err(netdev, "fail to create MACsec TX check table, err(%d)\n", err); + mlx5_core_err(mdev, "Fail to create MACsec TX check table, err(%d)\n", err); goto err; } tx_tables->ft_check = flow_table; @@ -363,9 +361,9 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in); if (IS_ERR(flow_group)) { err = PTR_ERR(flow_group); - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); goto err; } tx_tables->ft_check_group = flow_group; @@ -379,7 +377,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(tx_tables->ft_check, NULL, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err); + mlx5_core_err(mdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err); goto err; } tx_tables->check_miss_rule = rule; @@ -400,7 +398,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec check rule, err=%d\n", err); + mlx5_core_err(mdev, "Failed to add MACsec check rule, err=%d\n", err); goto err; } tx_fs->check_rule = rule; @@ -548,7 +546,7 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; struct mlx5_pkt_reformat_params reformat_params = {}; struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; - struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; union mlx5_macsec_rule *macsec_rule = NULL; struct mlx5_flow_destination dest = {}; struct mlx5_macsec_tables *tx_tables; @@ -588,21 +586,21 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, if (is_vlan_dev(macsec_ctx->netdev)) reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES; - flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, + flow_act.pkt_reformat = mlx5_packet_reformat_alloc(mdev, &reformat_params, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC); if (IS_ERR(flow_act.pkt_reformat)) { err = PTR_ERR(flow_act.pkt_reformat); - netdev_err(netdev, "Failed to allocate MACsec Tx reformat context err=%d\n", err); + mlx5_core_err(mdev, "Failed to allocate MACsec Tx reformat context err=%d\n", err); goto err; } tx_rule->pkt_reformat = flow_act.pkt_reformat; err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id); if (err) { - netdev_err(netdev, - "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n", - err); + mlx5_core_err(mdev, + "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n", + err); goto err; } @@ -617,7 +615,7 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec TX crypto rule, err=%d\n", err); + mlx5_core_err(mdev, "Failed to add MACsec TX crypto rule, err=%d\n", err); goto err; } tx_rule->rule = rule; @@ -644,9 +642,9 @@ static void macsec_fs_tx_cleanup(struct mlx5_macsec_fs *macsec_fs) tx_tables = &tx_fs->tables; if (tx_tables->refcnt) { - netdev_err(macsec_fs->netdev, - "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n", - tx_tables->refcnt); + mlx5_core_err(mdev, + "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n", + tx_tables->refcnt); return; } @@ -668,7 +666,6 @@ static void macsec_fs_tx_cleanup(struct mlx5_macsec_fs *macsec_fs) static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs) { - struct net_device *netdev = macsec_fs->netdev; struct mlx5_core_dev *mdev = macsec_fs->mdev; struct mlx5_macsec_tables *tx_tables; struct mlx5_macsec_tx *tx_fs; @@ -684,9 +681,9 @@ static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs) flow_counter = mlx5_fc_create(mdev, false); if (IS_ERR(flow_counter)) { err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Tx encrypt flow counter, err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create MACsec Tx encrypt flow counter, err(%d)\n", + err); goto err_encrypt_counter; } tx_tables->check_rule_counter = flow_counter; @@ -694,9 +691,9 @@ static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs) flow_counter = mlx5_fc_create(mdev, false); if (IS_ERR(flow_counter)) { err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Tx drop flow counter, err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create MACsec Tx drop flow counter, err(%d)\n", + err); goto err_drop_counter; } tx_tables->check_miss_rule_counter = flow_counter; @@ -856,7 +853,7 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI]; struct mlx5_pkt_reformat_params reformat_params = {}; struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; struct mlx5_macsec_tables *rx_tables; struct mlx5_flow_handle *rule; int err = 0; @@ -871,12 +868,12 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC; reformat_params.size = reformat_param_size; reformat_params.data = mlx5_reformat_buf; - flow_act->pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev, + flow_act->pkt_reformat = mlx5_packet_reformat_alloc(mdev, &reformat_params, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); if (IS_ERR(flow_act->pkt_reformat)) { err = PTR_ERR(flow_act->pkt_reformat); - netdev_err(netdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err); + mlx5_core_err(mdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err); return err; } rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat; @@ -908,7 +905,7 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to add MACsec Rx check rule, err=%d\n", err); + mlx5_core_err(mdev, "Failed to add MACsec Rx check rule, err=%d\n", err); return err; } @@ -921,7 +918,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; struct mlx5_macsec_flow_table *ft_crypto; struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_flow_destination dest = {}; @@ -935,7 +932,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) u32 *flow_group_in; int err; - ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); if (!ns) return -ENOMEM; @@ -959,7 +956,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) flow_table = mlx5_create_flow_table(ns, &ft_attr); if (IS_ERR(flow_table)) { err = PTR_ERR(flow_table); - netdev_err(netdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); + mlx5_core_err(mdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); goto out_flow_group; } ft_crypto->t = flow_table; @@ -967,9 +964,9 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) /* Rx crypto table groups */ err = macsec_fs_rx_create_crypto_table_groups(ft_crypto); if (err) { - netdev_err(netdev, - "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create default flow group for MACsec Tx crypto table err(%d)\n", + err); goto err; } @@ -977,9 +974,9 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add MACsec Rx crypto table default miss rule %d\n", - err); + mlx5_core_err(mdev, + "Failed to add MACsec Rx crypto table default miss rule %d\n", + err); goto err; } rx_tables->crypto_miss_rule = rule; @@ -991,7 +988,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) RX_CHECK_TABLE_NUM_FTE); if (IS_ERR(flow_table)) { err = PTR_ERR(flow_table); - netdev_err(netdev, "fail to create MACsec RX check table, err(%d)\n", err); + mlx5_core_err(mdev, "Fail to create MACsec RX check table, err(%d)\n", err); goto err; } rx_tables->ft_check = flow_table; @@ -1002,9 +999,9 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in); if (IS_ERR(flow_group)) { err = PTR_ERR(flow_group); - netdev_err(netdev, - "Failed to create default flow group for MACsec Rx check table err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create default flow group for MACsec Rx check table err(%d)\n", + err); goto err; } rx_tables->ft_check_group = flow_group; @@ -1018,7 +1015,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) rule = mlx5_add_flow_rules(rx_tables->ft_check, NULL, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err); + mlx5_core_err(mdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err); goto err; } rx_tables->check_miss_rule = rule; @@ -1147,7 +1144,7 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, { u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; - struct net_device *netdev = macsec_fs->netdev; + struct mlx5_core_dev *mdev = macsec_fs->mdev; union mlx5_macsec_rule *macsec_rule = NULL; struct mlx5_modify_hdr *modify_hdr = NULL; struct mlx5_macsec_flow_table *ft_crypto; @@ -1185,11 +1182,11 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, MLX5_SET(set_action_in, action, offset, 0); MLX5_SET(set_action_in, action, length, 32); - modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, 1, action); if (IS_ERR(modify_hdr)) { err = PTR_ERR(modify_hdr); - netdev_err(netdev, "fail to alloc MACsec set modify_header_id err=%d\n", err); + mlx5_core_err(mdev, "Fail to alloc MACsec set modify_header_id err=%d\n", err); modify_hdr = NULL; goto err; } @@ -1208,9 +1205,9 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n", - err); + mlx5_core_err(mdev, + "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n", + err); goto err; } rx_rule->rule[0] = rule; @@ -1233,9 +1230,9 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); - netdev_err(netdev, - "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n", - err); + mlx5_core_err(mdev, + "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n", + err); goto err; } rx_rule->rule[1] = rule; @@ -1254,7 +1251,6 @@ out_spec: static int macsec_fs_rx_init(struct mlx5_macsec_fs *macsec_fs) { - struct net_device *netdev = macsec_fs->netdev; struct mlx5_core_dev *mdev = macsec_fs->mdev; struct mlx5_macsec_tables *rx_tables; struct mlx5_macsec_rx *rx_fs; @@ -1268,9 +1264,9 @@ static int macsec_fs_rx_init(struct mlx5_macsec_fs *macsec_fs) flow_counter = mlx5_fc_create(mdev, false); if (IS_ERR(flow_counter)) { err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Rx encrypt flow counter, err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create MACsec Rx encrypt flow counter, err(%d)\n", + err); goto err_encrypt_counter; } @@ -1280,9 +1276,9 @@ static int macsec_fs_rx_init(struct mlx5_macsec_fs *macsec_fs) flow_counter = mlx5_fc_create(mdev, false); if (IS_ERR(flow_counter)) { err = PTR_ERR(flow_counter); - netdev_err(netdev, - "Failed to create MACsec Rx drop flow counter, err(%d)\n", - err); + mlx5_core_err(mdev, + "Failed to create MACsec Rx drop flow counter, err(%d)\n", + err); goto err_drop_counter; } rx_tables->check_miss_rule_counter = flow_counter; @@ -1314,9 +1310,9 @@ static void macsec_fs_rx_cleanup(struct mlx5_macsec_fs *macsec_fs) rx_tables = &rx_fs->tables; if (rx_tables->refcnt) { - netdev_err(macsec_fs->netdev, - "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n", - rx_tables->refcnt); + mlx5_core_err(mdev, + "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n", + rx_tables->refcnt); return; } @@ -1394,8 +1390,7 @@ void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs) } struct mlx5_macsec_fs * -mlx5_macsec_fs_init(struct mlx5_core_dev *mdev, - struct net_device *netdev) +mlx5_macsec_fs_init(struct mlx5_core_dev *mdev) { struct mlx5_macsec_fs *macsec_fs; int err; @@ -1405,17 +1400,16 @@ mlx5_macsec_fs_init(struct mlx5_core_dev *mdev, return NULL; macsec_fs->mdev = mdev; - macsec_fs->netdev = netdev; err = macsec_fs_tx_init(macsec_fs); if (err) { - netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); + mlx5_core_err(mdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); goto err; } err = macsec_fs_rx_init(macsec_fs); if (err) { - netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); + mlx5_core_err(mdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); goto tx_cleanup; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h index c0c28d08eae5..f007c33369c2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h @@ -43,7 +43,7 @@ enum mlx5_macsec_action { void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs); struct mlx5_macsec_fs * -mlx5_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev); +mlx5_macsec_fs_init(struct mlx5_core_dev *mdev); union mlx5_macsec_rule * mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, -- cgit From d4ece08f4b1d29471cc4c0eb0c87427600a77acd Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Sun, 8 Jan 2023 15:25:44 +0200 Subject: net/mlx5: Maintain fs_id xarray per MACsec device inside macsec steering Remove fs_id from the MACsec SA, since it has no real usage there and instead maintain with the MACsec steering data inside the core. Downstream patches requires this change to facilitate IB driver accesses to the fs_ids to avoid RoCE MACsec dependency on EN driver. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 115 +++------- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 247 +++++++++++++++++++-- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.h | 3 +- 3 files changed, 271 insertions(+), 94 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index fb599bacbe30..b4f3f4f10af3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -65,8 +65,6 @@ struct mlx5e_macsec_sa { ssci_t ssci; salt_t salt; - struct rhash_head hash; - u32 fs_id; union mlx5_macsec_rule *macsec_rule; struct rcu_head rcu_head; struct mlx5e_macsec_epn_state epn_state; @@ -105,14 +103,6 @@ struct mlx5e_macsec_aso { u32 pdn; }; -static const struct rhashtable_params rhash_sci = { - .key_len = sizeof_field(struct mlx5e_macsec_sa, sci), - .key_offset = offsetof(struct mlx5e_macsec_sa, sci), - .head_offset = offsetof(struct mlx5e_macsec_sa, hash), - .automatic_shrinking = true, - .min_size = 1, -}; - struct mlx5e_macsec_device { const struct net_device *netdev; struct mlx5e_macsec_sa *tx_sa[MACSEC_NUM_AN]; @@ -126,9 +116,6 @@ struct mlx5e_macsec { int num_of_devices; struct mutex lock; /* Protects mlx5e_macsec internal contexts */ - /* Tx sci -> fs id mapping handling */ - struct rhashtable sci_hash; /* sci -> mlx5e_macsec_sa */ - /* Rx fs_id -> rx_sc mapping */ struct xarray sc_xarray; @@ -325,29 +312,23 @@ static void mlx5e_macsec_destroy_object(struct mlx5_core_dev *mdev, u32 macsec_o static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec, struct mlx5e_macsec_sa *sa, - bool is_tx) + bool is_tx, struct net_device *netdev, u32 fs_id) { int action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : MLX5_ACCEL_MACSEC_ACTION_DECRYPT; - if ((is_tx) && sa->fs_id) { - /* Make sure ongoing datapath readers sees a valid SA */ - rhashtable_remove_fast(&macsec->sci_hash, &sa->hash, rhash_sci); - sa->fs_id = 0; - } - if (!sa->macsec_rule) return; - mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action); + mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action, netdev, + fs_id); mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id); sa->macsec_rule = NULL; } static int mlx5e_macsec_init_sa(struct macsec_context *ctx, struct mlx5e_macsec_sa *sa, - bool encrypt, - bool is_tx) + bool encrypt, bool is_tx, u32 *fs_id) { struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); struct mlx5e_macsec *macsec = priv->macsec; @@ -382,7 +363,7 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : MLX5_ACCEL_MACSEC_ACTION_DECRYPT; - macsec_rule = mlx5_macsec_fs_add_rule(mdev->macsec_fs, ctx, &rule_attrs, &sa->fs_id); + macsec_rule = mlx5_macsec_fs_add_rule(mdev->macsec_fs, ctx, &rule_attrs, fs_id); if (!macsec_rule) { err = -ENOMEM; goto destroy_macsec_object; @@ -390,16 +371,8 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx, sa->macsec_rule = macsec_rule; - if (is_tx) { - err = rhashtable_insert_fast(&macsec->sci_hash, &sa->hash, rhash_sci); - if (err) - goto destroy_macsec_object_and_rule; - } - return 0; -destroy_macsec_object_and_rule: - mlx5e_macsec_cleanup_sa(macsec, sa, is_tx); destroy_macsec_object: mlx5e_macsec_destroy_object(mdev, sa->macsec_obj_id); @@ -421,7 +394,7 @@ mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head *list, sci_t sci) static int macsec_rx_sa_active_update(struct macsec_context *ctx, struct mlx5e_macsec_sa *rx_sa, - bool active) + bool active, u32 *fs_id) { struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); struct mlx5e_macsec *macsec = priv->macsec; @@ -432,11 +405,11 @@ static int macsec_rx_sa_active_update(struct macsec_context *ctx, rx_sa->active = active; if (!active) { - mlx5e_macsec_cleanup_sa(macsec, rx_sa, false); + mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, *fs_id); return 0; } - err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false); + err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, fs_id); if (err) rx_sa->active = false; @@ -558,7 +531,7 @@ static int mlx5e_macsec_add_txsa(struct macsec_context *ctx) !tx_sa->active) goto out; - err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true); + err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL); if (err) goto destroy_encryption_key; @@ -622,7 +595,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx) goto out; if (ctx_tx_sa->active) { - err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true); + err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL); if (err) goto out; } else { @@ -631,7 +604,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx) goto out; } - mlx5e_macsec_cleanup_sa(macsec, tx_sa, true); + mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); } out: mutex_unlock(&macsec->lock); @@ -664,7 +637,7 @@ static int mlx5e_macsec_del_txsa(struct macsec_context *ctx) goto out; } - mlx5e_macsec_cleanup_sa(macsec, tx_sa, true); + mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id); kfree_rcu_mightsleep(tx_sa); macsec_device->tx_sa[assoc_num] = NULL; @@ -675,20 +648,6 @@ out: return err; } -static u32 mlx5e_macsec_get_sa_from_hashtable(struct rhashtable *sci_hash, sci_t *sci) -{ - struct mlx5e_macsec_sa *macsec_sa; - u32 fs_id = 0; - - rcu_read_lock(); - macsec_sa = rhashtable_lookup(sci_hash, sci, rhash_sci); - if (macsec_sa) - fs_id = macsec_sa->fs_id; - rcu_read_unlock(); - - return fs_id; -} - static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx) { struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element; @@ -808,7 +767,8 @@ static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx) if (!rx_sa) continue; - err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active); + err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active, + &rx_sc->sc_xarray_element->fs_id); if (err) goto out; } @@ -819,7 +779,8 @@ out: return err; } -static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc) +static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc, + struct net_device *netdev) { struct mlx5e_macsec_sa *rx_sa; int i; @@ -829,7 +790,8 @@ static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec if (!rx_sa) continue; - mlx5e_macsec_cleanup_sa(macsec, rx_sa, false); + mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, netdev, + rx_sc->sc_xarray_element->fs_id); mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id); kfree(rx_sa); @@ -877,7 +839,7 @@ static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx) goto out; } - macsec_del_rxsc_ctx(macsec, rx_sc); + macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev); out: mutex_unlock(&macsec->lock); @@ -936,7 +898,6 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx) rx_sa->next_pn = ctx_rx_sa->next_pn; rx_sa->sci = sci; rx_sa->assoc_num = assoc_num; - rx_sa->fs_id = rx_sc->sc_xarray_element->fs_id; if (ctx->secy->xpn) update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves, @@ -953,7 +914,7 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx) goto out; //TODO - add support for both authentication and encryption flows - err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false); + err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, &rx_sc->sc_xarray_element->fs_id); if (err) goto destroy_encryption_key; @@ -1020,7 +981,8 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx) goto out; } - err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active); + err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active, + &rx_sc->sc_xarray_element->fs_id); out: mutex_unlock(&macsec->lock); @@ -1068,7 +1030,8 @@ static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx) goto out; } - mlx5e_macsec_cleanup_sa(macsec, rx_sa, false); + mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, + rx_sc->sc_xarray_element->fs_id); mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id); kfree(rx_sa); rx_sc->rx_sa[assoc_num] = NULL; @@ -1149,7 +1112,8 @@ static int macsec_upd_secy_hw_address(struct macsec_context *ctx, if (!rx_sa || !rx_sa->macsec_rule) continue; - mlx5e_macsec_cleanup_sa(macsec, rx_sa, false); + mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, + rx_sc->sc_xarray_element->fs_id); } } @@ -1160,7 +1124,8 @@ static int macsec_upd_secy_hw_address(struct macsec_context *ctx, continue; if (rx_sa->active) { - err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false); + err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, + &rx_sc->sc_xarray_element->fs_id); if (err) goto out; } @@ -1213,7 +1178,7 @@ static int mlx5e_macsec_upd_secy(struct macsec_context *ctx) if (!tx_sa) continue; - mlx5e_macsec_cleanup_sa(macsec, tx_sa, true); + mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); } for (i = 0; i < MACSEC_NUM_AN; ++i) { @@ -1222,7 +1187,7 @@ static int mlx5e_macsec_upd_secy(struct macsec_context *ctx) continue; if (tx_sa->assoc_num == tx_sc->encoding_sa && tx_sa->active) { - err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true); + err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL); if (err) goto out; } @@ -1260,7 +1225,7 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx) if (!tx_sa) continue; - mlx5e_macsec_cleanup_sa(macsec, tx_sa, true); + mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id); kfree(tx_sa); macsec_device->tx_sa[i] = NULL; @@ -1268,7 +1233,7 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx) list = &macsec_device->macsec_rx_sc_list_head; list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) - macsec_del_rxsc_ctx(macsec, rx_sc); + macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev); kfree(macsec_device->dev_addr); macsec_device->dev_addr = NULL; @@ -1693,7 +1658,8 @@ bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb struct metadata_dst *md_dst = skb_metadata_dst(skb); u32 fs_id; - fs_id = mlx5e_macsec_get_sa_from_hashtable(&macsec->sci_hash, &md_dst->u.macsec_info.sci); + fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs, + &md_dst->u.macsec_info.sci); if (!fs_id) goto err_out; @@ -1711,7 +1677,8 @@ void mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec *macsec, struct metadata_dst *md_dst = skb_metadata_dst(skb); u32 fs_id; - fs_id = mlx5e_macsec_get_sa_from_hashtable(&macsec->sci_hash, &md_dst->u.macsec_info.sci); + fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs, + &md_dst->u.macsec_info.sci); if (!fs_id) return; @@ -1779,13 +1746,6 @@ int mlx5e_macsec_init(struct mlx5e_priv *priv) INIT_LIST_HEAD(&macsec->macsec_device_list_head); mutex_init(&macsec->lock); - err = rhashtable_init(&macsec->sci_hash, &rhash_sci); - if (err) { - mlx5_core_err(mdev, "MACsec offload: Failed to init SCI hash table, err=%d\n", - err); - goto err_hash; - } - err = mlx5e_macsec_aso_init(&macsec->aso, priv->mdev); if (err) { mlx5_core_err(mdev, "MACsec offload: Failed to init aso, err=%d\n", err); @@ -1824,8 +1784,6 @@ err_out: err_wq: mlx5e_macsec_aso_cleanup(&macsec->aso, priv->mdev); err_aso: - rhashtable_destroy(&macsec->sci_hash); -err_hash: kfree(macsec); priv->macsec = NULL; return err; @@ -1843,7 +1801,6 @@ void mlx5e_macsec_cleanup(struct mlx5e_priv *priv) mlx5_macsec_fs_cleanup(mdev->macsec_fs); destroy_workqueue(macsec->wq); mlx5e_macsec_aso_cleanup(&macsec->aso, mdev); - rhashtable_destroy(&macsec->sci_hash); mutex_destroy(&macsec->lock); kfree(macsec); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 8ecc91f30da1..b3528516ba35 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -74,6 +74,20 @@ struct mlx5_macsec_tables { u32 refcnt; }; +struct mlx5_fs_id { + u32 id; + refcount_t refcnt; + sci_t sci; + struct rhash_head hash; +}; + +struct mlx5_macsec_device { + struct list_head macsec_devices_list_entry; + void *macdev; + struct xarray tx_id_xa; + struct xarray rx_id_xa; +}; + struct mlx5_macsec_tx { struct mlx5_flow_handle *crypto_mke_rule; struct mlx5_flow_handle *check_rule; @@ -100,6 +114,22 @@ union mlx5_macsec_rule { struct mlx5_macsec_rx_rule rx_rule; }; +static const struct rhashtable_params rhash_sci = { + .key_len = sizeof_field(struct mlx5_fs_id, sci), + .key_offset = offsetof(struct mlx5_fs_id, sci), + .head_offset = offsetof(struct mlx5_fs_id, hash), + .automatic_shrinking = true, + .min_size = 1, +}; + +static const struct rhashtable_params rhash_fs_id = { + .key_len = sizeof_field(struct mlx5_fs_id, id), + .key_offset = offsetof(struct mlx5_fs_id, id), + .head_offset = offsetof(struct mlx5_fs_id, hash), + .automatic_shrinking = true, + .min_size = 1, +}; + struct mlx5_macsec_fs { struct mlx5_core_dev *mdev; struct mlx5_macsec_tx *tx_fs; @@ -107,6 +137,15 @@ struct mlx5_macsec_fs { /* Stats manage */ struct mlx5_macsec_stats stats; + + /* Tx sci -> fs id mapping handling */ + struct rhashtable sci_hash; /* sci -> mlx5_fs_id */ + + /* RX fs_id -> mlx5_fs_id mapping handling */ + struct rhashtable fs_id_hash; /* fs_id -> mlx5_fs_id */ + + /* TX & RX fs_id lists per macsec device */ + struct list_head macsec_devices_list; }; static void macsec_fs_destroy_groups(struct mlx5_macsec_flow_table *ft) @@ -512,9 +551,137 @@ static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx, memcpy(reformatbf, §ag, *reformat_size); } +static bool macsec_fs_is_macsec_device_empty(struct mlx5_macsec_device *macsec_device) +{ + if (xa_empty(&macsec_device->tx_id_xa) && + xa_empty(&macsec_device->rx_id_xa)) + return true; + + return false; +} + +static void macsec_fs_id_del(struct list_head *macsec_devices_list, u32 fs_id, + void *macdev, struct rhashtable *hash_table, bool is_tx) +{ + const struct rhashtable_params *rhash = (is_tx) ? &rhash_sci : &rhash_fs_id; + struct mlx5_macsec_device *iter, *macsec_device = NULL; + struct mlx5_fs_id *fs_id_found; + struct xarray *fs_id_xa; + + list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) { + if (iter->macdev == macdev) { + macsec_device = iter; + break; + } + } + WARN_ON(!macsec_device); + + fs_id_xa = (is_tx) ? &macsec_device->tx_id_xa : + &macsec_device->rx_id_xa; + xa_lock(fs_id_xa); + fs_id_found = xa_load(fs_id_xa, fs_id); + WARN_ON(!fs_id_found); + + if (!refcount_dec_and_test(&fs_id_found->refcnt)) { + xa_unlock(fs_id_xa); + return; + } + + if (fs_id_found->id) { + /* Make sure ongoing datapath readers sees a valid SA */ + rhashtable_remove_fast(hash_table, &fs_id_found->hash, *rhash); + fs_id_found->id = 0; + } + xa_unlock(fs_id_xa); + + xa_erase(fs_id_xa, fs_id); + + kfree(fs_id_found); + + if (macsec_fs_is_macsec_device_empty(macsec_device)) { + list_del(&macsec_device->macsec_devices_list_entry); + kfree(macsec_device); + } +} + +static int macsec_fs_id_add(struct list_head *macsec_devices_list, u32 fs_id, + void *macdev, struct rhashtable *hash_table, sci_t sci, + bool is_tx) +{ + const struct rhashtable_params *rhash = (is_tx) ? &rhash_sci : &rhash_fs_id; + struct mlx5_macsec_device *iter, *macsec_device = NULL; + struct mlx5_fs_id *fs_id_iter; + struct xarray *fs_id_xa; + int err; + + if (!is_tx) { + rcu_read_lock(); + fs_id_iter = rhashtable_lookup(hash_table, &fs_id, rhash_fs_id); + if (fs_id_iter) { + refcount_inc(&fs_id_iter->refcnt); + rcu_read_unlock(); + return 0; + } + rcu_read_unlock(); + } + + fs_id_iter = kzalloc(sizeof(*fs_id_iter), GFP_KERNEL); + if (!fs_id_iter) + return -ENOMEM; + + list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) { + if (iter->macdev == macdev) { + macsec_device = iter; + break; + } + } + + if (!macsec_device) { /* first time adding a SA to that device */ + macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL); + if (!macsec_device) { + err = -ENOMEM; + goto err_alloc_dev; + } + macsec_device->macdev = macdev; + xa_init(&macsec_device->tx_id_xa); + xa_init(&macsec_device->rx_id_xa); + list_add(&macsec_device->macsec_devices_list_entry, macsec_devices_list); + } + + fs_id_xa = (is_tx) ? &macsec_device->tx_id_xa : + &macsec_device->rx_id_xa; + fs_id_iter->id = fs_id; + refcount_set(&fs_id_iter->refcnt, 1); + fs_id_iter->sci = sci; + err = xa_err(xa_store(fs_id_xa, fs_id, fs_id_iter, GFP_KERNEL)); + if (err) + goto err_store_id; + + err = rhashtable_insert_fast(hash_table, &fs_id_iter->hash, *rhash); + if (err) + goto err_hash_insert; + + return 0; + +err_hash_insert: + xa_erase(fs_id_xa, fs_id); +err_store_id: + if (macsec_fs_is_macsec_device_empty(macsec_device)) { + list_del(&macsec_device->macsec_devices_list_entry); + kfree(macsec_device); + } +err_alloc_dev: + kfree(fs_id_iter); + return err; +} + static void macsec_fs_tx_del_rule(struct mlx5_macsec_fs *macsec_fs, - struct mlx5_macsec_tx_rule *tx_rule) + struct mlx5_macsec_tx_rule *tx_rule, + void *macdev) { + macsec_fs_id_del(&macsec_fs->macsec_devices_list, tx_rule->fs_id, macdev, + &macsec_fs->sci_hash, true); + if (tx_rule->rule) { mlx5_del_flow_rules(tx_rule->rule); tx_rule->rule = NULL; @@ -540,8 +707,7 @@ static void macsec_fs_tx_del_rule(struct mlx5_macsec_fs *macsec_fs, static union mlx5_macsec_rule * macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, const struct macsec_context *macsec_ctx, - struct mlx5_macsec_rule_attrs *attrs, - u32 *sa_fs_id) + struct mlx5_macsec_rule_attrs *attrs) { char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; struct mlx5_pkt_reformat_params reformat_params = {}; @@ -605,7 +771,6 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, } tx_rule->fs_id = fs_id; - *sa_fs_id = fs_id; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | @@ -620,10 +785,17 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, } tx_rule->rule = rule; + err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, fs_id, macsec_ctx->secy->netdev, + &macsec_fs->sci_hash, attrs->sci, true); + if (err) { + mlx5_core_err(mdev, "Failed to save fs_id, err=%d\n", err); + goto err; + } + goto out_spec; err: - macsec_fs_tx_del_rule(macsec_fs, tx_rule); + macsec_fs_tx_del_rule(macsec_fs, tx_rule, macsec_ctx->secy->netdev); macsec_rule = NULL; out_spec: kvfree(spec); @@ -699,6 +871,7 @@ static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs) tx_tables->check_miss_rule_counter = flow_counter; ida_init(&tx_fs->tx_halloc); + INIT_LIST_HEAD(&macsec_fs->macsec_devices_list); macsec_fs->tx_fs = tx_fs; @@ -1070,10 +1243,14 @@ static void macsec_fs_rx_ft_put(struct mlx5_macsec_fs *macsec_fs) } static void macsec_fs_rx_del_rule(struct mlx5_macsec_fs *macsec_fs, - struct mlx5_macsec_rx_rule *rx_rule) + struct mlx5_macsec_rx_rule *rx_rule, + void *macdev, u32 fs_id) { int i; + macsec_fs_id_del(&macsec_fs->macsec_devices_list, fs_id, macdev, + &macsec_fs->fs_id_hash, false); + for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) { if (rx_rule->rule[i]) { mlx5_del_flow_rules(rx_rule->rule[i]); @@ -1139,6 +1316,7 @@ static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec, static union mlx5_macsec_rule * macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, + const struct macsec_context *macsec_ctx, struct mlx5_macsec_rule_attrs *attrs, u32 fs_id) { @@ -1238,11 +1416,18 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, rx_rule->rule[1] = rule; } + err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, fs_id, macsec_ctx->secy->netdev, + &macsec_fs->fs_id_hash, attrs->sci, false); + if (err) { + mlx5_core_err(mdev, "Failed to save fs_id, err=%d\n", err); + goto err; + } + kvfree(spec); return macsec_rule; err: - macsec_fs_rx_del_rule(macsec_fs, rx_rule); + macsec_fs_rx_del_rule(macsec_fs, rx_rule, macsec_ctx->secy->netdev, fs_id); macsec_rule = NULL; out_spec: kvfree(spec); @@ -1362,6 +1547,20 @@ struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec return &macsec_fs->stats; } +u32 mlx5_macsec_fs_get_fs_id_from_hashtable(struct mlx5_macsec_fs *macsec_fs, sci_t *sci) +{ + struct mlx5_fs_id *mlx5_fs_id; + u32 fs_id = 0; + + rcu_read_lock(); + mlx5_fs_id = rhashtable_lookup(&macsec_fs->sci_hash, sci, rhash_sci); + if (mlx5_fs_id) + fs_id = mlx5_fs_id->id; + rcu_read_unlock(); + + return fs_id; +} + union mlx5_macsec_rule * mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, const struct macsec_context *macsec_ctx, @@ -1369,23 +1568,25 @@ mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, u32 *sa_fs_id) { return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? - macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) : - macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id); + macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs) : + macsec_fs_rx_add_rule(macsec_fs, macsec_ctx, attrs, *sa_fs_id); } void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, union mlx5_macsec_rule *macsec_rule, - int action) + int action, void *macdev, u32 sa_fs_id) { (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? - macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) : - macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule); + macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule, macdev) : + macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule, macdev, sa_fs_id); } void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs) { macsec_fs_rx_cleanup(macsec_fs); macsec_fs_tx_cleanup(macsec_fs); + rhashtable_destroy(&macsec_fs->fs_id_hash); + rhashtable_destroy(&macsec_fs->sci_hash); kfree(macsec_fs); } @@ -1401,10 +1602,24 @@ mlx5_macsec_fs_init(struct mlx5_core_dev *mdev) macsec_fs->mdev = mdev; + err = rhashtable_init(&macsec_fs->sci_hash, &rhash_sci); + if (err) { + mlx5_core_err(mdev, "MACsec offload: Failed to init SCI hash table, err=%d\n", + err); + goto err_hash; + } + + err = rhashtable_init(&macsec_fs->fs_id_hash, &rhash_fs_id); + if (err) { + mlx5_core_err(mdev, "MACsec offload: Failed to init FS_ID hash table, err=%d\n", + err); + goto sci_hash_cleanup; + } + err = macsec_fs_tx_init(macsec_fs); if (err) { mlx5_core_err(mdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err); - goto err; + goto fs_id_hash_cleanup; } err = macsec_fs_rx_init(macsec_fs); @@ -1417,7 +1632,11 @@ mlx5_macsec_fs_init(struct mlx5_core_dev *mdev) tx_cleanup: macsec_fs_tx_cleanup(macsec_fs); -err: +fs_id_hash_cleanup: + rhashtable_destroy(&macsec_fs->fs_id_hash); +sci_hash_cleanup: + rhashtable_destroy(&macsec_fs->sci_hash); +err_hash: kfree(macsec_fs); return NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h index f007c33369c2..34b80c3ef6a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h @@ -53,10 +53,11 @@ mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, union mlx5_macsec_rule *macsec_rule, - int action); + int action, void *macdev, u32 sa_fs_id); void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats); struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec_fs); +u32 mlx5_macsec_fs_get_fs_id_from_hashtable(struct mlx5_macsec_fs *macsec_fs, sci_t *sci); #endif -- cgit From 758ce14aee825f8f3ca8f76c9991c108094cae8b Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Tue, 3 May 2022 08:37:48 +0300 Subject: RDMA/mlx5: Implement MACsec gid addition and deletion Handle MACsec IP ambiguity issue, since mlx5 hw can't support programming both the MACsec and the physical gid when they have the same IP address, because it wouldn't know to whom to steer the traffic. Hence in such case we delete the physical gid from the hw gid table, which would then cause all traffic sent over it to fail, and we'll only be able to send traffic over the MACsec gid. Signed-off-by: Patrisious Haddad Reviewed-by: Raed Salem Reviewed-by: Mark Zhang Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/en_accel/macsec.c | 31 ---------------------- .../ethernet/mellanox/mlx5/core/en_accel/macsec.h | 2 -- 2 files changed, 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index b4f3f4f10af3..c9c1db971652 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1607,37 +1607,6 @@ static void mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso *aso, struct mlx5_c mlx5_core_dealloc_pd(mdev, aso->pdn); } -bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) -{ - if (!(MLX5_CAP_GEN_64(mdev, general_obj_types) & - MLX5_GENERAL_OBJ_TYPES_CAP_MACSEC_OFFLOAD)) - return false; - - if (!MLX5_CAP_GEN(mdev, log_max_dek)) - return false; - - if (!MLX5_CAP_MACSEC(mdev, log_max_macsec_offload)) - return false; - - if (!MLX5_CAP_FLOWTABLE_NIC_RX(mdev, macsec_decrypt) || - !MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_remove_macsec)) - return false; - - if (!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, macsec_encrypt) || - !MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_macsec)) - return false; - - if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_encrypt) && - !MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_encrypt)) - return false; - - if (!MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_128_decrypt) && - !MLX5_CAP_MACSEC(mdev, macsec_crypto_esp_aes_gcm_256_decrypt)) - return false; - - return true; -} - static const struct macsec_ops macsec_offload_ops = { .mdo_add_txsa = mlx5e_macsec_add_txsa, .mdo_upd_txsa = mlx5e_macsec_upd_txsa, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h index 2ecd769585f4..27df72e23106 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h @@ -36,7 +36,6 @@ static inline bool mlx5e_macsec_is_rx_flow(struct mlx5_cqe64 *cqe) void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, struct mlx5_cqe64 *cqe); -bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev); #else @@ -49,7 +48,6 @@ static inline void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, struct mlx5_cqe64 *cqe) {} -static inline bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) { return false; } #endif /* CONFIG_MLX5_MACSEC */ #endif /* __MLX5_ACCEL_EN_MACSEC_H__ */ -- cgit From afcb21d5a89b40c3062aa48d39ab5340abf7dcd8 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Thu, 11 Aug 2022 05:20:02 +0300 Subject: net/mlx5: Add MACsec priorities in RDMA namespaces Add MACsec flow steering priorities in RDMA namespaces. This allows adding tables/rules to forward RoCEv2 traffic to the MACsec crypto tables in NIC_TX domain, and accept RoCEv2 traffic from NIC_RX domain. Signed-off-by: Patrisious Haddad Reviewed-by: Maor Gottlieb Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 35 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 4ef04aa28771..cc27908bb113 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -224,6 +224,7 @@ static struct init_tree_node egress_root_fs = { enum { RDMA_RX_IPSEC_PRIO, + RDMA_RX_MACSEC_PRIO, RDMA_RX_COUNTERS_PRIO, RDMA_RX_BYPASS_PRIO, RDMA_RX_KERNEL_PRIO, @@ -237,9 +238,13 @@ enum { #define RDMA_RX_KERNEL_MIN_LEVEL (RDMA_RX_BYPASS_MIN_LEVEL + 1) #define RDMA_RX_COUNTERS_MIN_LEVEL (RDMA_RX_KERNEL_MIN_LEVEL + 2) +#define RDMA_RX_MACSEC_NUM_PRIOS 1 +#define RDMA_RX_MACSEC_PRIO_NUM_LEVELS 2 +#define RDMA_RX_MACSEC_MIN_LEVEL (RDMA_RX_COUNTERS_MIN_LEVEL + RDMA_RX_MACSEC_NUM_PRIOS) + static struct init_tree_node rdma_rx_root_fs = { .type = FS_TYPE_NAMESPACE, - .ar_size = 4, + .ar_size = 5, .children = (struct init_tree_node[]) { [RDMA_RX_IPSEC_PRIO] = ADD_PRIO(0, RDMA_RX_IPSEC_MIN_LEVEL, 0, @@ -247,6 +252,12 @@ static struct init_tree_node rdma_rx_root_fs = { ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, ADD_MULTIPLE_PRIO(RDMA_RX_IPSEC_NUM_PRIOS, RDMA_RX_IPSEC_NUM_LEVELS))), + [RDMA_RX_MACSEC_PRIO] = + ADD_PRIO(0, RDMA_RX_MACSEC_MIN_LEVEL, 0, + FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(RDMA_RX_MACSEC_NUM_PRIOS, + RDMA_RX_MACSEC_PRIO_NUM_LEVELS))), [RDMA_RX_COUNTERS_PRIO] = ADD_PRIO(0, RDMA_RX_COUNTERS_MIN_LEVEL, 0, FS_CHAINING_CAPS, @@ -270,6 +281,7 @@ static struct init_tree_node rdma_rx_root_fs = { enum { RDMA_TX_COUNTERS_PRIO, RDMA_TX_IPSEC_PRIO, + RDMA_TX_MACSEC_PRIO, RDMA_TX_BYPASS_PRIO, }; @@ -280,9 +292,13 @@ enum { #define RDMA_TX_IPSEC_PRIO_NUM_LEVELS 1 #define RDMA_TX_IPSEC_MIN_LEVEL (RDMA_TX_COUNTERS_MIN_LEVEL + RDMA_TX_IPSEC_NUM_PRIOS) +#define RDMA_TX_MACSEC_NUM_PRIOS 1 +#define RDMA_TX_MACESC_PRIO_NUM_LEVELS 1 +#define RDMA_TX_MACSEC_MIN_LEVEL (RDMA_TX_COUNTERS_MIN_LEVEL + RDMA_TX_MACSEC_NUM_PRIOS) + static struct init_tree_node rdma_tx_root_fs = { .type = FS_TYPE_NAMESPACE, - .ar_size = 3, + .ar_size = 4, .children = (struct init_tree_node[]) { [RDMA_TX_COUNTERS_PRIO] = ADD_PRIO(0, RDMA_TX_COUNTERS_MIN_LEVEL, 0, @@ -296,7 +312,12 @@ static struct init_tree_node rdma_tx_root_fs = { ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, ADD_MULTIPLE_PRIO(RDMA_TX_IPSEC_NUM_PRIOS, RDMA_TX_IPSEC_PRIO_NUM_LEVELS))), - + [RDMA_TX_MACSEC_PRIO] = + ADD_PRIO(0, RDMA_TX_MACSEC_MIN_LEVEL, 0, + FS_CHAINING_CAPS, + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, + ADD_MULTIPLE_PRIO(RDMA_TX_MACSEC_NUM_PRIOS, + RDMA_TX_MACESC_PRIO_NUM_LEVELS))), [RDMA_TX_BYPASS_PRIO] = ADD_PRIO(0, RDMA_TX_BYPASS_MIN_LEVEL, 0, FS_CHAINING_CAPS_RDMA_TX, @@ -2403,6 +2424,14 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev, root_ns = steering->rdma_tx_root_ns; prio = RDMA_TX_IPSEC_PRIO; break; + case MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC: + root_ns = steering->rdma_rx_root_ns; + prio = RDMA_RX_MACSEC_PRIO; + break; + case MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC: + root_ns = steering->rdma_tx_root_ns; + prio = RDMA_TX_MACSEC_PRIO; + break; default: /* Must be NIC RX */ WARN_ON(!is_nic_rx_ns(type)); root_ns = steering->root_ns; -- cgit From 9b240d1094cba5ca4e1bf80ea9f6ef55e6961af9 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Thu, 11 Aug 2022 06:00:55 +0300 Subject: net/mlx5: Configure MACsec steering for egress RoCEv2 traffic Add steering table in RDMA_TX domain, to forward MACsec traffic to MACsec crypto table in NIC domain. The tables are created in a lazy manner when the first TX SA is being created, and destroyed upon the destruction of the last SA. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 46 +++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index b3528516ba35..e5c42b1cc761 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -95,6 +95,8 @@ struct mlx5_macsec_tx { struct ida tx_halloc; struct mlx5_macsec_tables tables; + + struct mlx5_flow_table *ft_rdma_tx; }; struct mlx5_macsec_rx_rule { @@ -173,6 +175,9 @@ static void macsec_fs_tx_destroy(struct mlx5_macsec_fs *macsec_fs) struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; struct mlx5_macsec_tables *tx_tables; + if (mlx5_is_macsec_roce_supported(macsec_fs->mdev)) + mlx5_destroy_flow_table(tx_fs->ft_rdma_tx); + tx_tables = &tx_fs->tables; /* Tx check table */ @@ -300,6 +305,39 @@ static struct mlx5_flow_table return fdb; } +enum { + RDMA_TX_MACSEC_LEVEL = 0, +}; + +static int macsec_fs_tx_roce_create(struct mlx5_macsec_fs *macsec_fs) +{ + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_flow_namespace *ns; + struct mlx5_flow_table *ft; + int err; + + if (!mlx5_is_macsec_roce_supported(mdev)) { + mlx5_core_dbg(mdev, "Failed to init RoCE MACsec, capabilities not supported\n"); + return 0; + } + + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC); + if (!ns) + return -ENOMEM; + + /* Tx RoCE crypto table */ + ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_TX_MACSEC_LEVEL, CRYPTO_NUM_MAXSEC_FTE); + if (IS_ERR(ft)) { + err = PTR_ERR(ft); + mlx5_core_err(mdev, "Failed to create MACsec RoCE Tx crypto table err(%d)\n", err); + return err; + } + tx_fs->ft_rdma_tx = ft; + + return 0; +} + static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); @@ -442,7 +480,13 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs) } tx_fs->check_rule = rule; - goto out_flow_group; + err = macsec_fs_tx_roce_create(macsec_fs); + if (err) + goto err; + + kvfree(flow_group_in); + kvfree(spec); + return 0; err: macsec_fs_tx_destroy(macsec_fs); -- cgit From 8c14a2c7c96f1624ffb8406accd082b4aff36883 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Thu, 11 Aug 2022 06:09:18 +0300 Subject: net/mlx5: Configure MACsec steering for ingress RoCEv2 traffic Add steering tables/rules to check if the decrypted traffic is RoCEv2, if so copy reg_b_metadata to a temp reg and forward it to RDMA_RX domain. The rules are added once the MACsec device is assigned an IP address where we verify that the packet ip is for MACsec device and that the temp reg has MACsec operation and a valid SCI inside. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +- .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 359 ++++++++++++++++++++- 2 files changed, 352 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index cc27908bb113..805a51286718 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -107,7 +107,7 @@ LEFTOVERS_NUM_PRIOS) #define KERNEL_RX_MACSEC_NUM_PRIOS 1 -#define KERNEL_RX_MACSEC_NUM_LEVELS 2 +#define KERNEL_RX_MACSEC_NUM_LEVELS 3 #define KERNEL_RX_MACSEC_MIN_LEVEL (BY_PASS_MIN_LEVEL + KERNEL_RX_MACSEC_NUM_PRIOS) #define ETHTOOL_PRIO_NUM_LEVELS 1 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index e5c42b1cc761..552ab425ae39 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -22,7 +22,9 @@ #define TX_CHECK_TABLE_NUM_FTE 2 #define RX_CRYPTO_TABLE_LEVEL 0 #define RX_CHECK_TABLE_LEVEL 1 +#define RX_ROCE_TABLE_LEVEL 2 #define RX_CHECK_TABLE_NUM_FTE 3 +#define RX_ROCE_TABLE_NUM_FTE 2 #define RX_CRYPTO_TABLE_NUM_GROUPS 3 #define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \ ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2) @@ -30,6 +32,9 @@ (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE) #define RX_NUM_OF_RULES_PER_SA 2 +#define RDMA_RX_ROCE_IP_TABLE_LEVEL 0 +#define RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL 1 + #define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */ #define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23 #define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8 @@ -104,11 +109,31 @@ struct mlx5_macsec_rx_rule { struct mlx5_modify_hdr *meta_modhdr; }; +struct mlx5_macsec_miss { + struct mlx5_flow_group *g; + struct mlx5_flow_handle *rule; +}; + +struct mlx5_macsec_rx_roce { + /* Flow table/rules in NIC domain, to check if it's a RoCE packet */ + struct mlx5_flow_group *g; + struct mlx5_flow_table *ft; + struct mlx5_flow_handle *rule; + struct mlx5_modify_hdr *copy_modify_hdr; + struct mlx5_macsec_miss nic_miss; + + /* Flow table/rule in RDMA domain, to check dgid */ + struct mlx5_flow_table *ft_ip_check; + struct mlx5_flow_table *ft_macsec_op_check; + struct mlx5_macsec_miss miss; +}; + struct mlx5_macsec_rx { struct mlx5_flow_handle *check_rule[2]; struct mlx5_pkt_reformat *check_rule_pkt_reformat[2]; struct mlx5_macsec_tables tables; + struct mlx5_macsec_rx_roce roce; }; union mlx5_macsec_rule { @@ -932,6 +957,29 @@ err_encrypt_counter: return err; } +static void macsec_fs_rx_roce_miss_destroy(struct mlx5_macsec_miss *miss) +{ + mlx5_del_flow_rules(miss->rule); + mlx5_destroy_flow_group(miss->g); +} + +static void macsec_fs_rdma_rx_destroy(struct mlx5_macsec_rx_roce *roce, struct mlx5_core_dev *mdev) +{ + if (!mlx5_is_macsec_roce_supported(mdev)) + return; + + mlx5_del_flow_rules(roce->nic_miss.rule); + mlx5_del_flow_rules(roce->rule); + mlx5_modify_header_dealloc(mdev, roce->copy_modify_hdr); + mlx5_destroy_flow_group(roce->nic_miss.g); + mlx5_destroy_flow_group(roce->g); + mlx5_destroy_flow_table(roce->ft); + + macsec_fs_rx_roce_miss_destroy(&roce->miss); + mlx5_destroy_flow_table(roce->ft_macsec_op_check); + mlx5_destroy_flow_table(roce->ft_ip_check); +} + static void macsec_fs_rx_destroy(struct mlx5_macsec_fs *macsec_fs) { struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; @@ -976,6 +1024,8 @@ static void macsec_fs_rx_destroy(struct mlx5_macsec_fs *macsec_fs) } macsec_fs_destroy_flow_table(&rx_tables->ft_crypto); + + macsec_fs_rdma_rx_destroy(&macsec_fs->rx_fs->roce, macsec_fs->mdev); } static int macsec_fs_rx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft) @@ -1071,9 +1121,10 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs struct mlx5_pkt_reformat_params reformat_params = {}; struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_flow_destination roce_dest[2]; struct mlx5_macsec_tables *rx_tables; struct mlx5_flow_handle *rule; - int err = 0; + int err = 0, dstn = 0; rx_tables = &rx_fs->tables; @@ -1114,12 +1165,22 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); flow_act->flags = FLOW_ACT_NO_APPEND; - flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO | - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | - MLX5_FLOW_CONTEXT_ACTION_COUNT; - dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter); - rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1); + + if (rx_fs->roce.ft) { + flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + roce_dest[dstn].ft = rx_fs->roce.ft; + dstn++; + } else { + flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + } + + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + roce_dest[dstn].counter_id = mlx5_fc_id(rx_tables->check_rule_counter); + rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, roce_dest, dstn + 1); + if (IS_ERR(rule)) { err = PTR_ERR(rule); mlx5_core_err(mdev, "Failed to add MACsec Rx check rule, err=%d\n", err); @@ -1131,6 +1192,284 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs return 0; } +static int macsec_fs_rx_roce_miss_create(struct mlx5_core_dev *mdev, + struct mlx5_macsec_rx_roce *roce) +{ + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_group *flow_group; + struct mlx5_flow_handle *rule; + u32 *flow_group_in; + int err; + + flow_group_in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); + if (!flow_group_in) + return -ENOMEM; + + /* IP check ft has no miss rule since we use default miss action which is go to next PRIO */ + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, + roce->ft_macsec_op_check->max_fte - 1); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, + roce->ft_macsec_op_check->max_fte - 1); + flow_group = mlx5_create_flow_group(roce->ft_macsec_op_check, flow_group_in); + if (IS_ERR(flow_group)) { + err = PTR_ERR(flow_group); + mlx5_core_err(mdev, + "Failed to create miss flow group for MACsec RoCE operation check table err(%d)\n", + err); + goto err_macsec_op_miss_group; + } + roce->miss.g = flow_group; + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; + rule = mlx5_add_flow_rules(roce->ft_macsec_op_check, NULL, &flow_act, NULL, 0); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE operation check table err(%d)\n", + err); + goto err_macsec_op_rule; + } + roce->miss.rule = rule; + + kvfree(flow_group_in); + return 0; + +err_macsec_op_rule: + mlx5_destroy_flow_group(roce->miss.g); +err_macsec_op_miss_group: + kvfree(flow_group_in); + return err; +} + +#define MLX5_RX_ROCE_GROUP_SIZE BIT(0) + +static int macsec_fs_rx_roce_jump_to_rdma_groups_create(struct mlx5_core_dev *mdev, + struct mlx5_macsec_rx_roce *roce) +{ + struct mlx5_flow_group *g; + void *outer_headers_c; + int ix = 0; + u32 *in; + int err; + u8 *mc; + + in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); + if (!in) + return -ENOMEM; + + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); + outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers); + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol); + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, udp_dport); + + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); + MLX5_SET_CFG(in, start_flow_index, ix); + ix += MLX5_RX_ROCE_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + g = mlx5_create_flow_group(roce->ft, in); + if (IS_ERR(g)) { + err = PTR_ERR(g); + mlx5_core_err(mdev, "Failed to create main flow group for MACsec RoCE NIC UDP table err(%d)\n", + err); + goto err_udp_group; + } + roce->g = g; + + memset(in, 0, MLX5_ST_SZ_BYTES(create_flow_group_in)); + MLX5_SET_CFG(in, start_flow_index, ix); + ix += MLX5_RX_ROCE_GROUP_SIZE; + MLX5_SET_CFG(in, end_flow_index, ix - 1); + g = mlx5_create_flow_group(roce->ft, in); + if (IS_ERR(g)) { + err = PTR_ERR(g); + mlx5_core_err(mdev, "Failed to create miss flow group for MACsec RoCE NIC UDP table err(%d)\n", + err); + goto err_udp_miss_group; + } + roce->nic_miss.g = g; + + kvfree(in); + return 0; + +err_udp_miss_group: + mlx5_destroy_flow_group(roce->g); +err_udp_group: + kvfree(in); + return err; +} + +static int macsec_fs_rx_roce_jump_to_rdma_rules_create(struct mlx5_macsec_fs *macsec_fs, + struct mlx5_macsec_rx_roce *roce) +{ + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_flow_destination dst = {}; + struct mlx5_modify_hdr *modify_hdr; + MLX5_DECLARE_FLOW_ACT(flow_act); + struct mlx5_flow_handle *rule; + struct mlx5_flow_spec *spec; + int err; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_UDP); + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.udp_dport); + MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_dport, ROCE_V2_UDP_DPORT); + + MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY); + MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); + MLX5_SET(copy_action_in, action, src_offset, 0); + MLX5_SET(copy_action_in, action, length, 32); + MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_5); + MLX5_SET(copy_action_in, action, dst_offset, 0); + + modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, + 1, action); + + if (IS_ERR(modify_hdr)) { + err = PTR_ERR(modify_hdr); + mlx5_core_err(mdev, + "Failed to alloc macsec copy modify_header_id err(%d)\n", err); + goto err_alloc_hdr; + } + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + flow_act.modify_hdr = modify_hdr; + dst.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; + dst.ft = roce->ft_ip_check; + rule = mlx5_add_flow_rules(roce->ft, spec, &flow_act, &dst, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + mlx5_core_err(mdev, "Failed to add rule to MACsec RoCE NIC UDP table err(%d)\n", + err); + goto err_add_rule; + } + roce->rule = rule; + roce->copy_modify_hdr = modify_hdr; + + memset(&flow_act, 0, sizeof(flow_act)); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + rule = mlx5_add_flow_rules(roce->ft, NULL, &flow_act, NULL, 0); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE NIC UDP table err(%d)\n", + err); + goto err_add_rule2; + } + roce->nic_miss.rule = rule; + + kvfree(spec); + return 0; + +err_add_rule2: + mlx5_del_flow_rules(roce->rule); +err_add_rule: + mlx5_modify_header_dealloc(macsec_fs->mdev, modify_hdr); +err_alloc_hdr: + kvfree(spec); + return err; +} + +static int macsec_fs_rx_roce_jump_to_rdma_create(struct mlx5_macsec_fs *macsec_fs, + struct mlx5_macsec_rx_roce *roce) +{ + int err; + + err = macsec_fs_rx_roce_jump_to_rdma_groups_create(macsec_fs->mdev, roce); + if (err) + return err; + + err = macsec_fs_rx_roce_jump_to_rdma_rules_create(macsec_fs, roce); + if (err) + goto err; + + return 0; +err: + mlx5_destroy_flow_group(roce->nic_miss.g); + mlx5_destroy_flow_group(roce->g); + return err; +} + +static int macsec_fs_rx_roce_create(struct mlx5_macsec_fs *macsec_fs) +{ + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_namespace *ns; + struct mlx5_flow_table *ft; + int err = 0; + + if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev)) { + mlx5_core_dbg(mdev, "Failed to init RoCE MACsec, capabilities not supported\n"); + return 0; + } + + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC); + if (!ns) + return -ENOMEM; + + ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_IP_TABLE_LEVEL, + CRYPTO_NUM_MAXSEC_FTE); + if (IS_ERR(ft)) { + err = PTR_ERR(ft); + mlx5_core_err(mdev, + "Failed to create MACsec IP check RoCE table err(%d)\n", err); + return err; + } + rx_fs->roce.ft_ip_check = ft; + + ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL, + CRYPTO_NUM_MAXSEC_FTE); + if (IS_ERR(ft)) { + err = PTR_ERR(ft); + mlx5_core_err(mdev, + "Failed to create MACsec operation check RoCE table err(%d)\n", + err); + goto err_macsec_op; + } + rx_fs->roce.ft_macsec_op_check = ft; + + err = macsec_fs_rx_roce_miss_create(mdev, &rx_fs->roce); + if (err) + goto err_miss_create; + + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); + if (!ns) { + err = -EOPNOTSUPP; + goto err_ns; + } + + ft_attr.level = RX_ROCE_TABLE_LEVEL; + ft_attr.max_fte = RX_ROCE_TABLE_NUM_FTE; + ft = mlx5_create_flow_table(ns, &ft_attr); + if (IS_ERR(ft)) { + err = PTR_ERR(ft); + mlx5_core_err(mdev, + "Failed to create MACsec jump to RX RoCE, NIC table err(%d)\n", err); + goto err_ns; + } + rx_fs->roce.ft = ft; + + err = macsec_fs_rx_roce_jump_to_rdma_create(macsec_fs, &rx_fs->roce); + if (err) + goto err_udp_ft; + + return 0; + +err_udp_ft: + mlx5_destroy_flow_table(rx_fs->roce.ft); +err_ns: + macsec_fs_rx_roce_miss_destroy(&rx_fs->roce.miss); +err_miss_create: + mlx5_destroy_flow_table(rx_fs->roce.ft_macsec_op_check); +err_macsec_op: + mlx5_destroy_flow_table(rx_fs->roce.ft_ip_check); + return err; +} + static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); @@ -1166,6 +1505,10 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) rx_tables = &rx_fs->tables; ft_crypto = &rx_tables->ft_crypto; + err = macsec_fs_rx_roce_create(macsec_fs); + if (err) + goto out_flow_group; + /* Rx crypto table */ ft_attr.level = RX_CRYPTO_TABLE_LEVEL; ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; @@ -1174,7 +1517,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) if (IS_ERR(flow_table)) { err = PTR_ERR(flow_table); mlx5_core_err(mdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); - goto out_flow_group; + goto err; } ft_crypto->t = flow_table; -- cgit From ac7ea1c78f0edb910af1c17a3fb01345944bcb39 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Thu, 13 Apr 2023 12:04:42 +0300 Subject: net/mlx5: Add RoCE MACsec steering infrastructure in core Adds all the core steering helper functions that are needed in order to setup RoCE steering rules which includes both the RX and TX rules addition and deletion. As well as exporting the function to be ready to use from the IB driver where we expose functions to allow deletion of all rules, which is needed when a GID is deleted, or a deletion of a specific rule when an SA is deleted, and a similar manner for the rules addition. These functions are used in a later patch by IB driver to trigger the rules addition/deletion when needed. Signed-off-by: Patrisious Haddad Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 1 + .../ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 399 ++++++++++++++++++++- 2 files changed, 391 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 91dcb0dcad10..4e651c2f65c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -967,6 +967,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns, max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions); table_type = FS_FT_ESW_INGRESS_ACL; break; + case MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC: case MLX5_FLOW_NAMESPACE_RDMA_TX: max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions); table_type = FS_FT_RDMA_TX; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 552ab425ae39..2f2cb67717cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "fs_core.h" #include "lib/macsec_fs.h" #include "mlx5_core.h" @@ -46,6 +48,10 @@ /* MACsec RX flow steering */ #define MLX5_ETH_WQE_FT_META_MACSEC_MASK 0x3E +/* MACsec fs_id handling for steering */ +#define macsec_fs_set_tx_fs_id(fs_id) (MLX5_ETH_WQE_FT_META_MACSEC | (fs_id) << 2) +#define macsec_fs_set_rx_fs_id(fs_id) ((fs_id) | BIT(30)) + struct mlx5_sectag_header { __be16 ethertype; u8 tci_an; @@ -54,6 +60,14 @@ struct mlx5_sectag_header { u8 sci[MACSEC_SCI_LEN]; /* optional */ } __packed; +struct mlx5_roce_macsec_tx_rule { + u32 fs_id; + u16 gid_idx; + struct list_head entry; + struct mlx5_flow_handle *rule; + struct mlx5_modify_hdr *meta_modhdr; +}; + struct mlx5_macsec_tx_rule { struct mlx5_flow_handle *rule; struct mlx5_pkt_reformat *pkt_reformat; @@ -104,6 +118,14 @@ struct mlx5_macsec_tx { struct mlx5_flow_table *ft_rdma_tx; }; +struct mlx5_roce_macsec_rx_rule { + u32 fs_id; + u16 gid_idx; + struct mlx5_flow_handle *op; + struct mlx5_flow_handle *ip; + struct list_head entry; +}; + struct mlx5_macsec_rx_rule { struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA]; struct mlx5_modify_hdr *meta_modhdr; @@ -574,7 +596,7 @@ static int macsec_fs_tx_setup_fte(struct mlx5_macsec_fs *macsec_fs, MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a, MLX5_ETH_WQE_FT_META_MACSEC_MASK); MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a, - MLX5_ETH_WQE_FT_META_MACSEC | id << 2); + macsec_fs_set_tx_fs_id(id)); *fs_id = id; flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC; @@ -776,7 +798,7 @@ static void macsec_fs_tx_del_rule(struct mlx5_macsec_fs *macsec_fs, static union mlx5_macsec_rule * macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, const struct macsec_context *macsec_ctx, - struct mlx5_macsec_rule_attrs *attrs) + struct mlx5_macsec_rule_attrs *attrs, u32 *fs_id) { char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN]; struct mlx5_pkt_reformat_params reformat_params = {}; @@ -791,7 +813,6 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, struct mlx5_flow_spec *spec; size_t reformat_size; int err = 0; - u32 fs_id; tx_tables = &tx_fs->tables; @@ -831,7 +852,7 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, } tx_rule->pkt_reformat = flow_act.pkt_reformat; - err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id); + err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, fs_id); if (err) { mlx5_core_err(mdev, "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n", @@ -839,7 +860,7 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, goto err; } - tx_rule->fs_id = fs_id; + tx_rule->fs_id = *fs_id; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | @@ -854,7 +875,7 @@ macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs, } tx_rule->rule = rule; - err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, fs_id, macsec_ctx->secy->netdev, + err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, *fs_id, macsec_ctx->secy->netdev, &macsec_fs->sci_hash, attrs->sci, true); if (err) { mlx5_core_err(mdev, "Failed to save fs_id, err=%d\n", err); @@ -1743,7 +1764,7 @@ macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs, /* Set bit[15-0] fs id */ MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); - MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30)); + MLX5_SET(set_action_in, action, data, macsec_fs_set_rx_fs_id(fs_id)); MLX5_SET(set_action_in, action, offset, 0); MLX5_SET(set_action_in, action, length, 32); @@ -1902,6 +1923,114 @@ static void macsec_fs_rx_cleanup(struct mlx5_macsec_fs *macsec_fs) macsec_fs->rx_fs = NULL; } +static void set_ipaddr_spec_v4(struct sockaddr_in *in, struct mlx5_flow_spec *spec, bool is_dst_ip) +{ + MLX5_SET(fte_match_param, spec->match_value, + outer_headers.ip_version, MLX5_FS_IPV4_VERSION); + + if (is_dst_ip) { + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4); + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, + outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4), + &in->sin_addr.s_addr, 4); + } else { + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4); + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, + outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4), + &in->sin_addr.s_addr, 4); + } +} + +static void set_ipaddr_spec_v6(struct sockaddr_in6 *in6, struct mlx5_flow_spec *spec, + bool is_dst_ip) +{ + MLX5_SET(fte_match_param, spec->match_value, + outer_headers.ip_version, MLX5_FS_IPV6_VERSION); + + if (is_dst_ip) { + memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, + outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), + 0xff, 16); + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, + outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), + &in6->sin6_addr, 16); + } else { + memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, + outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), + 0xff, 16); + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, + outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), + &in6->sin6_addr, 16); + } +} + +static void set_ipaddr_spec(const struct sockaddr *addr, + struct mlx5_flow_spec *spec, bool is_dst_ip) +{ + struct sockaddr_in6 *in6; + + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + outer_headers.ip_version); + + if (addr->sa_family == AF_INET) { + struct sockaddr_in *in = (struct sockaddr_in *)addr; + + set_ipaddr_spec_v4(in, spec, is_dst_ip); + return; + } + + in6 = (struct sockaddr_in6 *)addr; + set_ipaddr_spec_v6(in6, spec, is_dst_ip); +} + +static void macsec_fs_del_roce_rule_rx(struct mlx5_roce_macsec_rx_rule *rx_rule) +{ + mlx5_del_flow_rules(rx_rule->op); + mlx5_del_flow_rules(rx_rule->ip); + list_del(&rx_rule->entry); + kfree(rx_rule); +} + +static void macsec_fs_del_roce_rules_rx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, + struct list_head *rx_rules_list) +{ + struct mlx5_roce_macsec_rx_rule *rx_rule, *next; + + if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev)) + return; + + list_for_each_entry_safe(rx_rule, next, rx_rules_list, entry) { + if (rx_rule->fs_id == fs_id) + macsec_fs_del_roce_rule_rx(rx_rule); + } +} + +static void macsec_fs_del_roce_rule_tx(struct mlx5_core_dev *mdev, + struct mlx5_roce_macsec_tx_rule *tx_rule) +{ + mlx5_del_flow_rules(tx_rule->rule); + mlx5_modify_header_dealloc(mdev, tx_rule->meta_modhdr); + list_del(&tx_rule->entry); + kfree(tx_rule); +} + +static void macsec_fs_del_roce_rules_tx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, + struct list_head *tx_rules_list) +{ + struct mlx5_roce_macsec_tx_rule *tx_rule, *next; + + if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev)) + return; + + list_for_each_entry_safe(tx_rule, next, tx_rules_list, entry) { + if (tx_rule->fs_id == fs_id) + macsec_fs_del_roce_rule_tx(macsec_fs->mdev, tx_rule); + } +} + void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats) { struct mlx5_macsec_stats *stats = (struct mlx5_macsec_stats *)macsec_stats; @@ -1954,20 +2083,270 @@ mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs, struct mlx5_macsec_rule_attrs *attrs, u32 *sa_fs_id) { - return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? - macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs) : + struct mlx5_macsec_event_data data = {.macsec_fs = macsec_fs, + .macdev = macsec_ctx->secy->netdev, + .is_tx = + (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) + }; + union mlx5_macsec_rule *macsec_rule; + u32 tx_new_fs_id; + + macsec_rule = (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? + macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, &tx_new_fs_id) : macsec_fs_rx_add_rule(macsec_fs, macsec_ctx, attrs, *sa_fs_id); + + data.fs_id = (data.is_tx) ? tx_new_fs_id : *sa_fs_id; + if (macsec_rule) + blocking_notifier_call_chain(&macsec_fs->mdev->macsec_nh, + MLX5_DRIVER_EVENT_MACSEC_SA_ADDED, + &data); + + return macsec_rule; } void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs, union mlx5_macsec_rule *macsec_rule, int action, void *macdev, u32 sa_fs_id) { + struct mlx5_macsec_event_data data = {.macsec_fs = macsec_fs, + .macdev = macdev, + .is_tx = (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) + }; + + data.fs_id = (data.is_tx) ? macsec_rule->tx_rule.fs_id : sa_fs_id; + blocking_notifier_call_chain(&macsec_fs->mdev->macsec_nh, + MLX5_DRIVER_EVENT_MACSEC_SA_DELETED, + &data); + (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ? macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule, macdev) : macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule, macdev, sa_fs_id); } +static int mlx5_macsec_fs_add_roce_rule_rx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, u16 gid_idx, + const struct sockaddr *addr, + struct list_head *rx_rules_list) +{ + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; + struct mlx5_roce_macsec_rx_rule *rx_rule; + struct mlx5_flow_destination dest = {}; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *new_rule; + struct mlx5_flow_spec *spec; + int err = 0; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + rx_rule = kzalloc(sizeof(*rx_rule), GFP_KERNEL); + if (!rx_rule) { + err = -ENOMEM; + goto out; + } + + set_ipaddr_spec(addr, spec, true); + + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + dest.ft = rx_fs->roce.ft_macsec_op_check; + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + new_rule = mlx5_add_flow_rules(rx_fs->roce.ft_ip_check, spec, &flow_act, + &dest, 1); + if (IS_ERR(new_rule)) { + err = PTR_ERR(new_rule); + goto ip_rule_err; + } + rx_rule->ip = new_rule; + + memset(&flow_act, 0, sizeof(flow_act)); + memset(spec, 0, sizeof(*spec)); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_5); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_5, + macsec_fs_set_rx_fs_id(fs_id)); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + new_rule = mlx5_add_flow_rules(rx_fs->roce.ft_macsec_op_check, spec, &flow_act, + NULL, 0); + if (IS_ERR(new_rule)) { + err = PTR_ERR(new_rule); + goto op_rule_err; + } + rx_rule->op = new_rule; + rx_rule->gid_idx = gid_idx; + rx_rule->fs_id = fs_id; + list_add_tail(&rx_rule->entry, rx_rules_list); + + goto out; + +op_rule_err: + mlx5_del_flow_rules(rx_rule->ip); + rx_rule->ip = NULL; +ip_rule_err: + kfree(rx_rule); +out: + kvfree(spec); + return err; +} + +static int mlx5_macsec_fs_add_roce_rule_tx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, u16 gid_idx, + const struct sockaddr *addr, + struct list_head *tx_rules_list) +{ + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; + struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_modify_hdr *modify_hdr = NULL; + struct mlx5_roce_macsec_tx_rule *tx_rule; + struct mlx5_flow_destination dest = {}; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *new_rule; + struct mlx5_flow_spec *spec; + int err = 0; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + tx_rule = kzalloc(sizeof(*tx_rule), GFP_KERNEL); + if (!tx_rule) { + err = -ENOMEM; + goto out; + } + + set_ipaddr_spec(addr, spec, false); + + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); + MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_A); + MLX5_SET(set_action_in, action, data, macsec_fs_set_tx_fs_id(fs_id)); + MLX5_SET(set_action_in, action, offset, 0); + MLX5_SET(set_action_in, action, length, 32); + + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC, + 1, action); + if (IS_ERR(modify_hdr)) { + err = PTR_ERR(modify_hdr); + mlx5_core_err(mdev, "Fail to alloc ROCE MACsec set modify_header_id err=%d\n", + err); + modify_hdr = NULL; + goto modify_hdr_err; + } + tx_rule->meta_modhdr = modify_hdr; + + flow_act.modify_hdr = modify_hdr; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + + dest.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; + dest.ft = tx_fs->tables.ft_crypto.t; + new_rule = mlx5_add_flow_rules(tx_fs->ft_rdma_tx, spec, &flow_act, &dest, 1); + if (IS_ERR(new_rule)) { + err = PTR_ERR(new_rule); + mlx5_core_err(mdev, "Failed to add ROCE TX rule, err=%d\n", err); + goto rule_err; + } + tx_rule->rule = new_rule; + tx_rule->gid_idx = gid_idx; + tx_rule->fs_id = fs_id; + list_add_tail(&tx_rule->entry, tx_rules_list); + + goto out; + +rule_err: + mlx5_modify_header_dealloc(mdev, tx_rule->meta_modhdr); +modify_hdr_err: + kfree(tx_rule); +out: + kvfree(spec); + return err; +} + +void mlx5_macsec_del_roce_rule(u16 gid_idx, struct mlx5_macsec_fs *macsec_fs, + struct list_head *tx_rules_list, struct list_head *rx_rules_list) +{ + struct mlx5_roce_macsec_rx_rule *rx_rule, *next_rx; + struct mlx5_roce_macsec_tx_rule *tx_rule, *next_tx; + + list_for_each_entry_safe(tx_rule, next_tx, tx_rules_list, entry) { + if (tx_rule->gid_idx == gid_idx) + macsec_fs_del_roce_rule_tx(macsec_fs->mdev, tx_rule); + } + + list_for_each_entry_safe(rx_rule, next_rx, rx_rules_list, entry) { + if (rx_rule->gid_idx == gid_idx) + macsec_fs_del_roce_rule_rx(rx_rule); + } +} +EXPORT_SYMBOL_GPL(mlx5_macsec_del_roce_rule); + +int mlx5_macsec_add_roce_rule(void *macdev, const struct sockaddr *addr, u16 gid_idx, + struct list_head *tx_rules_list, struct list_head *rx_rules_list, + struct mlx5_macsec_fs *macsec_fs) +{ + struct mlx5_macsec_device *iter, *macsec_device = NULL; + struct mlx5_core_dev *mdev = macsec_fs->mdev; + struct mlx5_fs_id *fs_id_iter; + unsigned long index = 0; + int err; + + list_for_each_entry(iter, &macsec_fs->macsec_devices_list, macsec_devices_list_entry) { + if (iter->macdev == macdev) { + macsec_device = iter; + break; + } + } + + if (!macsec_device) + return 0; + + xa_for_each(&macsec_device->tx_id_xa, index, fs_id_iter) { + err = mlx5_macsec_fs_add_roce_rule_tx(macsec_fs, fs_id_iter->id, gid_idx, addr, + tx_rules_list); + if (err) { + mlx5_core_err(mdev, "MACsec offload: Failed to add roce TX rule\n"); + goto out; + } + } + + index = 0; + xa_for_each(&macsec_device->rx_id_xa, index, fs_id_iter) { + err = mlx5_macsec_fs_add_roce_rule_rx(macsec_fs, fs_id_iter->id, gid_idx, addr, + rx_rules_list); + if (err) { + mlx5_core_err(mdev, "MACsec offload: Failed to add roce TX rule\n"); + goto out; + } + } + + return 0; +out: + mlx5_macsec_del_roce_rule(gid_idx, macsec_fs, tx_rules_list, rx_rules_list); + return err; +} +EXPORT_SYMBOL_GPL(mlx5_macsec_add_roce_rule); + +void mlx5_macsec_add_roce_sa_rules(u32 fs_id, const struct sockaddr *addr, u16 gid_idx, + struct list_head *tx_rules_list, + struct list_head *rx_rules_list, + struct mlx5_macsec_fs *macsec_fs, bool is_tx) +{ + (is_tx) ? + mlx5_macsec_fs_add_roce_rule_tx(macsec_fs, fs_id, gid_idx, addr, + tx_rules_list) : + mlx5_macsec_fs_add_roce_rule_rx(macsec_fs, fs_id, gid_idx, addr, + rx_rules_list); +} +EXPORT_SYMBOL_GPL(mlx5_macsec_add_roce_sa_rules); + +void mlx5_macsec_del_roce_sa_rules(u32 fs_id, struct mlx5_macsec_fs *macsec_fs, + struct list_head *tx_rules_list, + struct list_head *rx_rules_list, bool is_tx) +{ + (is_tx) ? + macsec_fs_del_roce_rules_tx(macsec_fs, fs_id, tx_rules_list) : + macsec_fs_del_roce_rules_rx(macsec_fs, fs_id, rx_rules_list); +} +EXPORT_SYMBOL_GPL(mlx5_macsec_del_roce_sa_rules); + void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs) { macsec_fs_rx_cleanup(macsec_fs); @@ -2015,6 +2394,8 @@ mlx5_macsec_fs_init(struct mlx5_core_dev *mdev) goto tx_cleanup; } + BLOCKING_INIT_NOTIFIER_HEAD(&mdev->macsec_nh); + return macsec_fs; tx_cleanup: -- cgit From b22eef6864caadd2199e3db0be7235c176a04f89 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 19 Aug 2023 12:11:06 +0100 Subject: net: dsa: realtek: add phylink_get_caps implementation The user ports use RSGMII, but we don't have that, and DT doesn't specify a phy interface mode, so phylib defaults to GMII. These support 1G, 100M and 10M with flow control. It is unknown whether asymetric pause is supported at all speeds. The CPU port uses MII/GMII/RGMII/REVMII by hardware pin strapping, and support speeds specific to each, with full duplex only supported in some modes. Flow control may be supported again by hardware pin strapping, and theoretically is readable through a register but no information is given in the datasheet for that. So, we do a best efforts - and be lenient. Signed-off-by: Russell King (Oracle) Reviewed-by: Vladimir Oltean Reviewed-by: Linus Walleij Signed-off-by: David S. Miller --- drivers/net/dsa/realtek/rtl8366rb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c index 25f88022b9e4..7868ef237f6c 100644 --- a/drivers/net/dsa/realtek/rtl8366rb.c +++ b/drivers/net/dsa/realtek/rtl8366rb.c @@ -1049,6 +1049,32 @@ static enum dsa_tag_protocol rtl8366_get_tag_protocol(struct dsa_switch *ds, return DSA_TAG_PROTO_RTL4_A; } +static void rtl8366rb_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + unsigned long *interfaces = config->supported_interfaces; + struct realtek_priv *priv = ds->priv; + + if (port == priv->cpu_port) { + __set_bit(PHY_INTERFACE_MODE_MII, interfaces); + __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); + /* REVMII only supports 100M FD */ + __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); + /* RGMII only supports 1G FD */ + phy_interface_set_rgmii(interfaces); + + config->mac_capabilities = MAC_1000 | MAC_100 | + MAC_SYM_PAUSE; + } else { + /* RSGMII port, but we don't have that, and we don't + * specify in DT, so phylib uses the default of GMII + */ + __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); + config->mac_capabilities = MAC_1000 | MAC_100 | MAC_10 | + MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + } +} + static void rtl8366rb_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface, struct phy_device *phydev, @@ -1796,6 +1822,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv) static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = { .get_tag_protocol = rtl8366_get_tag_protocol, .setup = rtl8366rb_setup, + .phylink_get_caps = rtl8366rb_phylink_get_caps, .phylink_mac_link_up = rtl8366rb_mac_link_up, .phylink_mac_link_down = rtl8366rb_mac_link_down, .get_strings = rtl8366_get_strings, @@ -1821,6 +1848,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = { .setup = rtl8366rb_setup, .phy_read = rtl8366rb_dsa_phy_read, .phy_write = rtl8366rb_dsa_phy_write, + .phylink_get_caps = rtl8366rb_phylink_get_caps, .phylink_mac_link_up = rtl8366rb_mac_link_up, .phylink_mac_link_down = rtl8366rb_mac_link_down, .get_strings = rtl8366_get_strings, -- cgit From d6499f0b7c7ce3d69f658331e78e520c7ebcb238 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 15:07:05 +0800 Subject: net: bgmac: Return PTR_ERR() for fixed_phy_register() fixed_phy_register() returns -EPROBE_DEFER, -EINVAL and -EBUSY, etc, in addition to -ENODEV. The best practice is to return these error codes with PTR_ERR(). Signed-off-by: Ruan Jinjie Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 10c7c232cc4e..7c19ba58e9cc 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1450,7 +1450,7 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac) phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (!phy_dev || IS_ERR(phy_dev)) { dev_err(bgmac->dev, "Failed to register fixed PHY device\n"); - return -ENODEV; + return PTR_ERR(phy_dev); } err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link, -- cgit From acf50d1adbf440a01fc9cca16e80dde3da3eccab Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 15:07:06 +0800 Subject: net: bcmgenet: Return PTR_ERR() for fixed_phy_register() fixed_phy_register() returns -EPROBE_DEFER, -EINVAL and -EBUSY, etc, in addition to -ENODEV. The Best practice is to return these error codes with PTR_ERR(). Signed-off-by: Ruan Jinjie Acked-by: Doug Berger Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 0092e46c46f8..4012a141a229 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -619,7 +619,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (!phydev || IS_ERR(phydev)) { dev_err(kdev, "failed to register fixed PHY device\n"); - return -ENODEV; + return PTR_ERR(phydev); } /* Make sure we initialize MoCA PHYs with a link down */ -- cgit From 294f48e9b234415cbd8cc4e233d5fbd41e961148 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Fri, 18 Aug 2023 15:07:07 +0800 Subject: net: lan743x: Return PTR_ERR() for fixed_phy_register() fixed_phy_register() returns -EPROBE_DEFER, -EINVAL and -EBUSY, etc, in addition to -EIO. The Best practice is to return these error codes with PTR_ERR(). Signed-off-by: Ruan Jinjie Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan743x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index a36f6369f132..c81cdeb4d4e7 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1515,7 +1515,7 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter) &fphy_status, NULL); if (IS_ERR(phydev)) { netdev_err(netdev, "No PHY/fixed_PHY found\n"); - return -EIO; + return PTR_ERR(phydev); } } else { goto return_error; -- cgit From 669a55560e4b8fad3598d544d062ab40fd860bcb Mon Sep 17 00:00:00 2001 From: Furong Xu <0x1207@gmail.com> Date: Sat, 19 Aug 2023 18:54:40 +0800 Subject: net: stmmac: Check more MAC HW features for XGMAC Core 3.20 1. XGMAC Core does not have hash_filter definition, it uses vlhash(VLAN Hash Filtering) instead, skip hash_filter when XGMAC. 2. Show exact size of Hash Table instead of raw register value. 3. Show full description of safety features defined by Synopsys Databook. 4. When safety feature is configured with no parity, or ECC only, keep FSM Parity Checking disabled. Signed-off-by: Furong Xu <0x1207@gmail.com> Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 36 +++++++++++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 21 +++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 6 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 23 +++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 71 ++++++++++++++++++++-- 5 files changed, 149 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 1f5293c8cc04..403cb397d4d3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -410,6 +410,18 @@ struct dma_features { unsigned int number_tx_queues; /* PPS output */ unsigned int pps_out_num; + /* Number of Traffic Classes */ + unsigned int numtc; + /* DCB Feature Enable */ + unsigned int dcben; + /* IEEE 1588 High Word Register Enable */ + unsigned int advthword; + /* PTP Offload Enable */ + unsigned int ptoen; + /* One-Step Timestamping Enable */ + unsigned int osten; + /* Priority-Based Flow Control Enable */ + unsigned int pfcen; /* Alternate (enhanced) DESC mode */ unsigned int enh_desc; /* TX and RX FIFO sizes */ @@ -430,16 +442,40 @@ struct dma_features { unsigned int dvlan; unsigned int l3l4fnum; unsigned int arpoffsel; + /* One Step for PTP over UDP/IP Feature Enable */ + unsigned int pou_ost_en; + /* Tx Timestamp FIFO Depth */ + unsigned int ttsfd; + /* Queue/Channel-Based VLAN tag insertion on Tx */ + unsigned int cbtisel; + /* Supported Parallel Instruction Processor Engines */ + unsigned int frppipe_num; + /* Number of Extended VLAN Tag Filters */ + unsigned int nrvf_num; /* TSN Features */ unsigned int estwid; unsigned int estdep; unsigned int estsel; unsigned int fpesel; unsigned int tbssel; + /* Number of DMA channels enabled for TBS */ + unsigned int tbs_ch_num; + /* Per-Stream Filtering Enable */ + unsigned int sgfsel; /* Numbers of Auxiliary Snapshot Inputs */ unsigned int aux_snapshot_n; /* Timestamp System Time Source */ unsigned int tssrc; + /* Enhanced DMA Enable */ + unsigned int edma; + /* Different Descriptor Cache Enable */ + unsigned int ediffc; + /* VxLAN/NVGRE Enable */ + unsigned int vxn; + /* Debug Memory Interface Enable */ + unsigned int dbgmem; + /* Number of Policing Counters */ + unsigned int pcsel; }; /* RX Buffer size must be multiple of 4/8/16 bytes */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 7f68bef456b7..7a8f47e7b728 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -122,6 +122,9 @@ #define XGMAC_TLPIEN BIT(0) #define XGMAC_LPI_TIMER_CTRL 0x000000d4 #define XGMAC_HW_FEATURE0 0x0000011c +#define XGMAC_HWFEAT_EDMA BIT(31) +#define XGMAC_HWFEAT_EDIFFC BIT(30) +#define XGMAC_HWFEAT_VXN BIT(29) #define XGMAC_HWFEAT_SAVLANINS BIT(27) #define XGMAC_HWFEAT_TSSTSSEL GENMASK(26, 25) #define XGMAC_HWFEAT_ADDMACADRSEL GENMASK(22, 18) @@ -142,29 +145,47 @@ #define XGMAC_HW_FEATURE1 0x00000120 #define XGMAC_HWFEAT_L3L4FNUM GENMASK(30, 27) #define XGMAC_HWFEAT_HASHTBLSZ GENMASK(25, 24) +#define XGMAC_HWFEAT_NUMTC GENMASK(23, 21) #define XGMAC_HWFEAT_RSSEN BIT(20) +#define XGMAC_HWFEAT_DBGMEMA BIT(19) #define XGMAC_HWFEAT_TSOEN BIT(18) #define XGMAC_HWFEAT_SPHEN BIT(17) +#define XGMAC_HWFEAT_DCBEN BIT(16) #define XGMAC_HWFEAT_ADDR64 GENMASK(15, 14) +#define XGMAC_HWFEAT_ADVTHWORD BIT(13) +#define XGMAC_HWFEAT_PTOEN BIT(12) +#define XGMAC_HWFEAT_OSTEN BIT(11) #define XGMAC_HWFEAT_TXFIFOSIZE GENMASK(10, 6) +#define XGMAC_HWFEAT_PFCEN BIT(5) #define XGMAC_HWFEAT_RXFIFOSIZE GENMASK(4, 0) #define XGMAC_HW_FEATURE2 0x00000124 +#define XGMAC_HWFEAT_AUXSNAPNUM GENMASK(30, 28) #define XGMAC_HWFEAT_PPSOUTNUM GENMASK(26, 24) #define XGMAC_HWFEAT_TXCHCNT GENMASK(21, 18) #define XGMAC_HWFEAT_RXCHCNT GENMASK(15, 12) #define XGMAC_HWFEAT_TXQCNT GENMASK(9, 6) #define XGMAC_HWFEAT_RXQCNT GENMASK(3, 0) #define XGMAC_HW_FEATURE3 0x00000128 +#define XGMAC_HWFEAT_TBSCH GENMASK(31, 28) #define XGMAC_HWFEAT_TBSSEL BIT(27) #define XGMAC_HWFEAT_FPESEL BIT(26) +#define XGMAC_HWFEAT_SGFSEL BIT(25) #define XGMAC_HWFEAT_ESTWID GENMASK(24, 23) #define XGMAC_HWFEAT_ESTDEP GENMASK(22, 20) #define XGMAC_HWFEAT_ESTSEL BIT(19) +#define XGMAC_HWFEAT_TTSFD GENMASK(18, 16) #define XGMAC_HWFEAT_ASP GENMASK(15, 14) #define XGMAC_HWFEAT_DVLAN BIT(13) #define XGMAC_HWFEAT_FRPES GENMASK(12, 11) #define XGMAC_HWFEAT_FRPPB GENMASK(10, 9) +#define XGMAC_HWFEAT_POUOST BIT(8) +#define XGMAC_HWFEAT_FRPPIPE GENMASK(7, 5) +#define XGMAC_HWFEAT_CBTISEL BIT(4) #define XGMAC_HWFEAT_FRPSEL BIT(3) +#define XGMAC_HWFEAT_NRVF GENMASK(2, 0) +#define XGMAC_HW_FEATURE4 0x0000012c +#define XGMAC_HWFEAT_EASP BIT(4) +#define XGMAC_HWFEAT_PCSEL GENMASK(1, 0) #define XGMAC_MAC_DPP_FSM_INT_STATUS 0x00000150 #define XGMAC_MAC_FSM_CONTROL 0x00000158 #define XGMAC_PRTYEN BIT(1) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 38782662ff98..34e1b0c3f346 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -861,8 +861,10 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp, value |= XGMAC_TCEIE; /* TSO Memory Correctable Error */ writel(value, ioaddr + XGMAC_DMA_ECC_INT_ENABLE); - /* Only ECC Protection for External Memory feature is selected */ - if (asp <= 0x1) + /* 0x2: Without ECC or Parity Ports on External Application Interface + * 0x4: Only ECC Protection for External Memory feature is selected + */ + if (asp == 0x2 || asp == 0x4) return 0; /* 4. Enable Parity and Timeout for FSM */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 3aacf791efeb..fa69d64a8694 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -393,6 +393,9 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature 0 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); + dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; + dma_cap->ediffc = (hw_cap & XGMAC_HWFEAT_EDIFFC) >> 30; + dma_cap->vxn = (hw_cap & XGMAC_HWFEAT_VXN) >> 29; dma_cap->vlins = (hw_cap & XGMAC_HWFEAT_SAVLANINS) >> 27; dma_cap->tssrc = (hw_cap & XGMAC_HWFEAT_TSSTSSEL) >> 25; dma_cap->multi_addr = (hw_cap & XGMAC_HWFEAT_ADDMACADRSEL) >> 18; @@ -425,9 +428,12 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->l3l4fnum = 32; dma_cap->hash_tb_sz = (hw_cap & XGMAC_HWFEAT_HASHTBLSZ) >> 24; + dma_cap->numtc = ((hw_cap & XGMAC_HWFEAT_NUMTC) >> 21) + 1; dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20; + dma_cap->dbgmem = (hw_cap & XGMAC_HWFEAT_DBGMEMA) >> 19; dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18; dma_cap->sphen = (hw_cap & XGMAC_HWFEAT_SPHEN) >> 17; + dma_cap->dcben = (hw_cap & XGMAC_HWFEAT_DCBEN) >> 16; dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14; switch (dma_cap->addr64) { @@ -445,13 +451,18 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, break; } + dma_cap->advthword = (hw_cap & XGMAC_HWFEAT_ADVTHWORD) >> 13; + dma_cap->ptoen = (hw_cap & XGMAC_HWFEAT_PTOEN) >> 12; + dma_cap->osten = (hw_cap & XGMAC_HWFEAT_OSTEN) >> 11; dma_cap->tx_fifo_size = 128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6); + dma_cap->pfcen = (hw_cap & XGMAC_HWFEAT_PFCEN) >> 5; dma_cap->rx_fifo_size = 128 << ((hw_cap & XGMAC_HWFEAT_RXFIFOSIZE) >> 0); /* MAC HW feature 2 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE2); + dma_cap->aux_snapshot_n = (hw_cap & XGMAC_HWFEAT_AUXSNAPNUM) >> 28; dma_cap->pps_out_num = (hw_cap & XGMAC_HWFEAT_PPSOUTNUM) >> 24; dma_cap->number_tx_channel = ((hw_cap & XGMAC_HWFEAT_TXCHCNT) >> 18) + 1; @@ -464,16 +475,28 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, /* MAC HW feature 3 */ hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3); + dma_cap->tbs_ch_num = ((hw_cap & XGMAC_HWFEAT_TBSCH) >> 28) + 1; dma_cap->tbssel = (hw_cap & XGMAC_HWFEAT_TBSSEL) >> 27; dma_cap->fpesel = (hw_cap & XGMAC_HWFEAT_FPESEL) >> 26; + dma_cap->sgfsel = (hw_cap & XGMAC_HWFEAT_SGFSEL) >> 25; dma_cap->estwid = (hw_cap & XGMAC_HWFEAT_ESTWID) >> 23; dma_cap->estdep = (hw_cap & XGMAC_HWFEAT_ESTDEP) >> 20; dma_cap->estsel = (hw_cap & XGMAC_HWFEAT_ESTSEL) >> 19; + dma_cap->ttsfd = (hw_cap & XGMAC_HWFEAT_TTSFD) >> 16; dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14; dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13; dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11; dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9; + dma_cap->pou_ost_en = (hw_cap & XGMAC_HWFEAT_POUOST) >> 8; + dma_cap->frppipe_num = ((hw_cap & XGMAC_HWFEAT_FRPPIPE) >> 5) + 1; + dma_cap->cbtisel = (hw_cap & XGMAC_HWFEAT_CBTISEL) >> 4; dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3; + dma_cap->nrvf_num = (hw_cap & XGMAC_HWFEAT_NRVF) >> 0; + + /* MAC HW feature 4 */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE4); + dma_cap->asp |= (hw_cap & XGMAC_HWFEAT_EASP) >> 2; + dma_cap->pcsel = (hw_cap & XGMAC_HWFEAT_PCSEL) >> 0; return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 733b5e900817..7a9bbcf03ea5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6243,6 +6243,16 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) "External", "Both", }; + static const char * const dwxgmac_safety_feature_desc[] = { + "No", + "All Safety Features with ECC and Parity", + "All Safety Features without ECC or Parity", + "All Safety Features with Parity Only", + "ECC Only", + "UNDEFINED", + "UNDEFINED", + "UNDEFINED", + }; struct net_device *dev = seq->private; struct stmmac_priv *priv = netdev_priv(dev); @@ -6261,15 +6271,16 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) (priv->dma_cap.mbps_1000) ? "Y" : "N"); seq_printf(seq, "\tHalf duplex: %s\n", (priv->dma_cap.half_duplex) ? "Y" : "N"); - seq_printf(seq, "\tHash Filter: %s\n", - (priv->dma_cap.hash_filter) ? "Y" : "N"); - if (priv->plat->has_xgmac) + if (priv->plat->has_xgmac) { seq_printf(seq, "\tNumber of Additional MAC address registers: %d\n", priv->dma_cap.multi_addr); - else + } else { + seq_printf(seq, "\tHash Filter: %s\n", + (priv->dma_cap.hash_filter) ? "Y" : "N"); seq_printf(seq, "\tMultiple MAC address registers: %s\n", (priv->dma_cap.multi_addr) ? "Y" : "N"); + } seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n", (priv->dma_cap.pcs) ? "Y" : "N"); seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", @@ -6316,12 +6327,13 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) (priv->dma_cap.enh_desc) ? "Y" : "N"); seq_printf(seq, "\tTX Fifo Size: %d\n", priv->dma_cap.tx_fifo_size); seq_printf(seq, "\tRX Fifo Size: %d\n", priv->dma_cap.rx_fifo_size); - seq_printf(seq, "\tHash Table Size: %d\n", priv->dma_cap.hash_tb_sz); + seq_printf(seq, "\tHash Table Size: %lu\n", priv->dma_cap.hash_tb_sz ? + (BIT(priv->dma_cap.hash_tb_sz) << 5) : 0); seq_printf(seq, "\tTSO: %s\n", priv->dma_cap.tsoen ? "Y" : "N"); seq_printf(seq, "\tNumber of PPS Outputs: %d\n", priv->dma_cap.pps_out_num); seq_printf(seq, "\tSafety Features: %s\n", - priv->dma_cap.asp ? "Y" : "N"); + dwxgmac_safety_feature_desc[priv->dma_cap.asp]); seq_printf(seq, "\tFlexible RX Parser: %s\n", priv->dma_cap.frpsel ? "Y" : "N"); seq_printf(seq, "\tEnhanced Addressing: %d\n", @@ -6346,6 +6358,53 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) priv->dma_cap.fpesel ? "Y" : "N"); seq_printf(seq, "\tTime-Based Scheduling (TBS): %s\n", priv->dma_cap.tbssel ? "Y" : "N"); + seq_printf(seq, "\tNumber of DMA Channels Enabled for TBS: %d\n", + priv->dma_cap.tbs_ch_num); + seq_printf(seq, "\tPer-Stream Filtering: %s\n", + priv->dma_cap.sgfsel ? "Y" : "N"); + seq_printf(seq, "\tTX Timestamp FIFO Depth: %lu\n", + BIT(priv->dma_cap.ttsfd) >> 1); + seq_printf(seq, "\tNumber of Traffic Classes: %d\n", + priv->dma_cap.numtc); + seq_printf(seq, "\tDCB Feature: %s\n", + priv->dma_cap.dcben ? "Y" : "N"); + seq_printf(seq, "\tIEEE 1588 High Word Register: %s\n", + priv->dma_cap.advthword ? "Y" : "N"); + seq_printf(seq, "\tPTP Offload: %s\n", + priv->dma_cap.ptoen ? "Y" : "N"); + seq_printf(seq, "\tOne-Step Timestamping: %s\n", + priv->dma_cap.osten ? "Y" : "N"); + seq_printf(seq, "\tPriority-Based Flow Control: %s\n", + priv->dma_cap.pfcen ? "Y" : "N"); + seq_printf(seq, "\tNumber of Flexible RX Parser Instructions: %lu\n", + BIT(priv->dma_cap.frpes) << 6); + seq_printf(seq, "\tNumber of Flexible RX Parser Parsable Bytes: %lu\n", + BIT(priv->dma_cap.frpbs) << 6); + seq_printf(seq, "\tParallel Instruction Processor Engines: %d\n", + priv->dma_cap.frppipe_num); + seq_printf(seq, "\tNumber of Extended VLAN Tag Filters: %lu\n", + priv->dma_cap.nrvf_num ? + (BIT(priv->dma_cap.nrvf_num) << 1) : 0); + seq_printf(seq, "\tWidth of the Time Interval Field in GCL: %d\n", + priv->dma_cap.estwid ? 4 * priv->dma_cap.estwid + 12 : 0); + seq_printf(seq, "\tDepth of GCL: %lu\n", + priv->dma_cap.estdep ? (BIT(priv->dma_cap.estdep) << 5) : 0); + seq_printf(seq, "\tQueue/Channel-Based VLAN Tag Insertion on TX: %s\n", + priv->dma_cap.cbtisel ? "Y" : "N"); + seq_printf(seq, "\tNumber of Auxiliary Snapshot Inputs: %d\n", + priv->dma_cap.aux_snapshot_n); + seq_printf(seq, "\tOne-Step Timestamping for PTP over UDP/IP: %s\n", + priv->dma_cap.pou_ost_en ? "Y" : "N"); + seq_printf(seq, "\tEnhanced DMA: %s\n", + priv->dma_cap.edma ? "Y" : "N"); + seq_printf(seq, "\tDifferent Descriptor Cache: %s\n", + priv->dma_cap.ediffc ? "Y" : "N"); + seq_printf(seq, "\tVxLAN/NVGRE: %s\n", + priv->dma_cap.vxn ? "Y" : "N"); + seq_printf(seq, "\tDebug Memory Interface: %s\n", + priv->dma_cap.dbgmem ? "Y" : "N"); + seq_printf(seq, "\tNumber of Policing Counters: %lu\n", + priv->dma_cap.pcsel ? BIT(priv->dma_cap.pcsel + 3) : 0); return 0; } DEFINE_SHOW_ATTRIBUTE(stmmac_dma_cap); -- cgit From cb39c35783f26892bb1a72b1115c94fa2e77f4c5 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Mon, 21 Aug 2023 09:55:37 +0800 Subject: pds_core: Fix some kernel-doc comments Fix some kernel-doc comments to silence the warnings: drivers/net/ethernet/amd/pds_core/auxbus.c:18: warning: Function parameter or member 'pf' not described in 'pds_client_register' drivers/net/ethernet/amd/pds_core/auxbus.c:18: warning: Excess function parameter 'pf_pdev' description in 'pds_client_register' drivers/net/ethernet/amd/pds_core/auxbus.c:58: warning: Function parameter or member 'pf' not described in 'pds_client_unregister' drivers/net/ethernet/amd/pds_core/auxbus.c:58: warning: Excess function parameter 'pf_pdev' description in 'pds_client_unregister' Signed-off-by: Yang Li Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/pds_core/auxbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c index 6787a5fae908..f46efebaaea9 100644 --- a/drivers/net/ethernet/amd/pds_core/auxbus.c +++ b/drivers/net/ethernet/amd/pds_core/auxbus.c @@ -8,7 +8,7 @@ /** * pds_client_register - Link the client to the firmware - * @pf_pdev: ptr to the PF driver struct + * @pf: a pointer to the pdsc structure * @devname: name that includes service into, e.g. pds_core.vDPA * * Return: positive client ID (ci) on success, or @@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(pds_client_register); /** * pds_client_unregister - Unlink the client from the firmware - * @pf_pdev: ptr to the PF driver struct + * @pf: a pointer to the pdsc structure * @client_id: id returned from pds_client_register() * * Return: 0 on success, or -- cgit From 9c8fd72a5c2a031cbc680a2990107ecd958ffcdb Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 19:07:15 +0300 Subject: wifi: mwifiex: fix memory leak in mwifiex_histogram_read() Always free the zeroed page on return from 'mwifiex_histogram_read()'. Fixes: cbf6e05527a7 ("mwifiex: add rx histogram statistics support") Acked-by: Brian Norris Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802160726.85545-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/debugfs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 52b18f4a774b..0cdd6c50c1c0 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -253,8 +253,11 @@ mwifiex_histogram_read(struct file *file, char __user *ubuf, if (!p) return -ENOMEM; - if (!priv || !priv->hist_data) - return -EFAULT; + if (!priv || !priv->hist_data) { + ret = -EFAULT; + goto free_and_exit; + } + phist_data = priv->hist_data; p += sprintf(p, "\n" @@ -309,6 +312,8 @@ mwifiex_histogram_read(struct file *file, char __user *ubuf, ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page, (unsigned long)p - page); +free_and_exit: + free_page(page); return ret; } -- cgit From 9b1cd8266f350c4e8453361c6e183e6174d63e4b Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 19:07:16 +0300 Subject: wifi: mwifiex: cleanup private data structures Drop unused fields 'status_code' of 'struct mwifiex_txinfo', 'dfs_chan_switch_timer', 'sleep_params' (including related data type 'struct mwifiex_sleep_params') of 'struct mwifiex_adapter', adjust related code. Acked-by: Brian Norris Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802160726.85545-2-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/decl.h | 1 - drivers/net/wireless/marvell/mwifiex/init.c | 1 - drivers/net/wireless/marvell/mwifiex/main.h | 11 ----------- drivers/net/wireless/marvell/mwifiex/sta_tx.c | 1 - drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 1 - 5 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index 88648c062713..326ffb05d791 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -180,7 +180,6 @@ struct mwifiex_rxinfo { }; struct mwifiex_txinfo { - u32 status_code; u8 flags; u8 bss_num; u8 bss_type; diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 7dddb4b5dea1..86293be782a2 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -282,7 +282,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); - memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); adapter->tx_lock_flag = false; adapter->null_pkt_interval = 0; diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index b95886e1413e..7421e9bf8650 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -444,15 +444,6 @@ struct mwifiex_current_bss_params { u8 data_rates[MWIFIEX_SUPPORTED_RATES]; }; -struct mwifiex_sleep_params { - u16 sp_error; - u16 sp_offset; - u16 sp_stable_time; - u8 sp_cal_control; - u8 sp_ext_sleep_clk; - u16 sp_reserved; -}; - struct mwifiex_sleep_period { u16 period; u16 reserved; @@ -681,7 +672,6 @@ struct mwifiex_private { struct cfg80211_chan_def dfs_chandef; struct workqueue_struct *dfs_cac_workqueue; struct delayed_work dfs_cac_work; - struct timer_list dfs_chan_switch_timer; struct workqueue_struct *dfs_chan_sw_workqueue; struct delayed_work dfs_chan_sw_work; struct cfg80211_beacon_data beacon_after; @@ -955,7 +945,6 @@ struct mwifiex_adapter { u8 config_bands; struct mwifiex_chan_scan_param_set *scan_channels; u8 tx_lock_flag; - struct mwifiex_sleep_params sleep_params; struct mwifiex_sleep_period sleep_period; u16 ps_mode; u32 ps_state; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c index 13c0e67ededf..d27b6e6493f3 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c @@ -42,7 +42,6 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, if (!skb->len) { mwifiex_dbg(adapter, ERROR, "Tx: bad packet length: %d\n", skb->len); - tx_info->status_code = -1; return skb->data; } diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 04ff051f5d18..360d36ceeb1d 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -474,7 +474,6 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, if (!skb->len) { mwifiex_dbg(adapter, ERROR, "Tx: bad packet length: %d\n", skb->len); - tx_info->status_code = -1; return skb->data; } -- cgit From 968d02c61311221deb881634d15f191effa1ab22 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 19:07:17 +0300 Subject: wifi: mwifiex: handle possible sscanf() errors Return -EINVAL on possible 'sscanf()' errors in 'mwifiex_regrdwr_write()' and 'mwifiex_rdeeprom_write()'. Found by Linux Verification Center (linuxtesting.org) with SVACE. Acked-by: Brian Norris Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802160726.85545-3-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/debugfs.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 0cdd6c50c1c0..f9c9fec7c792 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -425,7 +425,10 @@ mwifiex_regrdwr_write(struct file *file, if (IS_ERR(buf)) return PTR_ERR(buf); - sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); + if (sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value) != 3) { + ret = -EINVAL; + goto done; + } if (reg_type == 0 || reg_offset == 0) { ret = -EINVAL; @@ -691,7 +694,10 @@ mwifiex_rdeeprom_write(struct file *file, if (IS_ERR(buf)) return PTR_ERR(buf); - sscanf(buf, "%d %d", &offset, &bytes); + if (sscanf(buf, "%d %d", &offset, &bytes) != 2) { + ret = -EINVAL; + goto done; + } if (offset == -1 || bytes == -1) { ret = -EINVAL; -- cgit From a6b3a0169ade026b257be58f9295f5eec7edd359 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 19:07:18 +0300 Subject: wifi: mwifiex: handle possible mwifiex_write_reg() errors Return -1 on possible 'mwifiex_write_reg()' errors in 'mwifiex_init_sdio_ioport()', do not ignore the value returned by the latter in 'mwifiex_init_sdio()' and 'mwifiex_sdio_up_dev()' as well. Found by Linux Verification Center (linuxtesting.org) with SVACE. Acked-by: Brian Norris Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802160726.85545-4-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/sdio.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index a24bd40dd41a..0d60484cd5df 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1083,17 +1083,17 @@ cont: "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); /* Set Host interrupt reset to read to clear */ - if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, ®)) - mwifiex_write_reg(adapter, card->reg->host_int_rsr_reg, - reg | card->reg->sdio_int_mask); - else + if (mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, ®)) + return -1; + if (mwifiex_write_reg(adapter, card->reg->host_int_rsr_reg, + reg | card->reg->sdio_int_mask)) return -1; /* Dnld/Upld ready set to auto reset */ - if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®)) - mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg, - reg | AUTO_RE_ENABLE_INT); - else + if (mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®)) + return -1; + if (mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg, + reg | AUTO_RE_ENABLE_INT)) return -1; return 0; @@ -2525,7 +2525,8 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); /* Get SDIO ioport */ - mwifiex_init_sdio_ioport(adapter); + if (mwifiex_init_sdio_ioport(adapter)) + return -EIO; /* Initialize SDIO variables in card */ card->mp_rd_bitmap = 0; @@ -3141,7 +3142,8 @@ static void mwifiex_sdio_up_dev(struct mwifiex_adapter *adapter) */ mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); - mwifiex_init_sdio_ioport(adapter); + if (mwifiex_init_sdio_ioport(adapter)) + dev_err(&card->func->dev, "error enabling SDIO port\n"); } static struct mwifiex_if_ops sdio_ops = { -- cgit From 359838758ceaabeadec2aab7a4ae1c8c89372c21 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 2 Aug 2023 19:07:19 +0300 Subject: wifi: mwifiex: drop BUG_ON from TX paths In 'mwifiex_process_sta_txpd()' and 'mwifiex_process_uap_txpd()', replace 'BUG_ON()' with runtime check, and move all these checks to 'mwifiex_process_tx()'. This way, both callees may be converted to 'void', and the caller may be simplified as well. Suggested-by: Brian Norris Signed-off-by: Dmitry Antipov Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802160726.85545-5-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/main.h | 6 ++-- drivers/net/wireless/marvell/mwifiex/sta_tx.c | 14 ++------ drivers/net/wireless/marvell/mwifiex/txrx.c | 44 +++++++++++++++---------- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 14 ++------ 4 files changed, 34 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 7421e9bf8650..97e7c835d729 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1144,8 +1144,10 @@ int mwifiex_process_uap_event(struct mwifiex_private *); void mwifiex_delete_all_station_list(struct mwifiex_private *priv); void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr); -void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); -void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); +void mwifiex_process_sta_txpd(struct mwifiex_private *priv, + struct sk_buff *skb); +void mwifiex_process_uap_txpd(struct mwifiex_private *priv, + struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init); int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, struct mwifiex_scan_cmd_config *scan_cfg); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c index d27b6e6493f3..70c2790b8e35 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c @@ -29,8 +29,8 @@ * - Priority specific Tx control * - Flags */ -void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) +void mwifiex_process_sta_txpd(struct mwifiex_private *priv, + struct sk_buff *skb) { struct mwifiex_adapter *adapter = priv->adapter; struct txpd *local_tx_pd; @@ -39,14 +39,6 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, u16 pkt_type, pkt_offset; int hroom = adapter->intf_hdr_len; - if (!skb->len) { - mwifiex_dbg(adapter, ERROR, - "Tx: bad packet length: %d\n", skb->len); - return skb->data; - } - - BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN); - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; pad = ((uintptr_t)skb->data - (sizeof(*local_tx_pd) + hroom)) & @@ -108,8 +100,6 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, if (!local_tx_pd->tx_control) /* TxCtrl set by user or default */ local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - return skb->data; } /* diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c index 54c204608dab..bd91678d26b4 100644 --- a/drivers/net/wireless/marvell/mwifiex/txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/txrx.c @@ -72,13 +72,18 @@ EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, struct mwifiex_tx_param *tx_param) { - int hroom, ret = -1; + int hroom, ret; struct mwifiex_adapter *adapter = priv->adapter; - u8 *head_ptr; struct txpd *local_tx_pd = NULL; struct mwifiex_sta_node *dest_node; struct ethhdr *hdr = (void *)skb->data; + if (unlikely(!skb->len || + skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN)) { + ret = -EINVAL; + goto out; + } + hroom = adapter->intf_hdr_len; if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { @@ -88,33 +93,31 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, dest_node->stats.tx_packets++; } - head_ptr = mwifiex_process_uap_txpd(priv, skb); + mwifiex_process_uap_txpd(priv, skb); } else { - head_ptr = mwifiex_process_sta_txpd(priv, skb); + mwifiex_process_sta_txpd(priv, skb); } - if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { + if (adapter->data_sent || adapter->tx_lock_flag) { skb_queue_tail(&adapter->tx_data_q, skb); atomic_inc(&adapter->tx_queued); return 0; } - if (head_ptr) { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - local_tx_pd = (struct txpd *)(head_ptr + hroom); - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, - priv->usb_port, - skb, tx_param); - } else { - ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_TYPE_DATA, - skb, tx_param); - } + if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) + local_tx_pd = (struct txpd *)(skb->data + hroom); + if (adapter->iface_type == MWIFIEX_USB) { + ret = adapter->if_ops.host_to_card(adapter, + priv->usb_port, + skb, tx_param); + } else { + ret = adapter->if_ops.host_to_card(adapter, + MWIFIEX_TYPE_DATA, + skb, tx_param); } mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data, min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN)); - +out: switch (ret) { case -ENOSR: mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n"); @@ -137,6 +140,11 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, break; case -EINPROGRESS: break; + case -EINVAL: + mwifiex_dbg(adapter, ERROR, + "malformed skb (length: %u, headroom: %u)\n", + skb->len, skb_headroom(skb)); + fallthrough; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); break; diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 360d36ceeb1d..caff442399f3 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -461,8 +461,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, * - Priority specific Tx control * - Flags */ -void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) +void mwifiex_process_uap_txpd(struct mwifiex_private *priv, + struct sk_buff *skb) { struct mwifiex_adapter *adapter = priv->adapter; struct uap_txpd *txpd; @@ -471,14 +471,6 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, u16 pkt_type, pkt_offset; int hroom = adapter->intf_hdr_len; - if (!skb->len) { - mwifiex_dbg(adapter, ERROR, - "Tx: bad packet length: %d\n", skb->len); - return skb->data; - } - - BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN); - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; pad = ((uintptr_t)skb->data - (sizeof(*txpd) + hroom)) & @@ -526,6 +518,4 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, if (!txpd->tx_control) /* TxCtrl set by user or default */ txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - return skb->data; } -- cgit From a9be18642ad6561e3313de2c7870b226f451d495 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Tue, 8 Aug 2023 16:10:23 +0800 Subject: wifi: mwifiex: use is_zero_ether_addr() instead of ether_addr_equal() Use is_zero_ether_addr() instead of ether_addr_equal() to check if the ethernet address is all zeros. Signed-off-by: Ruan Jinjie Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230808081023.2303423-1-ruanjinjie@huawei.com --- drivers/net/wireless/marvell/mwifiex/scan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 644b1e134b01..fb3105a76337 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -828,7 +828,6 @@ mwifiex_config_scan(struct mwifiex_private *priv, u8 ssid_filter; struct mwifiex_ie_types_htcap *ht_cap; struct mwifiex_ie_types_bss_mode *bss_mode; - const u8 zero_mac[6] = {0, 0, 0, 0, 0, 0}; /* The tlv_buf_len is calculated for each scan command. The TLVs added in this routine will be preserved since the routine that sends the @@ -966,7 +965,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, sizeof(struct mwifiex_ie_types_scan_chan_gap); } - if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) { + if (!is_zero_ether_addr(user_scan_in->random_mac)) { random_mac_tlv = (void *)tlv_pos; random_mac_tlv->header.type = cpu_to_le16(TLV_TYPE_RANDOM_MAC); -- cgit From 2785851c627f2db05f9271f7f63661b5dbd95c4c Mon Sep 17 00:00:00 2001 From: Polaris Pi Date: Thu, 10 Aug 2023 08:39:11 +0000 Subject: wifi: mwifiex: Fix missed return in oob checks failed path Add missed return in mwifiex_uap_queue_bridged_pkt() and mwifiex_process_rx_packet(). Fixes: 119585281617 ("wifi: mwifiex: Fix OOB and integer underflow when rx packets") Signed-off-by: Polaris Pi Reported-by: Dmitry Antipov Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230810083911.3725248-1-pinkperfect2021@gmail.com --- drivers/net/wireless/marvell/mwifiex/sta_rx.c | 1 + drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index f2899d53a43f..65420ad67416 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -92,6 +92,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, skb->len, rx_pkt_off); priv->stats.rx_dropped++; dev_kfree_skb_any(skb); + return -1; } if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index caff442399f3..b9866f2e2644 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -110,6 +110,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); priv->stats.rx_dropped++; dev_kfree_skb_any(skb); + return; } if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, -- cgit From 0e6ccd25e0d09fe7b03f783a3918c2b67c55ecd5 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 14 Aug 2023 17:19:04 +0300 Subject: wifi: mwifiex: cleanup adapter data Remove unused and set but unused 'dfs_workqueue', 'dfs_work', and 'scan_channels' members of 'struct mwifiex_adapter', adjust users. Signed-off-by: Dmitry Antipov Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230814142101.60308-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/init.c | 1 - drivers/net/wireless/marvell/mwifiex/main.h | 3 --- drivers/net/wireless/marvell/mwifiex/scan.c | 4 ---- 3 files changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 86293be782a2..c9c58419c37b 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -288,7 +288,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->fw_bands = 0; adapter->config_bands = 0; adapter->adhoc_start_band = 0; - adapter->scan_channels = NULL; adapter->fw_release_number = 0; adapter->fw_cap_info = 0; memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 97e7c835d729..7bdec6c62248 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -878,8 +878,6 @@ struct mwifiex_adapter { struct work_struct main_work; struct workqueue_struct *rx_workqueue; struct work_struct rx_work; - struct workqueue_struct *dfs_workqueue; - struct work_struct dfs_work; bool rx_work_enabled; bool rx_processing; bool delay_main_work; @@ -943,7 +941,6 @@ struct mwifiex_adapter { u8 fw_bands; u8 adhoc_start_band; u8 config_bands; - struct mwifiex_chan_scan_param_set *scan_channels; u8 tx_lock_flag; struct mwifiex_sleep_period sleep_period; u16 ps_mode; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index fb3105a76337..72904c275461 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -612,7 +612,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct mwifiex_chan_scan_param_set *tmp_chan_list; - struct mwifiex_chan_scan_param_set *start_chan; u32 tlv_idx, rates_size, cmd_no; u32 total_scan_time; u32 done_early; @@ -643,7 +642,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, total_scan_time = 0; radio_type = 0; chan_tlv_out->header.len = 0; - start_chan = tmp_chan_list; done_early = false; /* @@ -750,8 +748,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out, radio_type); - priv->adapter->scan_channels = start_chan; - /* Send the scan command to the firmware with the specified cfg */ if (priv->adapter->ext_scan) -- cgit From ab55a976095e0c5396ca21a81cab95a7d2a42eee Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 14 Aug 2023 17:19:05 +0300 Subject: wifi: mwifiex: fix comment typos in SDIO module Fix comment typos around ' mwifiex_deaggr_sdio_pkt()' and 'mwifiex_host_to_card_mp_aggr()'. Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230814142101.60308-2-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 0d60484cd5df..774858cfe86f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1556,7 +1556,7 @@ done: } /* - * This function decode sdio aggreation pkt. + * This function decodes sdio aggregation pkt. * * Based on the data block size and pkt_len, * skb data will be decoded to few packets. @@ -2266,7 +2266,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, card->mpa_tx.buf_len, mport); - /* Save the last multi port tx aggreagation info to debug log */ + /* Save the last multi port tx aggregation info to debug log. */ index = adapter->dbg.last_sdio_mp_index; index = (index + 1) % MWIFIEX_DBG_SDIO_MP_NUM; adapter->dbg.last_sdio_mp_index = index; -- cgit From 87677749463463973589a85edd96b1468c9ea4ea Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Wed, 2 Aug 2023 01:23:06 +0000 Subject: wifi: ipw2x00: refactor to use kstrtoul The current implementation seems to reinvent what `kstrtoul` already does in terms of functionality and error handling. Remove uses of `simple_strtoul()` in favor of `kstrtoul()`. There is the following note at `lib/vsprintf.c:simple_strtoull()` which further backs this change: | * This function has caveats. Please use kstrtoull (or kstrtoul) instead. And here, simple_str* are explicitly deprecated [3]. This patch also removes an instance of the deprecated `strncpy` which helps [2]. Compile tested only. Link: https://lore.kernel.org/all/202308011602.3CC1C0244C@keescook/ [1] Link: https://github.com/KSPP/linux/issues/90 [2] Link: https://docs.kernel.org/process/deprecated.html#simple-strtol-simple-strtoll-simple-strtoul-simple-strtoull [3] Cc: linux-hardening@vger.kernel.org Suggested-by: Kees Cook Signed-off-by: Justin Stitt Reviewed-by: Kees Cook Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802-wifi-ipw2x00-refactor-v2-1-d33f765e9cd5@google.com --- drivers/net/wireless/intel/ipw2x00/ipw2200.c | 39 +++++++++------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index dfe0f74369e6..820100cac491 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -1176,23 +1176,20 @@ static ssize_t debug_level_show(struct device_driver *d, char *buf) static ssize_t debug_level_store(struct device_driver *d, const char *buf, size_t count) { - char *p = (char *)buf; - u32 val; + unsigned long val; - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buf) + int result = kstrtoul(buf, 0, &val); + + if (result == -EINVAL) printk(KERN_INFO DRV_NAME ": %s is not in hex or decimal form.\n", buf); + else if (result == -ERANGE) + printk(KERN_INFO DRV_NAME + ": %s has overflowed.\n", buf); else ipw_debug_level = val; - return strnlen(buf, count); + return count; } static DRIVER_ATTR_RW(debug_level); @@ -1461,25 +1458,13 @@ static ssize_t scan_age_store(struct device *d, struct device_attribute *attr, { struct ipw_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; - char buffer[] = "00000000"; - unsigned long len = - (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; - unsigned long val; - char *p = buffer; IPW_DEBUG_INFO("enter\n"); - strncpy(buffer, buf, len); - buffer[len] = 0; + unsigned long val; + int result = kstrtoul(buf, 0, &val); - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buffer) { + if (result == -EINVAL || result == -ERANGE) { IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); } else { priv->ieee->scan_age = val; @@ -1487,7 +1472,7 @@ static ssize_t scan_age_store(struct device *d, struct device_attribute *attr, } IPW_DEBUG_INFO("exit\n"); - return len; + return count; } static DEVICE_ATTR_RW(scan_age); -- cgit From b3bfc4fb1edc8136396ece2d7204c2ee5cae188d Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Thu, 3 Aug 2023 19:01:50 +0800 Subject: wifi: rtw89: 8852b: rfk: fine tune IQK parameters to improve performance on 2GHz band A few samples get bad performance on 2GHz band, so use proper IQK command code and select another group to have wider range of calibration value. Fixes: f2abe804e823 ("wifi: rtw89: 8852b: rfk: add IQK") Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803110150.8457-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c index fa018e1f499b..259df67836a0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c @@ -846,7 +846,7 @@ static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, case ID_NBTXK: rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x0); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x011); - iqk_cmd = 0x308 | (1 << (4 + path)); + iqk_cmd = 0x408 | (1 << (4 + path)); break; case ID_NBRXK: rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x1); @@ -1078,7 +1078,7 @@ static bool _iqk_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8 { struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; bool kfail; - u8 gp = 0x3; + u8 gp = 0x2; switch (iqk_info->iqk_band[path]) { case RTW89_BAND_2G: -- cgit From eb2624f55ad14634f97efbf56cb0cb815800508a Mon Sep 17 00:00:00 2001 From: Kuan-Chung Chen Date: Fri, 4 Aug 2023 13:34:58 +0800 Subject: wifi: rtw89: Introduce Time Averaged SAR (TAS) feature Time Averaged SAR (TAS) tracks the amount of transmit power over a period of time and adjusts the power accordingly. Two thresholds are used to determine when to increase or reduce transmit power: Dynamic Power Reduction (DPR) on/off. Compared to Static SAR, which has a constant transmit power, TAS can improve the user experience or range extension. TAS can be enabled through BIOS, and the driver will evaluate Realtek ACPI DSM with RTW89_ACPI_DSM_FUNC_TAS_EN to determine whether TAS should be enabled. Signed-off-by: Kuan-Chung Chen Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230804053458.31492-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 4 + drivers/net/wireless/realtek/rtw89/core.h | 18 +++ drivers/net/wireless/realtek/rtw89/debug.c | 3 + drivers/net/wireless/realtek/rtw89/reg.h | 4 + drivers/net/wireless/realtek/rtw89/sar.c | 197 +++++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/sar.h | 4 + 6 files changed, 230 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 62c21c09cf92..71eb9cfd4896 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2682,6 +2682,7 @@ static void rtw89_track_work(struct work_struct *work) rtw89_phy_tx_path_div_track(rtwdev); rtw89_phy_antdiv_track(rtwdev); rtw89_phy_ul_tb_ctrl_track(rtwdev); + rtw89_tas_track(rtwdev); if (rtwdev->lps_enabled && !rtwdev->btc.lps) rtw89_enter_lps_track(rtwdev); @@ -3496,6 +3497,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + rtw89_tas_reset(rtwdev); + ret = rtw89_hci_start(rtwdev); if (ret) { rtw89_err(rtwdev, "failed to start hci\n"); @@ -3612,6 +3615,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) rtw89_ser_init(rtwdev); rtw89_entity_init(rtwdev); + rtw89_tas_init(rtwdev); return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index fa4bbc4095ab..b5a08f90f5bd 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3690,6 +3690,23 @@ struct rtw89_sar_info { }; }; +enum rtw89_tas_state { + RTW89_TAS_STATE_DPR_OFF, + RTW89_TAS_STATE_DPR_ON, + RTW89_TAS_STATE_DPR_FORBID, +}; + +#define RTW89_TAS_MAX_WINDOW 50 +struct rtw89_tas_info { + s16 txpwr_history[RTW89_TAS_MAX_WINDOW]; + s32 total_txpwr; + u8 cur_idx; + s8 dpr_gap; + s8 delta; + enum rtw89_tas_state state; + bool enable; +}; + struct rtw89_chanctx_cfg { enum rtw89_sub_entity_idx idx; }; @@ -4365,6 +4382,7 @@ struct rtw89_dev { struct rtw89_regulatory_info regulatory; struct rtw89_sar_info sar; + struct rtw89_tas_info tas; struct rtw89_btc btc; enum rtw89_ps_mode ps_mode; diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index f1e5ac4186c2..f6f1e90c3934 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -615,6 +615,9 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v) seq_puts(m, "[SAR]\n"); rtw89_print_sar(m, rtwdev); + seq_puts(m, "[TAS]\n"); + rtw89_print_tas(m, rtwdev); + seq_puts(m, "\n[TX power byrate]\n"); ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_byr); if (ret) diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 55595fde7494..2d34b43cda3a 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -4109,6 +4109,8 @@ #define B_TXAGC_BB_OFT GENMASK(31, 16) #define B_TXAGC_BB GENMASK(31, 24) #define B_TXAGC_RF GENMASK(5, 0) +#define R_PATH0_TXPWR 0x1C78 +#define B_PATH0_TXPWR GENMASK(8, 0) #define R_S0_ADDCK 0x1E00 #define B_S0_ADDCK_I GENMASK(9, 0) #define B_S0_ADDCK_Q GENMASK(19, 10) @@ -4184,6 +4186,8 @@ #define R_TXAGC_BB_S1 0x3C60 #define B_TXAGC_BB_S1_OFT GENMASK(31, 16) #define B_TXAGC_BB_S1 GENMASK(31, 24) +#define R_PATH1_TXPWR 0x3C78 +#define B_PATH1_TXPWR GENMASK(8, 0) #define R_S1_ADDCK 0x3E00 #define B_S1_ADDCK_I GENMASK(9, 0) #define B_S1_ADDCK_Q GENMASK(19, 10) diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index dfccae81c380..fafc7a0cfe97 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -2,9 +2,16 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include "acpi.h" #include "debug.h" +#include "phy.h" +#include "reg.h" #include "sar.h" +#define RTW89_TAS_FACTOR 2 /* unit: 0.25 dBm */ +#define RTW89_TAS_DPR_GAP (1 << RTW89_TAS_FACTOR) +#define RTW89_TAS_DELTA (2 << RTW89_TAS_FACTOR) + static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev, u32 center_freq) { @@ -157,11 +164,35 @@ static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg) RTW89_SAR_TXPWR_MAC_MAX); } +static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl, + s8 cfg) +{ + const u8 fct = sar_hdl->txpwr_factor_sar; + + if (fct > RTW89_TAS_FACTOR) + return cfg << (fct - RTW89_TAS_FACTOR); + else + return cfg >> (RTW89_TAS_FACTOR - fct); +} + +static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl, + s8 cfg) +{ + const u8 fct = sar_hdl->txpwr_factor_sar; + + if (fct > RTW89_TAS_FACTOR) + return cfg >> (fct - RTW89_TAS_FACTOR); + else + return cfg << (RTW89_TAS_FACTOR - fct); +} + s8 rtw89_query_sar(struct rtw89_dev *rtwdev) { const enum rtw89_sar_sources src = rtwdev->sar.src; /* its members are protected by rtw89_sar_set_src() */ const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; + struct rtw89_tas_info *tas = &rtwdev->tas; + s8 delta; int ret; s32 cfg; u8 fct; @@ -175,6 +206,19 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev) if (ret) return RTW89_SAR_TXPWR_MAC_MAX; + if (tas->enable) { + switch (tas->state) { + case RTW89_TAS_STATE_DPR_OFF: + return RTW89_SAR_TXPWR_MAC_MAX; + case RTW89_TAS_STATE_DPR_ON: + delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta); + cfg -= delta; + case RTW89_TAS_STATE_DPR_FORBID: + default: + break; + } + } + fct = sar_hdl->txpwr_factor_sar; return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg); @@ -212,6 +256,19 @@ void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev) seq_printf(m, "config: %d (unit: 1/%lu dBm)\n", cfg, BIT(fct)); } +void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev) +{ + struct rtw89_tas_info *tas = &rtwdev->tas; + + if (!tas->enable) { + seq_puts(m, "no TAS is applied\n"); + return; + } + + seq_printf(m, "DPR gap: %d\n", tas->dpr_gap); + seq_printf(m, "TAS delta: %d\n", tas->delta); +} + static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev, const struct rtw89_sar_cfg_common *sar) { @@ -292,3 +349,143 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, return rtw89_apply_sar_common(rtwdev, &sar_common); } + +static void rtw89_tas_state_update(struct rtw89_dev *rtwdev) +{ + const enum rtw89_sar_sources src = rtwdev->sar.src; + /* its members are protected by rtw89_sar_set_src() */ + const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; + struct rtw89_tas_info *tas = &rtwdev->tas; + s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT; + s32 dpr_on_threshold, dpr_off_threshold, cfg; + enum rtw89_tas_state state = tas->state; + int ret; + + lockdep_assert_held(&rtwdev->mutex); + + if (src == RTW89_SAR_SOURCE_NONE) + return; + + ret = sar_hdl->query_sar_config(rtwdev, &cfg); + if (ret) + return; + + cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg); + + if (tas->delta >= cfg) { + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "TAS delta exceed SAR limit\n"); + state = RTW89_TAS_STATE_DPR_FORBID; + goto out; + } + + dpr_on_threshold = cfg; + dpr_off_threshold = cfg - tas->dpr_gap; + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n", + dpr_on_threshold, dpr_off_threshold, txpwr_avg); + + if (txpwr_avg >= dpr_on_threshold) + state = RTW89_TAS_STATE_DPR_ON; + else if (txpwr_avg < dpr_off_threshold) + state = RTW89_TAS_STATE_DPR_OFF; + +out: + if (tas->state == state) + return; + + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "TAS old state: %d, new state: %d\n", tas->state, state); + tas->state = state; + rtw89_core_set_chip_txpwr(rtwdev); +} + +void rtw89_tas_init(struct rtw89_dev *rtwdev) +{ + struct rtw89_tas_info *tas = &rtwdev->tas; + int ret; + u8 val; + + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &val); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "acpi: cannot get TAS: %d\n", ret); + return; + } + + switch (val) { + case 0: + tas->enable = false; + break; + case 1: + tas->enable = true; + break; + default: + break; + } + + if (!tas->enable) { + rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n"); + return; + } + + tas->dpr_gap = RTW89_TAS_DPR_GAP; + tas->delta = RTW89_TAS_DELTA; +} + +void rtw89_tas_reset(struct rtw89_dev *rtwdev) +{ + struct rtw89_tas_info *tas = &rtwdev->tas; + + if (!tas->enable) + return; + + memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history)); + tas->total_txpwr = 0; + tas->cur_idx = 0; + tas->state = RTW89_TAS_STATE_DPR_OFF; +} + +static const struct rtw89_reg_def txpwr_regs[] = { + {R_PATH0_TXPWR, B_PATH0_TXPWR}, + {R_PATH1_TXPWR, B_PATH1_TXPWR}, +}; + +void rtw89_tas_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const enum rtw89_sar_sources src = rtwdev->sar.src; + u8 max_nss_num = rtwdev->chip->rf_path_num; + struct rtw89_tas_info *tas = &rtwdev->tas; + s16 tmp, txpwr, instant_txpwr = 0; + u32 val; + int i; + + if (!tas->enable || src == RTW89_SAR_SOURCE_NONE) + return; + + if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM) + return; + + for (i = 0; i < max_nss_num; i++) { + val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr, + txpwr_regs[i].mask); + tmp = sign_extend32(val, 8); + if (tmp <= 0) + return; + instant_txpwr += tmp; + } + + instant_txpwr /= max_nss_num; + /* in unit of 0.25 dBm multiply by percentage */ + txpwr = instant_txpwr * env->ifs_clm_tx_ratio; + tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx]; + tas->txpwr_history[tas->cur_idx] = txpwr; + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n", + instant_txpwr, env->ifs_clm_tx_ratio, txpwr); + + tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW; + + rtw89_tas_state_update(rtwdev); +} diff --git a/drivers/net/wireless/realtek/rtw89/sar.h b/drivers/net/wireless/realtek/rtw89/sar.h index 7b5484c84eb1..40ce5990ceaf 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.h +++ b/drivers/net/wireless/realtek/rtw89/sar.h @@ -20,7 +20,11 @@ extern const struct cfg80211_sar_capa rtw89_sar_capa; s8 rtw89_query_sar(struct rtw89_dev *rtwdev); void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev); +void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev); int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); +void rtw89_tas_init(struct rtw89_dev *rtwdev); +void rtw89_tas_reset(struct rtw89_dev *rtwdev); +void rtw89_tas_track(struct rtw89_dev *rtwdev); #endif -- cgit From 66311106b20b5aba36ca4974d0bc5d637ccf0948 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 4 Aug 2023 17:01:20 +0800 Subject: wifi: rtlwifi: use eth_broadcast_addr() to assign broadcast address Use eth_broadcast_addr() to assign broadcast address instead of memcpy(). Signed-off-by: Yang Yingliang Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230804090120.1332091-1-yangyingliang@huawei.com --- drivers/net/wireless/realtek/rtlwifi/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 4fb16f5f6f83..3835b639d453 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1656,7 +1656,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, memcpy(rtlpriv->sec.key_buf[key_idx], key->key, key->keylen); rtlpriv->sec.key_len[key_idx] = key->keylen; - memcpy(mac_addr, bcast_addr, ETH_ALEN); + eth_broadcast_addr(mac_addr); } else { /* pairwise key */ rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "set pairwise key\n"); -- cgit From 186f2432741f6d28d86ff723ac7830446affddfc Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Sat, 5 Aug 2023 17:17:28 +0800 Subject: wifi: rt2x00: correct MAC_SYS_CTRL register RX mask in R-Calibration For MAC_SYS_CTRL register, Bit[2] controls MAC_TX_EN and Bit[3] controls MAC_RX_EN (Bit index starts from 0). Therefore, 0x08 is the correct mask for RX. Signed-off-by: Shiji Yang Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/TYAP286MB03150B571B67B896A504AC34BC0EA@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 1226a883cd67..ab374c50c35d 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -8561,7 +8561,7 @@ static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev) rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n"); maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); - maccfg &= (~0x04); + maccfg &= (~0x08); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg); if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX))) -- cgit From e2a61151ff8c38ae7b3afae0e91cb97fb211a6bf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 8 Aug 2023 08:36:09 +0300 Subject: wifi: rtw89: fix a width vs precision bug The "buf" is skb->data that comes from the firmware. We want to print "len" number of bytes. But there is a missing period so the "len" variable is used for formatting (width) instead of limiting the output (precision). Fixes: cad2bd8a136c ("wifi: rtw89: support firmware log with formatted text") Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/0700c7b9-bfd3-4aa6-82bf-5bf3c74644e1@moroto.mountain --- drivers/net/wireless/realtek/rtw89/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 2811a94b5f69..bcd9050f989f 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -1165,7 +1165,7 @@ void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) return; plain_log: - rtw89_info(rtwdev, "C2H log: %*s", len, buf); + rtw89_info(rtwdev, "C2H log: %.*s", len, buf); } -- cgit From f585f4ab0b998578b4ef3610ccfc08e207fc3499 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Tue, 15 Aug 2023 20:02:53 +0800 Subject: wifi: rtw89: regd: update regulatory map to R64-R43 Sync Realtek Regulatory R43 and Realtek Channel Plan R64. 1. add entry for XK (Kosovo) 2. change TH (Thailand) to Realtek regd world-wide 3. configures Realtek 6 GHz regd for below countries * AR, MX, HT -> FCC * LB, ZA, BF, LA, MN -> ETSI Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230815120253.9901-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/regd.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index 34c4d40cfa02..9e2328db1865 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -13,10 +13,10 @@ } static const struct rtw89_regd rtw89_ww_regd = - COUNTRY_REGD("00", RTW89_WW, RTW89_WW); + COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW); static const struct rtw89_regd rtw89_regd_map[] = { - COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), + COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC), COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE), @@ -26,7 +26,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC), - COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), + COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC), COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA), @@ -81,7 +81,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), @@ -96,7 +96,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE), COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), @@ -115,7 +115,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TH", RTW89_WW, RTW89_WW, RTW89_WW), COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), @@ -148,7 +148,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -164,7 +164,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -179,20 +179,21 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC), - COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -207,7 +208,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), -- cgit From 7a73cf0bf7f96cd2b9f2ea890bf1e981730d8d6c Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Wed, 8 Mar 2023 11:59:36 +0200 Subject: net/mlx5e: aRFS, Prevent repeated kernel rule migrations requests aRFS rule movement requests from one Rx ring to other Rx ring arrive from the kernel to ensure that packets are steered to the right Rx ring. In the time interval until satisfying such a request, several more requests might follow, for the same flow. This patch detects and prevents repeated aRFS rules movement requests. In mlx5e_rx_flow_steer() ndo, after finding the aRFS rule that have been requested to move by the kernel, check if it's already requested to move by calling work_busy(&arfs_rule->arfs_work) handler. IOW, if this request is pending to be executed (in the work queue) or it's executing now but hasn't finished yet, return current filter ID and don't issue a new transition work. Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index 5aa51d74f8b4..67d8b198a014 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -740,7 +740,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, spin_lock_bh(&arfs->arfs_lock); arfs_rule = arfs_find_rule(arfs_t, &fk); if (arfs_rule) { - if (arfs_rule->rxq == rxq_index) { + if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) { spin_unlock_bh(&arfs->arfs_lock); return arfs_rule->filter_id; } -- cgit From 7653d80672455658ea106a6ba1bcabfd7a9c3917 Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Mon, 8 May 2023 14:27:48 +0300 Subject: net/mlx5e: aRFS, Warn if aRFS table does not exist for aRFS rule aRFS tables should be allocated and exist in advance. Driver shouldn't reach a point where it tries to add aRFS rule to table that does not exist. Add warning if driver encounters such situation. Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index 67d8b198a014..e8b0acf7d454 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -519,6 +519,8 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv, ntohs(tuple->etype)); arfs_table = arfs_get_table(arfs, tuple->ip_proto, tuple->etype); if (!arfs_table) { + WARN_ONCE(1, "arfs table does not exist for etype %u and ip_proto %u\n", + tuple->etype, tuple->ip_proto); err = -EINVAL; goto out; } -- cgit From f98e51585f2ca00efbd16e27ed1d94a5e5520703 Mon Sep 17 00:00:00 2001 From: Adham Faris Date: Wed, 8 Mar 2023 12:08:43 +0200 Subject: net/mlx5e: aRFS, Introduce ethtool stats Improve aRFS observability by adding new set of counters. Each Rx ring will have this set of counters listed below. These counters are exposed through ethtool -S. 1) arfs_add: number of times a new rule has been created. 2) arfs_request_in: number of times a rule was requested to move from its current Rx ring to a new Rx ring (incremented on the destination Rx ring). 3) arfs_request_out: number of times a rule was requested to move out from its current Rx ring (incremented on source/current Rx ring). 4) arfs_expired: number of times a rule has been expired by the kernel and removed from HW. 5) arfs_err: number of times a rule creation or modification has failed. This patch removes rx[i]_xsk_arfs_err counter and its documentation in mlx5/counters.rst since aRFS activity does not occur in XSK RQ's. Signed-off-by: Adham Faris Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Reviewed-by: Shay Drory --- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c | 17 ++++++++++++++--- drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | 22 ++++++++++++++++++---- drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 13 ++++++++++++- 3 files changed, 44 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index e8b0acf7d454..bb7f86c993e5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -432,8 +432,10 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv) } spin_unlock_bh(&arfs->arfs_lock); hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) { - if (arfs_rule->rule) + if (arfs_rule->rule) { mlx5_del_flow_rules(arfs_rule->rule); + priv->channel_stats[arfs_rule->rxq]->rq.arfs_expired++; + } hlist_del(&arfs_rule->hlist); kfree(arfs_rule); } @@ -509,6 +511,7 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv, spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) { + priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++; err = -ENOMEM; goto out; } @@ -602,9 +605,11 @@ static void arfs_modify_rule_rq(struct mlx5e_priv *priv, dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR; dst.tir_num = mlx5e_rx_res_get_tirn_direct(priv->rx_res, rxq); err = mlx5_modify_rule_destination(rule, &dst, NULL); - if (err) + if (err) { + priv->channel_stats[rxq]->rq.arfs_err++; netdev_warn(priv->netdev, "Failed to modify aRFS rule destination to rq=%d\n", rxq); + } } static void arfs_handle_work(struct work_struct *work) @@ -634,6 +639,7 @@ static void arfs_handle_work(struct work_struct *work) if (IS_ERR(rule)) goto out; arfs_rule->rule = rule; + priv->channel_stats[arfs_rule->rxq]->rq.arfs_add++; } else { arfs_modify_rule_rq(priv, arfs_rule->rule, arfs_rule->rxq); @@ -652,8 +658,10 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv, struct arfs_tuple *tuple; rule = kzalloc(sizeof(*rule), GFP_ATOMIC); - if (!rule) + if (!rule) { + priv->channel_stats[rxq]->rq.arfs_err++; return NULL; + } rule->priv = priv; rule->rxq = rxq; @@ -746,6 +754,9 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, spin_unlock_bh(&arfs->arfs_lock); return arfs_rule->filter_id; } + + priv->channel_stats[rxq_index]->rq.arfs_request_in++; + priv->channel_stats[arfs_rule->rxq]->rq.arfs_request_out++; arfs_rule->rxq = rxq_index; } else { arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 52141729444e..348fb140858c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -180,7 +180,13 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_blks) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_pkts) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_congst_umr) }, +#ifdef CONFIG_MLX5_EN_ARFS + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_add) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_request_in) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_request_out) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_expired) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_err) }, +#endif { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_recover) }, #ifdef CONFIG_PAGE_POOL_STATS { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_pp_alloc_fast) }, @@ -231,7 +237,6 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xsk_cqe_compress_blks) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xsk_cqe_compress_pkts) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xsk_congst_umr) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xsk_arfs_err) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xsk_xmit) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xsk_mpwqe) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_xsk_inlnw) }, @@ -321,7 +326,6 @@ static void mlx5e_stats_grp_sw_update_stats_xskrq(struct mlx5e_sw_stats *s, s->rx_xsk_cqe_compress_blks += xskrq_stats->cqe_compress_blks; s->rx_xsk_cqe_compress_pkts += xskrq_stats->cqe_compress_pkts; s->rx_xsk_congst_umr += xskrq_stats->congst_umr; - s->rx_xsk_arfs_err += xskrq_stats->arfs_err; } static void mlx5e_stats_grp_sw_update_stats_rq_stats(struct mlx5e_sw_stats *s, @@ -354,7 +358,13 @@ static void mlx5e_stats_grp_sw_update_stats_rq_stats(struct mlx5e_sw_stats *s, s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks; s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts; s->rx_congst_umr += rq_stats->congst_umr; +#ifdef CONFIG_MLX5_EN_ARFS + s->rx_arfs_add += rq_stats->arfs_add; + s->rx_arfs_request_in += rq_stats->arfs_request_in; + s->rx_arfs_request_out += rq_stats->arfs_request_out; + s->rx_arfs_expired += rq_stats->arfs_expired; s->rx_arfs_err += rq_stats->arfs_err; +#endif s->rx_recover += rq_stats->recover; #ifdef CONFIG_PAGE_POOL_STATS s->rx_pp_alloc_fast += rq_stats->pp_alloc_fast; @@ -1990,7 +2000,13 @@ static const struct counter_desc rq_stats_desc[] = { { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_blks) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, congst_umr) }, +#ifdef CONFIG_MLX5_EN_ARFS + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_add) }, + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_request_in) }, + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_request_out) }, + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_expired) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_err) }, +#endif { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, recover) }, #ifdef CONFIG_PAGE_POOL_STATS { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, pp_alloc_fast) }, @@ -2092,7 +2108,6 @@ static const struct counter_desc xskrq_stats_desc[] = { { MLX5E_DECLARE_XSKRQ_STAT(struct mlx5e_rq_stats, cqe_compress_blks) }, { MLX5E_DECLARE_XSKRQ_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) }, { MLX5E_DECLARE_XSKRQ_STAT(struct mlx5e_rq_stats, congst_umr) }, - { MLX5E_DECLARE_XSKRQ_STAT(struct mlx5e_rq_stats, arfs_err) }, }; static const struct counter_desc xsksq_stats_desc[] = { @@ -2168,7 +2183,6 @@ static const struct counter_desc ptp_rq_stats_desc[] = { { MLX5E_DECLARE_PTP_RQ_STAT(struct mlx5e_rq_stats, cqe_compress_blks) }, { MLX5E_DECLARE_PTP_RQ_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) }, { MLX5E_DECLARE_PTP_RQ_STAT(struct mlx5e_rq_stats, congst_umr) }, - { MLX5E_DECLARE_PTP_RQ_STAT(struct mlx5e_rq_stats, arfs_err) }, { MLX5E_DECLARE_PTP_RQ_STAT(struct mlx5e_rq_stats, recover) }, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 409e9a47e433..176fa5976259 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -194,7 +194,13 @@ struct mlx5e_sw_stats { u64 rx_cqe_compress_blks; u64 rx_cqe_compress_pkts; u64 rx_congst_umr; +#ifdef CONFIG_MLX5_EN_ARFS + u64 rx_arfs_add; + u64 rx_arfs_request_in; + u64 rx_arfs_request_out; + u64 rx_arfs_expired; u64 rx_arfs_err; +#endif u64 rx_recover; u64 ch_events; u64 ch_poll; @@ -256,7 +262,6 @@ struct mlx5e_sw_stats { u64 rx_xsk_cqe_compress_blks; u64 rx_xsk_cqe_compress_pkts; u64 rx_xsk_congst_umr; - u64 rx_xsk_arfs_err; u64 tx_xsk_xmit; u64 tx_xsk_mpwqe; u64 tx_xsk_inlnw; @@ -358,7 +363,13 @@ struct mlx5e_rq_stats { u64 cqe_compress_blks; u64 cqe_compress_pkts; u64 congst_umr; +#ifdef CONFIG_MLX5_EN_ARFS + u64 arfs_add; + u64 arfs_request_in; + u64 arfs_request_out; + u64 arfs_expired; u64 arfs_err; +#endif u64 recover; #ifdef CONFIG_PAGE_POOL_STATS u64 pp_alloc_fast; -- cgit From d7cea02a1fac70808423b6c7a64464ba3185f7a9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 4 Aug 2023 19:23:06 +0100 Subject: net/mlx5e: Fix spelling mistake "Faided" -> "Failed" There is a spelling mistake in a warning message. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Rahul Rameshbabu Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c index 455746952260..095f31f380fa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -316,7 +316,7 @@ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) err = mlx5_esw_ipsec_modify_flow_dests(esw, flow); if (err) mlx5_core_warn_once(mdev, - "Faided to modify flow dests for IPsec"); + "Failed to modify flow dests for IPsec"); } rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); -- cgit From 9e9ff54e63b4bc4e2436112f008ddb9e3aed4910 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 9 Jun 2023 12:10:27 -0700 Subject: net/mlx5: IRQ, consolidate irq and affinity mask allocation Consolidate the mlx5_irq and mlx5_irq->mask allocation, to simplify error flows and to match the dealloctation sequence @irq_release for symmetry. Signed-off-by: Saeed Mahameed Reviewed-by: Shay Drory --- drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index 33a133c9918c..653648216730 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -259,8 +259,11 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, int err; irq = kzalloc(sizeof(*irq), GFP_KERNEL); - if (!irq) + if (!irq || !zalloc_cpumask_var(&irq->mask, GFP_KERNEL)) { + kfree(irq); return ERR_PTR(-ENOMEM); + } + if (!i || !pci_msix_can_alloc_dyn(dev->pdev)) { /* The vector at index 0 is always statically allocated. If * dynamic irq is not supported all vectors are statically @@ -297,11 +300,7 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, mlx5_core_err(dev, "Failed to request irq. err = %d\n", err); goto err_req_irq; } - if (!zalloc_cpumask_var(&irq->mask, GFP_KERNEL)) { - mlx5_core_warn(dev, "zalloc_cpumask_var failed\n"); - err = -ENOMEM; - goto err_cpumask; - } + if (af_desc) { cpumask_copy(irq->mask, &af_desc->mask); irq_set_affinity_and_hint(irq->map.virq, irq->mask); @@ -319,8 +318,6 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, err_xa: if (af_desc) irq_update_affinity_hint(irq->map.virq, NULL); - free_cpumask_var(irq->mask); -err_cpumask: free_irq(irq->map.virq, &irq->nh); err_req_irq: #ifdef CONFIG_RFS_ACCEL @@ -333,6 +330,7 @@ err_irq_rmap: if (i && pci_msix_can_alloc_dyn(dev->pdev)) pci_msix_free_irq(dev->pdev, irq->map); err_alloc_irq: + free_cpumask_var(irq->mask); kfree(irq); return ERR_PTR(err); } -- cgit From f83e2d8aef4acc044465ad6464f54b6a704ec34b Mon Sep 17 00:00:00 2001 From: Yevgeny Kliteynik Date: Wed, 2 Aug 2023 01:01:14 +0300 Subject: net/mlx5: DR, Fix code indentation Signed-off-by: Yevgeny Kliteynik Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c index feb307fb3440..14f6df88b1f9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c @@ -336,7 +336,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, if (fte->action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) { err = -EINVAL; mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n"); - goto free_actions; + goto free_actions; } is_decap = fte->action.pkt_reformat->reformat_type == -- cgit From a15e472f8834826668fecba89bd11d2e49530ab0 Mon Sep 17 00:00:00 2001 From: Yevgeny Kliteynik Date: Wed, 2 Aug 2023 01:03:31 +0300 Subject: net/mlx5: DR, Remove unneeded local variable Remove local variable that is already defined outside of the scope of this block. Signed-off-by: Yevgeny Kliteynik Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index 54bb0866ed72..5b83da08692d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -1422,7 +1422,6 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn, case DR_ACTION_TYP_TNL_L3_TO_L2: { u8 *hw_actions; - int ret; hw_actions = kzalloc(DR_ACTION_CACHE_LINE_SIZE, GFP_KERNEL); if (!hw_actions) -- cgit From ab943e2efd5da306920fd45387c05c77bf9c3168 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Mon, 26 Jun 2023 14:26:17 +0300 Subject: net/mlx5: Remove health syndrome enum duplication Health syndrome enum values were duplicated in mlx5_ifc and health.c, the correct place for them is mlx5_ifc. Signed-off-by: Gal Pressman Reviewed-by: Rahul Rameshbabu Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 36 ++++++++---------------- 1 file changed, 11 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 187cb2c464f8..2fb2598b775e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -49,20 +49,6 @@ enum { MAX_MISSES = 3, }; -enum { - MLX5_HEALTH_SYNDR_FW_ERR = 0x1, - MLX5_HEALTH_SYNDR_IRISC_ERR = 0x7, - MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR = 0x8, - MLX5_HEALTH_SYNDR_CRC_ERR = 0x9, - MLX5_HEALTH_SYNDR_FETCH_PCI_ERR = 0xa, - MLX5_HEALTH_SYNDR_HW_FTL_ERR = 0xb, - MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR = 0xc, - MLX5_HEALTH_SYNDR_EQ_ERR = 0xd, - MLX5_HEALTH_SYNDR_EQ_INV = 0xe, - MLX5_HEALTH_SYNDR_FFSER_ERR = 0xf, - MLX5_HEALTH_SYNDR_HIGH_TEMP = 0x10 -}; - enum { MLX5_DROP_HEALTH_WORK, }; @@ -357,27 +343,27 @@ static int mlx5_health_try_recover(struct mlx5_core_dev *dev) static const char *hsynd_str(u8 synd) { switch (synd) { - case MLX5_HEALTH_SYNDR_FW_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_FW_INTERNAL_ERR: return "firmware internal error"; - case MLX5_HEALTH_SYNDR_IRISC_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_DEAD_IRISC: return "irisc not responding"; - case MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_HW_FATAL_ERR: return "unrecoverable hardware error"; - case MLX5_HEALTH_SYNDR_CRC_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_FW_CRC_ERR: return "firmware CRC error"; - case MLX5_HEALTH_SYNDR_FETCH_PCI_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_ICM_FETCH_PCI_ERR: return "ICM fetch PCI error"; - case MLX5_HEALTH_SYNDR_HW_FTL_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_ICM_PAGE_ERR: return "HW fatal error\n"; - case MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_ASYNCHRONOUS_EQ_BUF_OVERRUN: return "async EQ buffer overrun"; - case MLX5_HEALTH_SYNDR_EQ_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_EQ_IN_ERR: return "EQ error"; - case MLX5_HEALTH_SYNDR_EQ_INV: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_EQ_INV: return "Invalid EQ referenced"; - case MLX5_HEALTH_SYNDR_FFSER_ERR: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_FFSER_ERR: return "FFSER error"; - case MLX5_HEALTH_SYNDR_HIGH_TEMP: + case MLX5_INITIAL_SEG_HEALTH_SYNDROME_HIGH_TEMP_ERR: return "High temperature"; default: return "unrecognized error"; -- cgit From ba3d85f008f293ed1b721a4d892b0d55a7d16e9f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 May 2023 19:14:38 +0200 Subject: net/mlx5: Call mlx5_esw_offloads_rep_load/unload() for uplink port directly For uplink port, mlx5_esw_offloads_load/unload_rep() are currently called. There are 2 check inside, which effectively make the functions a simple wrappers of mlx5_esw_offloads_rep_load/unload() for uplink port. So avoid one check and indirection and call mlx5_esw_offloads_rep_load/unload() for uplink port directly. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 46b8c60ac39a..c0b1b7b66cff 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2542,11 +2542,9 @@ int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; - if (vport_num != MLX5_VPORT_UPLINK) { - err = mlx5_esw_offloads_devlink_port_register(esw, vport_num); - if (err) - return err; - } + err = mlx5_esw_offloads_devlink_port_register(esw, vport_num); + if (err) + return err; err = mlx5_esw_offloads_rep_load(esw, vport_num); if (err) @@ -2554,8 +2552,7 @@ int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) return err; load_err: - if (vport_num != MLX5_VPORT_UPLINK) - mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); + mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); return err; } @@ -2566,8 +2563,7 @@ void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num) mlx5_esw_offloads_rep_unload(esw, vport_num); - if (vport_num != MLX5_VPORT_UPLINK) - mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); + mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); } static int esw_set_slave_root_fdb(struct mlx5_core_dev *master, @@ -3471,7 +3467,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; /* Uplink vport rep must load first. */ - err = mlx5_esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK); + err = mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK); if (err) goto err_uplink; @@ -3482,7 +3478,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) return 0; err_vports: - mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); + mlx5_esw_offloads_rep_unload(esw, MLX5_VPORT_UPLINK); err_uplink: esw_offloads_steering_cleanup(esw); err_steering_init: @@ -3520,7 +3516,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, void esw_offloads_disable(struct mlx5_eswitch *esw) { mlx5_eswitch_disable_pf_vf_vports(esw); - mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); + mlx5_esw_offloads_rep_unload(esw, MLX5_VPORT_UPLINK); esw_set_passing_vport_metadata(esw, false); esw_offloads_steering_cleanup(esw); mapping_destroy(esw->offloads.reg_c0_obj_pool); -- cgit From 52020903f35c78e5d147c21f8a1fea1ad7631e3e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 11:07:32 +0200 Subject: net/mlx5: Remove VPORT_UPLINK handling from devlink_port.c It is not possible that the functions in devlink_port.c are called for uplink port. Remove this leftover code. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 0313432d50a1..ccf8cdedeab4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -16,8 +16,7 @@ mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_i static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_num) { - return vport_num == MLX5_VPORT_UPLINK || - (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) || + return (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) || mlx5_eswitch_is_vf_vport(esw, vport_num) || mlx5_core_is_ec_vf_vport(esw->dev, vport_num); } @@ -25,7 +24,6 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_core_dev *dev = esw->dev; - struct devlink_port_attrs attrs = {}; struct netdev_phys_item_id ppid = {}; struct devlink_port *dl_port; u32 controller_num = 0; @@ -42,13 +40,7 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 if (external) controller_num = dev->priv.eswitch->offloads.host_number + 1; - if (vport_num == MLX5_VPORT_UPLINK) { - attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; - attrs.phys.port_number = pfnum; - memcpy(attrs.switch_id.id, ppid.id, ppid.id_len); - attrs.switch_id.id_len = ppid.id_len; - devlink_port_attrs_set(dl_port, &attrs); - } else if (vport_num == MLX5_VPORT_PF) { + if (vport_num == MLX5_VPORT_PF) { memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); dl_port->attrs.switch_id.id_len = ppid.id_len; devlink_port_attrs_pci_pf_set(dl_port, controller_num, pfnum, external); -- cgit From df3822f5808de66903a3627bf0694909447faa32 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 May 2023 14:23:54 +0200 Subject: net/mlx5: Rename devlink port ops struct for PFs/VFs As this struct is only used for devlink ports created for PF/VF, add it to the name of the variable to distinguish from the SF related ops struct. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index ccf8cdedeab4..234fd4c28e79 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -63,7 +63,7 @@ static void mlx5_esw_dl_port_free(struct devlink_port *dl_port) kfree(dl_port); } -static const struct devlink_port_ops mlx5_esw_dl_port_ops = { +static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, @@ -95,7 +95,7 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, - &mlx5_esw_dl_port_ops); + &mlx5_esw_pf_vf_dl_port_ops); if (err) goto reg_err; -- cgit From 95c337cce0e11d06a715da73e6796ade9216637f Mon Sep 17 00:00:00 2001 From: Itamar Gozlan Date: Mon, 7 Aug 2023 15:07:26 +0300 Subject: net/mlx5: DR, Supporting inline WQE when possible In WQE (Work Queue Entry), the two types of data segments memories are pointers and inline data, where inline data is passed directly as part of the WQE. For software steering, the maximal inline size should be less than 2*MLX5_SEND_WQE_BB, i.e., the potential data must fit with the required inline WQE headers. Two consecutive blocks (MLX5_SEND_WQE_BB) are not guaranteed to reside on the same memory page. Hence, writes to MLX5_SEND_WQE_BB should be done separately, i.e., each MLX5_SEND_WQE_BB should be obtained using the mlx5_wq_cyc_get_wqe macro. Signed-off-by: Itamar Gozlan Reviewed-by: Yevgeny Kliteynik Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/steering/dr_send.c | 115 ++++++++++++++++++--- 1 file changed, 102 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c index 6fa06ba2d346..4e8527a724f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c @@ -52,6 +52,7 @@ struct dr_qp_init_attr { u32 cqn; u32 pdn; u32 max_send_wr; + u32 max_send_sge; struct mlx5_uars_page *uar; u8 isolate_vl_tc:1; }; @@ -246,6 +247,37 @@ static int dr_poll_cq(struct mlx5dr_cq *dr_cq, int ne) return err == CQ_POLL_ERR ? err : npolled; } +static int dr_qp_get_args_update_send_wqe_size(struct dr_qp_init_attr *attr) +{ + return roundup_pow_of_two(sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_flow_update_ctrl_seg) + + sizeof(struct mlx5_wqe_header_modify_argument_update_seg)); +} + +/* We calculate for specific RC QP with the required functionality */ +static int dr_qp_calc_rc_send_wqe(struct dr_qp_init_attr *attr) +{ + int update_arg_size; + int inl_size = 0; + int tot_size; + int size; + + update_arg_size = dr_qp_get_args_update_send_wqe_size(attr); + + size = sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg); + inl_size = size + ALIGN(sizeof(struct mlx5_wqe_inline_seg) + + DR_STE_SIZE, 16); + + size += attr->max_send_sge * sizeof(struct mlx5_wqe_data_seg); + + size = max(size, update_arg_size); + + tot_size = max(size, inl_size); + + return ALIGN(tot_size, MLX5_SEND_WQE_BB); +} + static struct mlx5dr_qp *dr_create_rc_qp(struct mlx5_core_dev *mdev, struct dr_qp_init_attr *attr) { @@ -253,6 +285,7 @@ static struct mlx5dr_qp *dr_create_rc_qp(struct mlx5_core_dev *mdev, u32 temp_qpc[MLX5_ST_SZ_DW(qpc)] = {}; struct mlx5_wq_param wqp; struct mlx5dr_qp *dr_qp; + int wqe_size; int inlen; void *qpc; void *in; @@ -332,6 +365,15 @@ static struct mlx5dr_qp *dr_create_rc_qp(struct mlx5_core_dev *mdev, if (err) goto err_in; dr_qp->uar = attr->uar; + wqe_size = dr_qp_calc_rc_send_wqe(attr); + dr_qp->max_inline_data = min(wqe_size - + (sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_inline_seg)), + (2 * MLX5_SEND_WQE_BB - + (sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_inline_seg)))); return dr_qp; @@ -395,8 +437,48 @@ dr_rdma_handle_flow_access_arg_segments(struct mlx5_wqe_ctrl_seg *wq_ctrl, MLX5_SEND_WQE_DS; } +static int dr_set_data_inl_seg(struct mlx5dr_qp *dr_qp, + struct dr_data_seg *data_seg, void *wqe) +{ + int inline_header_size = sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_inline_seg); + struct mlx5_wqe_inline_seg *seg; + int left_space; + int inl = 0; + void *addr; + int len; + int idx; + + seg = wqe; + wqe += sizeof(*seg); + addr = (void *)(unsigned long)(data_seg->addr); + len = data_seg->length; + inl += len; + left_space = MLX5_SEND_WQE_BB - inline_header_size; + + if (likely(len > left_space)) { + memcpy(wqe, addr, left_space); + len -= left_space; + addr += left_space; + idx = (dr_qp->sq.pc + 1) & (dr_qp->sq.wqe_cnt - 1); + wqe = mlx5_wq_cyc_get_wqe(&dr_qp->wq.sq, idx); + } + + memcpy(wqe, addr, len); + + if (likely(inl)) { + seg->byte_count = cpu_to_be32(inl | MLX5_INLINE_SEG); + return DIV_ROUND_UP(inl + sizeof(seg->byte_count), + MLX5_SEND_WQE_DS); + } else { + return 0; + } +} + static void -dr_rdma_handle_icm_write_segments(struct mlx5_wqe_ctrl_seg *wq_ctrl, +dr_rdma_handle_icm_write_segments(struct mlx5dr_qp *dr_qp, + struct mlx5_wqe_ctrl_seg *wq_ctrl, u64 remote_addr, u32 rkey, struct dr_data_seg *data_seg, @@ -412,15 +494,17 @@ dr_rdma_handle_icm_write_segments(struct mlx5_wqe_ctrl_seg *wq_ctrl, wq_raddr->reserved = 0; wq_dseg = (void *)(wq_raddr + 1); + /* WQE ctrl segment + WQE remote addr segment */ + *size = (sizeof(*wq_ctrl) + sizeof(*wq_raddr)) / MLX5_SEND_WQE_DS; - wq_dseg->byte_count = cpu_to_be32(data_seg->length); - wq_dseg->lkey = cpu_to_be32(data_seg->lkey); - wq_dseg->addr = cpu_to_be64(data_seg->addr); - - *size = (sizeof(*wq_ctrl) + /* WQE ctrl segment */ - sizeof(*wq_dseg) + /* WQE data segment */ - sizeof(*wq_raddr)) / /* WQE remote addr segment */ - MLX5_SEND_WQE_DS; + if (data_seg->send_flags & IB_SEND_INLINE) { + *size += dr_set_data_inl_seg(dr_qp, data_seg, wq_dseg); + } else { + wq_dseg->byte_count = cpu_to_be32(data_seg->length); + wq_dseg->lkey = cpu_to_be32(data_seg->lkey); + wq_dseg->addr = cpu_to_be64(data_seg->addr); + *size += sizeof(*wq_dseg) / MLX5_SEND_WQE_DS; /* WQE data segment */ + } } static void dr_set_ctrl_seg(struct mlx5_wqe_ctrl_seg *wq_ctrl, @@ -451,7 +535,7 @@ static void dr_rdma_segments(struct mlx5dr_qp *dr_qp, u64 remote_addr, switch (opcode) { case MLX5_OPCODE_RDMA_READ: case MLX5_OPCODE_RDMA_WRITE: - dr_rdma_handle_icm_write_segments(wq_ctrl, remote_addr, + dr_rdma_handle_icm_write_segments(dr_qp, wq_ctrl, remote_addr, rkey, data_seg, &size); break; case MLX5_OPCODE_FLOW_TBL_ACCESS: @@ -572,7 +656,7 @@ static void dr_fill_write_args_segs(struct mlx5dr_send_ring *send_ring, if (send_ring->pending_wqe % send_ring->signal_th == 0) send_info->write.send_flags |= IB_SEND_SIGNALED; else - send_info->write.send_flags = 0; + send_info->write.send_flags &= ~IB_SEND_SIGNALED; } static void dr_fill_write_icm_segs(struct mlx5dr_domain *dmn, @@ -596,9 +680,13 @@ static void dr_fill_write_icm_segs(struct mlx5dr_domain *dmn, } send_ring->pending_wqe++; + if (!send_info->write.lkey) + send_info->write.send_flags |= IB_SEND_INLINE; if (send_ring->pending_wqe % send_ring->signal_th == 0) send_info->write.send_flags |= IB_SEND_SIGNALED; + else + send_info->write.send_flags &= ~IB_SEND_SIGNALED; send_ring->pending_wqe++; send_info->read.length = send_info->write.length; @@ -608,9 +696,9 @@ static void dr_fill_write_icm_segs(struct mlx5dr_domain *dmn, send_info->read.lkey = send_ring->sync_mr->mkey; if (send_ring->pending_wqe % send_ring->signal_th == 0) - send_info->read.send_flags = IB_SEND_SIGNALED; + send_info->read.send_flags |= IB_SEND_SIGNALED; else - send_info->read.send_flags = 0; + send_info->read.send_flags &= ~IB_SEND_SIGNALED; } static void dr_fill_data_segs(struct mlx5dr_domain *dmn, @@ -1257,6 +1345,7 @@ int mlx5dr_send_ring_alloc(struct mlx5dr_domain *dmn) dmn->send_ring->cq->qp = dmn->send_ring->qp; dmn->info.max_send_wr = QUEUE_SIZE; + init_attr.max_send_sge = 1; dmn->info.max_inline_size = min(dmn->send_ring->qp->max_inline_data, DR_STE_SIZE); -- cgit From 7d7c6e8c5fe4e8cceea7f66e93cee1c951670836 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Mon, 14 Aug 2023 15:23:42 +0800 Subject: net/mlx5: Devcom, only use devcom after NULL check in mlx5_devcom_send_event() There is a warning reported by kernel test robot: smatch warnings: drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c:264 mlx5_devcom_send_event() warn: variable dereferenced before IS_ERR check devcom (see line 259) The reason for the warning is that the pointer is used before check, put the assignment to comp after devcom check to silence the warning. Fixes: 88d162b47981 ("net/mlx5: Devcom, Infrastructure changes") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202308041028.AkXYDwJ6-lkp@intel.com/ Signed-off-by: Li Zetao Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index feb62d952643..00e67910e3ee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -256,14 +256,15 @@ int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, int event, int rollback_event, void *event_data) { - struct mlx5_devcom_comp *comp = devcom->comp; struct mlx5_devcom_comp_dev *pos; + struct mlx5_devcom_comp *comp; int err = 0; void *data; if (IS_ERR_OR_NULL(devcom)) return -ENODEV; + comp = devcom->comp; down_write(&comp->sem); list_for_each_entry(pos, &comp->comp_dev_list_head, list) { data = rcu_dereference_protected(pos->data, lockdep_is_held(&comp->sem)); -- cgit From 7eb6deb3f55678216a6a0e956846c04958093ea5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 21 Aug 2023 12:11:35 -0700 Subject: Revert "pds_core: Fix some kernel-doc comments" This reverts commit cb39c35783f26892bb1a72b1115c94fa2e77f4c5. Patch was applied to hastily, the problem is already fixed in Alex's vfio tree: https://lore.kernel.org/all/20230821112237.105872b5.alex.williamson@redhat.com/ Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/auxbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c index f46efebaaea9..6787a5fae908 100644 --- a/drivers/net/ethernet/amd/pds_core/auxbus.c +++ b/drivers/net/ethernet/amd/pds_core/auxbus.c @@ -8,7 +8,7 @@ /** * pds_client_register - Link the client to the firmware - * @pf: a pointer to the pdsc structure + * @pf_pdev: ptr to the PF driver struct * @devname: name that includes service into, e.g. pds_core.vDPA * * Return: positive client ID (ci) on success, or @@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(pds_client_register); /** * pds_client_unregister - Unlink the client from the firmware - * @pf: a pointer to the pdsc structure + * @pf_pdev: ptr to the PF driver struct * @client_id: id returned from pds_client_register() * * Return: 0 on success, or -- cgit From 90308679c297ffcbb317c715ef434e9fb3c881dc Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 18 Aug 2023 04:07:46 +0100 Subject: net: pcs: lynxi: implement pcs_disable op When switching from 10GBase-R/5GBase-R/USXGMII to one of the interface modes provided by mtk-pcs-lynxi we need to make sure to always perform a full configuration of the PHYA. Implement pcs_disable op which resets the stored interface mode to PHY_INTERFACE_MODE_NA to trigger a full reconfiguration once the LynxI PCS driver had previously been deselected in favor of another PCS driver such as the to-be-added driver for the USXGMII PCS found in MT7988. Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/f23d1a60d2c9d2fb72e32dcb0eaa5f7e867a3d68.1692327891.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/pcs/pcs-mtk-lynxi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c index b0f3ede945d9..8501dd365279 100644 --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c @@ -233,11 +233,19 @@ static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, } } +static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) +{ + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + + mpcs->interface = PHY_INTERFACE_MODE_NA; +} + static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { .pcs_get_state = mtk_pcs_lynxi_get_state, .pcs_config = mtk_pcs_lynxi_config, .pcs_an_restart = mtk_pcs_lynxi_restart_an, .pcs_link_up = mtk_pcs_lynxi_link_up, + .pcs_disable = mtk_pcs_lynxi_disable, }; struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, -- cgit From 3a198c95c95da10ad844cbeade2fe40bdf14c411 Mon Sep 17 00:00:00 2001 From: "GONG, Ruiqi" Date: Mon, 21 Aug 2023 09:32:18 +0800 Subject: alx: fix OOB-read compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following message shows up when compiling with W=1: In function ‘fortify_memcpy_chk’, inlined from ‘alx_get_ethtool_stats’ at drivers/net/ethernet/atheros/alx/ethtool.c:297:2: ./include/linux/fortify-string.h:592:4: error: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning] 592 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In order to get alx stats altogether, alx_get_ethtool_stats() reads beyond hw->stats.rx_ok. Fix this warning by directly copying hw->stats, and refactor the unnecessarily complicated BUILD_BUG_ON btw. Signed-off-by: GONG, Ruiqi Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230821013218.1614265-1-gongruiqi@huaweicloud.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/atheros/alx/ethtool.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index b716adacd815..7f6b69a52367 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -292,9 +292,8 @@ static void alx_get_ethtool_stats(struct net_device *netdev, spin_lock(&alx->stats_lock); alx_update_hw_stats(hw); - BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) < - ALX_NUM_STATS * sizeof(u64)); - memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64)); + BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64)); + memcpy(data, &hw->stats, sizeof(hw->stats)); spin_unlock(&alx->stats_lock); } -- cgit From b33663307002db8c9aac6783e31e3a786ed991c3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:43 +0300 Subject: wifi: iwlwifi: mvm: advertise MLO only if EHT is enabled If 11ax/EHT is disabled, then we shouldn't advertise MLO support either. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.ae4f9151440e.I6ce0b98d063d5005fd7a613454fcdb8b866a417a@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index ce7905faa08f..e7fe5b76def4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -315,8 +315,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, STA_MMPDU_TXQ); /* Set this early since we need to have it for the check below */ - if (mvm->mld_api_is_used && - mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + if (mvm->mld_api_is_used && mvm->nvm_data->sku_cap_11be_enable && + !iwlwifi_mod_params.disable_11ax && + !iwlwifi_mod_params.disable_11be) hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; /* With MLD FW API, it tracks timing by itself, -- cgit From 0c2f92f6a5ac258457e7c9d55c74f14a0f1937cd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:44 +0300 Subject: wifi: iwlwifi: api: fix a small upper/lower-case typo The structure name in the docs should be given in all lower case matching the actual C declaration. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.c06f98055dbb.Ie9267108c57edcbb913f0d0f349eac85ca39409b@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/api/debug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 8fef38139bf6..48ffab22bb7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2022 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -377,7 +377,7 @@ struct iwl_buf_alloc_cmd { #define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF /** - * struct iwL_dram_info - DRAM fragments allocation struct + * struct iwl_dram_info - DRAM fragments allocation struct * * Driver will fill in the first 1K(+) of the pointed DRAM fragment * -- cgit From d9d115fed674351effd8610aad1e8f1178a5f8b9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:45 +0300 Subject: wifi: iwlwifi: remove WARN from read_mem32() There's no reason to warn here, it's not an internal consistency issue, we even use this to check if the device is dead, and if it read_mem() returns an error that's either because grab NIC access or memory allocation failed, both of which are already noisy. Just remove the warning entirely. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.5f4e80eb63cc.Iffd88f63f95575f28e503da13b473724e3341aee@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index d02943d0ea62..8a6ddb5fb0c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2022 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1490,7 +1490,7 @@ static inline u32 iwl_trans_read_mem32(struct iwl_trans *trans, u32 addr) { u32 value; - if (WARN_ON(iwl_trans_read_mem(trans, addr, &value, 1))) + if (iwl_trans_read_mem(trans, addr, &value, 1)) return 0xa5a5a5a5; return value; -- cgit From a06320044a30d2ef33fa07f3df5d7411c217d4c0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:46 +0300 Subject: wifi: iwlwifi: pcie: clean up gen1/gen2 TFD unmap This is a bit messy right now, there are functions for both, but then gen1 function can actually deal with both gen1 and gen2, due to the confusion about use_tfh/gen2 cleaned up in the previous patch. Fix the common paths to call the right functions and remove handling of gen2 from the gen1 function. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.baf23841ec5c.I40702e94b25db05e82f935f14548316f8c6429b9@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 6 ++++- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 33 ++++++++------------------- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 11 +-------- 3 files changed, 16 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 790e5b124740..9ab1b2590dd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1203,7 +1203,11 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, group_id = cmd->hdr.group_id; cmd_id = WIDE_ID(group_id, cmd->hdr.cmd); - iwl_txq_gen1_tfd_unmap(trans, meta, txq, index); + if (trans->trans_cfg->gen2) + iwl_txq_gen2_tfd_unmap(trans, meta, + iwl_txq_get_tfd(trans, txq, index)); + else + iwl_txq_gen1_tfd_unmap(trans, meta, txq, index); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 5bb3cc3367c9..5b1100e6e1d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -1340,22 +1340,12 @@ error: } static inline dma_addr_t iwl_txq_gen1_tfd_tb_get_addr(struct iwl_trans *trans, - void *_tfd, u8 idx) + struct iwl_tfd *tfd, u8 idx) { - struct iwl_tfd *tfd; - struct iwl_tfd_tb *tb; + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; dma_addr_t addr; dma_addr_t hi_len; - if (trans->trans_cfg->gen2) { - struct iwl_tfh_tfd *tfh_tfd = _tfd; - struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx]; - - return (dma_addr_t)(le64_to_cpu(tfh_tb->addr)); - } - - tfd = _tfd; - tb = &tfd->tbs[idx]; addr = get_unaligned_le32(&tb->lo); if (sizeof(dma_addr_t) <= sizeof(u32)) @@ -1376,7 +1366,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, struct iwl_txq *txq, int index) { int i, num_tbs; - void *tfd = iwl_txq_get_tfd(trans, txq, index); + struct iwl_tfd *tfd = iwl_txq_get_tfd(trans, txq, index); /* Sanity check on number of chunks */ num_tbs = iwl_txq_gen1_tfd_get_num_tbs(trans, tfd); @@ -1408,15 +1398,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, meta->tbs = 0; - if (trans->trans_cfg->gen2) { - struct iwl_tfh_tfd *tfd_fh = (void *)tfd; - - tfd_fh->num_tbs = 0; - } else { - struct iwl_tfd *tfd_fh = (void *)tfd; - - tfd_fh->num_tbs = 0; - } + tfd->num_tbs = 0; } #define IWL_TX_CRC_SIZE 4 @@ -1520,7 +1502,12 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) /* We have only q->n_window txq->entries, but we use * TFD_QUEUE_SIZE_MAX tfds */ - iwl_txq_gen1_tfd_unmap(trans, &txq->entries[idx].meta, txq, rd_ptr); + if (trans->trans_cfg->gen2) + iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta, + iwl_txq_get_tfd(trans, txq, rd_ptr)); + else + iwl_txq_gen1_tfd_unmap(trans, &txq->entries[idx].meta, + txq, rd_ptr); /* free SKB */ skb = txq->entries[idx].skb; diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h index 1e4a24ab9bab..15b3edce56e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -131,17 +131,8 @@ struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len, struct sk_buff *skb); #endif static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans, - void *_tfd) + struct iwl_tfd *tfd) { - struct iwl_tfd *tfd; - - if (trans->trans_cfg->gen2) { - struct iwl_tfh_tfd *tfh_tfd = _tfd; - - return le16_to_cpu(tfh_tfd->num_tbs) & 0x1f; - } - - tfd = (struct iwl_tfd *)_tfd; return tfd->num_tbs & 0x1f; } -- cgit From d5050543f1ed78beb85f85b5830242cb0c4968c0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:47 +0300 Subject: wifi: iwlwifi: remove 'def_rx_queue' struct member This is only ever initialized to zero, use a new define for the default RX queue instead. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.e0c6fa57c162.I907bbb428cf99725f06a348c8dbce5d3dd877136@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/iwl-fh.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 4 +--- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 -- 4 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 4e4a60ddf9b2..41ab5a6e2dd3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -565,6 +565,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans, #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 +#define IWL_DEFAULT_RX_QUEUE 0 + /** * struct iwl_rb_status - reserve buffer status * host memory mapped FH registers diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 0adcf0e13e85..0f6493dab8cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2003-2015, 2018-2022 Intel Corporation + * Copyright (C) 2003-2015, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -315,7 +315,6 @@ enum iwl_pcie_imr_status { * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_write_waitq: wait queue for uCode load * @cmd_queue - command queue number - * @def_rx_queue - default rx queue number * @rx_buf_size: Rx buffer size * @scd_set_active: should the transport configure the SCD for HCMD queue * @rx_page_order: page order for receive buffer size @@ -398,7 +397,6 @@ struct iwl_trans_pcie { wait_queue_head_t ucode_write_waitq; wait_queue_head_t sx_waitq; - u8 def_rx_queue; u8 n_no_reclaim_cmds; u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; u16 num_rx_bufs; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index f87b28edc267..4614acee9f7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1373,7 +1373,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, } } - if (rxq->id == trans_pcie->def_rx_queue) + if (rxq->id == IWL_DEFAULT_RX_QUEUE) iwl_op_mode_rx(trans->op_mode, &rxq->napi, &rxcb); else diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 3e988da44973..2096f7158728 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3617,8 +3617,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, PCIE_LINK_STATE_CLKPM); } - trans_pcie->def_rx_queue = 0; - pci_set_master(pdev); addr_size = trans->txqs.tfd.addr_size; -- cgit From c522948a4718a4c577cea05ae6e48d74d3b6cab7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:48 +0300 Subject: wifi: iwlwifi: pcie: move gen1 TB handling to header We will need this in another place soon in reclaim and init, so add this function to the queue header file instead. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.52b6f66de219.Ic8403fd098c187fac067977808c0129d96514c91@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 18 +----------------- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 9ab1b2590dd2..2f39b639c43f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -132,22 +132,6 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) } } -static inline void iwl_pcie_tfd_set_tb(struct iwl_trans *trans, void *tfd, - u8 idx, dma_addr_t addr, u16 len) -{ - struct iwl_tfd *tfd_fh = (void *)tfd; - struct iwl_tfd_tb *tb = &tfd_fh->tbs[idx]; - - u16 hi_n_len = len << 4; - - put_unaligned_le32(addr, &tb->lo); - hi_n_len |= iwl_get_dma_hi_addr(addr); - - tb->hi_n_len = cpu_to_le16(hi_n_len); - - tfd_fh->num_tbs = idx + 1; -} - static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, dma_addr_t addr, u16 len, bool reset) { @@ -172,7 +156,7 @@ static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, "Unaligned address = %llx\n", (unsigned long long)addr)) return -EINVAL; - iwl_pcie_tfd_set_tb(trans, tfd, num_tbs, addr, len); + iwl_pcie_gen1_tfd_set_tb(trans, tfd, num_tbs, addr, len); return num_tbs; } diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h index 15b3edce56e0..b7d3808588bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -155,6 +155,21 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans, return le16_to_cpu(tb->hi_n_len) >> 4; } +static inline void iwl_pcie_gen1_tfd_set_tb(struct iwl_trans *trans, + struct iwl_tfd *tfd, + u8 idx, dma_addr_t addr, u16 len) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + u16 hi_n_len = len << 4; + + put_unaligned_le32(addr, &tb->lo); + hi_n_len |= iwl_get_dma_hi_addr(addr); + + tb->hi_n_len = cpu_to_le16(hi_n_len); + + tfd->num_tbs = idx + 1; +} + void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, struct iwl_cmd_meta *meta, struct iwl_txq *txq, int index); -- cgit From 80fa8377f5c64aac66699f98186605f7fa25089e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:49 +0300 Subject: wifi: iwlwifi: queue: move iwl_txq_gen2_set_tb() up We need this earlier in the file next, move it up to have an easier to read change, since this moves other things in the diff git generates by default. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.c6d798b600bb.I9b891ee3d3dc67822a28e44941409f5b7cb637cf@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 71 +++++++++++++-------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 5b1100e6e1d1..95c2af54ea46 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -84,6 +84,41 @@ static u8 iwl_txq_gen2_get_num_tbs(struct iwl_trans *trans, return le16_to_cpu(tfd->num_tbs) & 0x1f; } +int iwl_txq_gen2_set_tb(struct iwl_trans *trans, struct iwl_tfh_tfd *tfd, + dma_addr_t addr, u16 len) +{ + int idx = iwl_txq_gen2_get_num_tbs(trans, tfd); + struct iwl_tfh_tb *tb; + + /* Only WARN here so we know about the issue, but we mess up our + * unmap path because not every place currently checks for errors + * returned from this function - it can only return an error if + * there's no more space, and so when we know there is enough we + * don't always check ... + */ + WARN(iwl_txq_crosses_4g_boundary(addr, len), + "possible DMA problem with iova:0x%llx, len:%d\n", + (unsigned long long)addr, len); + + if (WARN_ON(idx >= IWL_TFH_NUM_TBS)) + return -EINVAL; + tb = &tfd->tbs[idx]; + + /* Each TFD can point to a maximum max_tbs Tx buffers */ + if (le16_to_cpu(tfd->num_tbs) >= trans->txqs.tfd.max_tbs) { + IWL_ERR(trans, "Error can not send more than %d chunks\n", + trans->txqs.tfd.max_tbs); + return -EINVAL; + } + + put_unaligned_le64(addr, &tb->addr); + tb->tb_len = cpu_to_le16(len); + + tfd->num_tbs = cpu_to_le16(idx + 1); + + return idx; +} + void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans, struct iwl_cmd_meta *meta, struct iwl_tfh_tfd *tfd) { @@ -142,42 +177,6 @@ void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) } } -int iwl_txq_gen2_set_tb(struct iwl_trans *trans, struct iwl_tfh_tfd *tfd, - dma_addr_t addr, u16 len) -{ - int idx = iwl_txq_gen2_get_num_tbs(trans, tfd); - struct iwl_tfh_tb *tb; - - /* - * Only WARN here so we know about the issue, but we mess up our - * unmap path because not every place currently checks for errors - * returned from this function - it can only return an error if - * there's no more space, and so when we know there is enough we - * don't always check ... - */ - WARN(iwl_txq_crosses_4g_boundary(addr, len), - "possible DMA problem with iova:0x%llx, len:%d\n", - (unsigned long long)addr, len); - - if (WARN_ON(idx >= IWL_TFH_NUM_TBS)) - return -EINVAL; - tb = &tfd->tbs[idx]; - - /* Each TFD can point to a maximum max_tbs Tx buffers */ - if (le16_to_cpu(tfd->num_tbs) >= trans->txqs.tfd.max_tbs) { - IWL_ERR(trans, "Error can not send more than %d chunks\n", - trans->txqs.tfd.max_tbs); - return -EINVAL; - } - - put_unaligned_le64(addr, &tb->addr); - tb->tb_len = cpu_to_le16(len); - - tfd->num_tbs = cpu_to_le16(idx + 1); - - return idx; -} - static struct page *get_workaround_page(struct iwl_trans *trans, struct sk_buff *skb) { -- cgit From c83031afaaaa4a1129394439c8cd93ffe94f9970 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:50 +0300 Subject: wifi: iwlwifi: pcie: point invalid TFDs to invalid data There are occasionally bugs which cause the device to try to use a TFD that it wasn't supposed to, and these are very hard to diagnose. Fill all unused TFDs with a debug command that immediately causes an error to be detected in these cases. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.10a9af1ca91f.Ifc790d62c52b4bc9a74c9581610af498509f5759@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/api/debug.h | 5 +++ drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 3 ++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 29 ++++++++++++++++ drivers/net/wireless/intel/iwlwifi/queue/tx.c | 40 +++++++++++++++++++---- 4 files changed, 71 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 48ffab22bb7b..90ce8d9b6ad3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -29,6 +29,11 @@ enum iwl_debug_cmds { * &struct iwl_dbg_host_event_cfg_cmd */ HOST_EVENT_CFG = 0x3, + /** + * @INVALID_WR_PTR_CMD: invalid write pointer, set in the TFD + * when it's not in use + */ + INVALID_WR_PTR_CMD = 0x6, /** * @DBGC_SUSPEND_RESUME: * DBGC suspend/resume commad. Uses a single dword as data: diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 8a6ddb5fb0c3..3b6b0e03037f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1069,6 +1069,7 @@ struct iwl_trans_txqs { * @mbx_addr_1_step: step address data 1 * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*), * only valid for discrete (not integrated) NICs + * @invalid_tx_cmd: invalid TX command buffer */ struct iwl_trans { bool csme_own; @@ -1133,6 +1134,8 @@ struct iwl_trans { u8 pcie_link_speed; + struct iwl_dma_ptr invalid_tx_cmd; + /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char trans_specific[] __aligned(sizeof(void *)); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 2096f7158728..198933f853c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2018,6 +2018,30 @@ void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions memset(desc_dram, 0, sizeof(*desc_dram)); } +static void iwl_pcie_free_invalid_tx_cmd(struct iwl_trans *trans) +{ + iwl_pcie_free_dma_ptr(trans, &trans->invalid_tx_cmd); +} + +static int iwl_pcie_alloc_invalid_tx_cmd(struct iwl_trans *trans) +{ + struct iwl_cmd_header_wide bad_cmd = { + .cmd = INVALID_WR_PTR_CMD, + .group_id = DEBUG_GROUP, + .sequence = cpu_to_le16(0xffff), + .length = cpu_to_le16(0), + .version = 0, + }; + int ret; + + ret = iwl_pcie_alloc_dma_ptr(trans, &trans->invalid_tx_cmd, + sizeof(bad_cmd)); + if (ret) + return ret; + memcpy(trans->invalid_tx_cmd.addr, &bad_cmd, sizeof(bad_cmd)); + return 0; +} + void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -2048,6 +2072,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_ict(trans); } + iwl_pcie_free_invalid_tx_cmd(trans); + iwl_pcie_free_fw_monitor(trans); iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data, @@ -3684,6 +3710,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, init_waitqueue_head(&trans_pcie->sx_waitq); + ret = iwl_pcie_alloc_invalid_tx_cmd(trans); + if (ret) + goto out_no_pci; if (trans_pcie->msix_enabled) { ret = iwl_pcie_init_msix_handler(pdev, trans_pcie); diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 95c2af54ea46..340240b8954f 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -10,6 +10,7 @@ #include "fw/api/commands.h" #include "fw/api/tx.h" #include "fw/api/datapath.h" +#include "fw/api/debug.h" #include "queue/tx.h" #include "iwl-fh.h" #include "iwl-scd.h" @@ -119,6 +120,15 @@ int iwl_txq_gen2_set_tb(struct iwl_trans *trans, struct iwl_tfh_tfd *tfd, return idx; } +static void iwl_txq_set_tfd_invalid_gen2(struct iwl_trans *trans, + struct iwl_tfh_tfd *tfd) +{ + tfd->num_tbs = 0; + + iwl_txq_gen2_set_tb(trans, tfd, trans->invalid_tx_cmd.dma, + trans->invalid_tx_cmd.size); +} + void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans, struct iwl_cmd_meta *meta, struct iwl_tfh_tfd *tfd) { @@ -146,7 +156,7 @@ void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans, struct iwl_cmd_meta *meta, DMA_TO_DEVICE); } - tfd->num_tbs = 0; + iwl_txq_set_tfd_invalid_gen2(trans, tfd); } void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) @@ -1025,11 +1035,21 @@ static void iwl_txq_stuck_timer(struct timer_list *t) iwl_force_nmi(trans); } +static void iwl_txq_set_tfd_invalid_gen1(struct iwl_trans *trans, + struct iwl_tfd *tfd) +{ + tfd->num_tbs = 0; + + iwl_pcie_gen1_tfd_set_tb(trans, tfd, 0, trans->invalid_tx_cmd.dma, + trans->invalid_tx_cmd.size); +} + int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, bool cmd_queue) { - size_t tfd_sz = trans->txqs.tfd.size * - trans->trans_cfg->base_params->max_tfd_queue_size; + size_t num_entries = trans->trans_cfg->gen2 ? + slots_num : trans->trans_cfg->base_params->max_tfd_queue_size; + size_t tfd_sz; size_t tb0_buf_sz; int i; @@ -1039,8 +1059,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, if (WARN_ON(txq->entries || txq->tfds)) return -EINVAL; - if (trans->trans_cfg->gen2) - tfd_sz = trans->txqs.tfd.size * slots_num; + tfd_sz = trans->txqs.tfd.size * num_entries; timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0); txq->trans = trans; @@ -1080,6 +1099,15 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, if (!txq->first_tb_bufs) goto err_free_tfds; + for (i = 0; i < num_entries; i++) { + void *tfd = iwl_txq_get_tfd(trans, txq, i); + + if (trans->trans_cfg->gen2) + iwl_txq_set_tfd_invalid_gen2(trans, tfd); + else + iwl_txq_set_tfd_invalid_gen1(trans, tfd); + } + return 0; err_free_tfds: dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr); @@ -1397,7 +1425,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, meta->tbs = 0; - tfd->num_tbs = 0; + iwl_txq_set_tfd_invalid_gen1(trans, tfd); } #define IWL_TX_CRC_SIZE 4 -- cgit From 533d93086248735aa958bccbbb13053e9031f9ba Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Wed, 16 Aug 2023 11:10:51 +0300 Subject: wifi: iwlwifi: add Razer to ppag approved list Add a new vendor (Razer) to PPAG approved list. Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.f586a86fa644.I97408afb20bd7c46fcff8c3561ead8ed9c60b37e@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index dfe8357036eb..b26f90e52256 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -69,6 +69,11 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), }, }, + { .ident = "RAZER", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Razer"), + }, + }, {} }; -- cgit From 0922a71079038b565b249a5926b4f8ba7ed62893 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:52 +0300 Subject: wifi: iwlwifi: mvm: enable HE TX/RX <242 tone RU on new RFs Two new RFs were added in the code, but we forgot to add them to the list here that enables HE TX/RX 1024 QAM less than 242 tone RU. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.ddb090c86c8c.Ic630aa579e3dc52069758d8698069480d555eefe@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 8c23f57f5c89..31176897b746 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -990,6 +990,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, case IWL_CFG_RF_TYPE_GF: case IWL_CFG_RF_TYPE_MR: case IWL_CFG_RF_TYPE_MS: + case IWL_CFG_RF_TYPE_FM: + case IWL_CFG_RF_TYPE_WH: iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; if (!is_ap) -- cgit From d09d290ae39345fb914163e45ee2b42f8c938f7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Aug 2023 11:10:53 +0300 Subject: wifi: iwlwifi: mvm: support flush on AP interfaces Support TX flush on AP interfaces so that we will do a proper flush for frames on the queue before keys are removed. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.f4b749b91ec2.Ia8381bd4f7d47592e74387c564739798a01c4049@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index e7fe5b76def4..5918c1f2b10c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -5605,9 +5605,6 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return; } - if (vif->type != NL80211_IFTYPE_STATION) - return; - /* Make sure we're done with the deferred traffic before flushing */ flush_work(&mvm->add_stream_wk); @@ -5631,9 +5628,6 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ap_sta_done = true; } - /* make sure only TDLS peers or the AP are flushed */ - WARN_ON_ONCE(sta != mvmvif->ap_sta && !sta->tdls); - if (drop) { if (iwl_mvm_flush_sta(mvm, mvmsta, false)) IWL_ERR(mvm, "flush request fail\n"); -- cgit From d166a5c9775f8cc0b20e3331e238844a3fe57fa1 Mon Sep 17 00:00:00 2001 From: Mukesh Sisodiya Date: Wed, 16 Aug 2023 11:10:54 +0300 Subject: wifi: iwlwifi: remove memory check for LMAC error address LMAC error table address was checked against UMAC error table minimum address defined. Because of that, the LMAC error table was not read, since both addresses belong to different ranges. As addresses are updated from FW alive message and should be correct, this check is not needed. Still keep the check for address 0 to avoid NULL address read. Signed-off-by: Mukesh Sisodiya Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230816104355.08ab1497904d.I270d4c5bcc23c5ecd0b7db475501032c450852ad@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 5876f917e536..8f107ceec407 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -182,8 +182,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu base = fwrt->fw->inst_errlog_ptr; } - if ((fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && !base) || - (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ && base < 0x400000)) { + if (!base) { IWL_ERR(fwrt, "Not valid error log pointer 0x%08X for %s uCode\n", base, -- cgit From 057381ddac0593c6e4ca8f58732830d8542b9c4e Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 22 Aug 2023 10:33:15 +0300 Subject: wifi: iwlwifi: pcie: avoid a warning in case prepare card failed In case CSME holds the NIC and SAP connection is already established, iwl_pcie_prepare_card_hw() during iwl_pci_probe() will fail (which is fine since CSME will release the nic later when asked with a SAP message). In this case tring to grab nic access to read the crf ids will fail with a warning. Avoid the warning by only trying to read the crf ids in case prepare card succeeded. Signed-off-by: Avraham Stern Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230822103048.9b026fa7b97e.I12bea7e6eef54eeeaf916b68d71583e92ff310fd@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 73c1fb3c0c5e..bc83d2ba55c6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1132,12 +1132,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans) else sd_reg_ver_addr = SD_REG_VER; - if (!iwl_trans_grab_nic_access(iwl_trans)) { - IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n"); - ret = -EIO; - goto out; - } - /* Enable access to peripheral registers */ val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG); val |= ENABLE_WFPM; @@ -1157,9 +1151,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans) iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id, iwl_trans->hw_wfpm_id); - iwl_trans_release_nic_access(iwl_trans); - -out: return ret; } @@ -1351,6 +1342,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_free_trans; if (iwl_trans_grab_nic_access(iwl_trans)) { + get_crf_id(iwl_trans); /* all good */ iwl_trans_release_nic_access(iwl_trans); } else { @@ -1360,7 +1352,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); - get_crf_id(iwl_trans); /* * The RF_ID is set to zero in blank OTP so read version to -- cgit From ef030ab17e060b0ef47028e86cf85b68988b56ae Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 22 Aug 2023 10:33:16 +0300 Subject: wifi: iwlmei: don't send SAP messages if AMT is disabled SAP messages should not be sent when AMT is disabled. Signed-off-by: Avraham Stern Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230822103048.db16b55c27c1.I48834c14f5af8d31792f5048b3023509cba191dd@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mei/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 54445f39fd55..908506f98242 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021-2022 Intel Corporation + * Copyright (C) 2021-2023 Intel Corporation */ #include @@ -1532,7 +1532,7 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1561,7 +1561,7 @@ void iwl_mei_host_disassociated(void) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1597,7 +1597,7 @@ void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1626,7 +1626,7 @@ void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1654,7 +1654,7 @@ void iwl_mei_set_country_code(u16 mcc) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1680,7 +1680,7 @@ void iwl_mei_set_power_limit(const __le16 *power_limit) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei && !mei->amt_enabled) + if (!mei || !mei->amt_enabled) goto out; memcpy(msg.sar_chain_info_table, power_limit, sizeof(msg.sar_chain_info_table)); -- cgit From 3243aee1cb9206521c82a49fa5879934c69cee7c Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 22 Aug 2023 10:33:17 +0300 Subject: wifi: iwlmei: send HOST_GOES_DOWN message even if wiamt is disabled The HOST_GOES_DOWN message should be sent even if wiamt is disabled. Otherwise wiamt may still use the shared memory (e.g. if enabled later) while it's no longer valid. Signed-off-by: Avraham Stern Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230822103048.2baad50eb1c3.If7b7c1dc2d6bfc6bacf7f6c72972f19714d9d973@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mei/main.c | 42 ++++++++++++--------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 908506f98242..27f45f5ea264 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -2070,33 +2070,29 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) mutex_lock(&iwl_mei_mutex); - if (mei->amt_enabled) { - /* - * Tell CSME that we are going down so that it won't access the - * memory anymore, make sure this message goes through immediately. - */ - mei->csa_throttled = false; - iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_HOST_GOES_DOWN); - - for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { - if (!iwl_mei_host_to_me_data_pending(mei)) - break; + /* Tell CSME that we are going down so that it won't access the + * memory anymore, make sure this message goes through immediately. + */ + mei->csa_throttled = false; + iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_HOST_GOES_DOWN); - msleep(20); - } + for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { + if (!iwl_mei_host_to_me_data_pending(mei)) + break; - /* - * If we couldn't make sure that CSME saw the HOST_GOES_DOWN - * message, it means that it will probably keep reading memory - * that we are going to unmap and free, expect IOMMU error - * messages. - */ - if (i == SEND_SAP_MAX_WAIT_ITERATION) - dev_err(&mei->cldev->dev, - "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); + msleep(20); } + /* If we couldn't make sure that CSME saw the HOST_GOES_DOWN + * message, it means that it will probably keep reading memory + * that we are going to unmap and free, expect IOMMU error + * messages. + */ + if (i == SEND_SAP_MAX_WAIT_ITERATION) + dev_err(&mei->cldev->dev, + "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); + mutex_unlock(&iwl_mei_mutex); /* -- cgit From a7d9ac48a6512acdb81bb3d1f55c7b30d9b9d1c0 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 22 Aug 2023 10:33:18 +0300 Subject: wifi: iwlmei: send driver down SAP message only if wiamt is enabled When wiamt is disabled the driver up SAP message is not sent, so there is no need to send the driver down message as well. Signed-off-by: Avraham Stern Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230822103048.100f41b84656.I583d3e18ea65793f53aa710af13e47f8af82b53d@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mei/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 27f45f5ea264..78b78a772f54 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -1832,7 +1832,9 @@ void iwl_mei_unregister_complete(void) struct iwl_mei *mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - iwl_mei_send_sap_msg(mei->cldev, SAP_MSG_NOTIF_WIFIDR_DOWN); + if (mei->amt_enabled) + iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_WIFIDR_DOWN); mei->got_ownership = false; } -- cgit From 6d2c360b4badf78fb778afe1f5b85196ff18383e Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 22 Aug 2023 10:33:19 +0300 Subject: wifi: iwlmei: don't send nic info with invalid mac address In case the SAP connection is established before the interface is added, the mac address is still not set. Don't send the nic info SAP message in this case since it will result in sending an invalid mac address. The nic info message will be sent with a valid mac address when the interface is added. Signed-off-by: Avraham Stern Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20230822103048.a49436bed387.I0ca88d72456e6e9f939bbc2e0c52ffb173fbc97e@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mei/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 78b78a772f54..1dd9106c6513 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -774,9 +774,13 @@ static void iwl_mei_set_init_conf(struct iwl_mei *mei) iwl_mei_send_sap_msg_payload(mei->cldev, &sar_msg.hdr); } - ether_addr_copy(nic_info_msg.mac_address, iwl_mei_cache.mac_address); - ether_addr_copy(nic_info_msg.nvm_address, iwl_mei_cache.nvm_address); - iwl_mei_send_sap_msg_payload(mei->cldev, &nic_info_msg.hdr); + if (is_valid_ether_addr(iwl_mei_cache.mac_address)) { + ether_addr_copy(nic_info_msg.mac_address, + iwl_mei_cache.mac_address); + ether_addr_copy(nic_info_msg.nvm_address, + iwl_mei_cache.nvm_address); + iwl_mei_send_sap_msg_payload(mei->cldev, &nic_info_msg.hdr); + } iwl_mei_send_sap_msg_payload(mei->cldev, &rfkill_msg.hdr); } -- cgit From 691b2bf1494620ff8c292626e4967c57e5705a8b Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Mon, 21 Aug 2023 18:10:08 +0800 Subject: bonding: update port speed when getting bond speed Andrew reported a bonding issue that if we put an active-back bond on top of a 802.3ad bond interface. When the 802.3ad bond's speed/duplex changed dynamically. The upper bonding interface's speed/duplex can't be changed at the same time, which will show incorrect speed. Fix it by updating the port speed when calling ethtool. Reported-by: Andrew Schorr Closes: https://lore.kernel.org/netdev/ZEt3hvyREPVdbesO@Laptop-X1/ Signed-off-by: Hangbin Liu Acked-by: Jay Vosburgh Link: https://lore.kernel.org/r/20230821101008.797482-1-liuhangbin@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f398bec78457..ed7212e61c54 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5718,6 +5718,7 @@ static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev, */ bond_for_each_slave(bond, slave, iter) { if (bond_slave_can_tx(slave)) { + bond_update_speed_duplex(slave); if (slave->speed != SPEED_UNKNOWN) { if (BOND_MODE(bond) == BOND_MODE_BROADCAST) speed = bond_mode_bcast_speed(slave, -- cgit From f708ed71775d2216d829fe6e00f1b4c6b38bc03c Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 21 Aug 2023 10:57:09 +0300 Subject: wifi: ath5k: Remove redundant dev_err() There is no need to call the dev_err() function directly to print a custom message when handling an error from platform_get_irq() function as it is going to display an appropriate error message in case of a failure. Signed-off-by: Ruan Jinjie Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726171235.2475625-1-ruanjinjie@huawei.com --- drivers/net/wireless/ath/ath5k/ahb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 28a1e5eff204..08bd5d3b00f1 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -115,7 +115,6 @@ static int ath_ahb_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq); ret = irq; goto err_iounmap; } -- cgit From b674fb513e2e7a514fcde287c0f73915d393fdb6 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Tue, 25 Apr 2023 22:26:06 +0300 Subject: wifi: ath9k: fix races between ath9k_wmi_cmd and ath9k_wmi_ctrl_rx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the synchronization between ath9k_wmi_cmd() and ath9k_wmi_ctrl_rx() is exposed to a race condition which, although being rather unlikely, can lead to invalid behaviour of ath9k_wmi_cmd(). Consider the following scenario: CPU0 CPU1 ath9k_wmi_cmd(...) mutex_lock(&wmi->op_mutex) ath9k_wmi_cmd_issue(...) wait_for_completion_timeout(...) --- timeout --- /* the callback is being processed * before last_seq_id became zero */ ath9k_wmi_ctrl_rx(...) spin_lock_irqsave(...) /* wmi->last_seq_id check here * doesn't detect timeout yet */ spin_unlock_irqrestore(...) /* last_seq_id is zeroed to * indicate there was a timeout */ wmi->last_seq_id = 0 mutex_unlock(&wmi->op_mutex) return -ETIMEDOUT ath9k_wmi_cmd(...) mutex_lock(&wmi->op_mutex) /* the buffer is replaced with * another one */ wmi->cmd_rsp_buf = rsp_buf wmi->cmd_rsp_len = rsp_len ath9k_wmi_cmd_issue(...) spin_lock_irqsave(...) spin_unlock_irqrestore(...) wait_for_completion_timeout(...) /* the continuation of the * callback left after the first * ath9k_wmi_cmd call */ ath9k_wmi_rsp_callback(...) /* copying data designated * to already timeouted * WMI command into an * inappropriate wmi_cmd_buf */ memcpy(...) complete(&wmi->cmd_wait) /* awakened by the bogus callback * => invalid return result */ mutex_unlock(&wmi->op_mutex) return 0 To fix this, update last_seq_id on timeout path inside ath9k_wmi_cmd() under the wmi_lock. Move ath9k_wmi_rsp_callback() under wmi_lock inside ath9k_wmi_ctrl_rx() so that the wmi->cmd_wait can be completed only for initially designated wmi_cmd call, otherwise the path would be rejected with last_seq_id check. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: fb9987d0f748 ("ath9k_htc: Support for AR9271 chipset.") Signed-off-by: Fedor Pchelkin Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230425192607.18015-1-pchelkin@ispras.ru --- drivers/net/wireless/ath/ath9k/wmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index d652c647d56b..04f363cb90fe 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -242,10 +242,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, spin_unlock_irqrestore(&wmi->wmi_lock, flags); goto free_skb; } - spin_unlock_irqrestore(&wmi->wmi_lock, flags); /* WMI command response */ ath9k_wmi_rsp_callback(wmi, skb); + spin_unlock_irqrestore(&wmi->wmi_lock, flags); free_skb: kfree_skb(skb); @@ -308,8 +308,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, struct ath_common *common = ath9k_hw_common(ah); u16 headroom = sizeof(struct htc_frame_hdr) + sizeof(struct wmi_cmd_hdr); + unsigned long time_left, flags; struct sk_buff *skb; - unsigned long time_left; int ret = 0; if (ah->ah_flags & AH_UNPLUGGED) @@ -345,7 +345,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, if (!time_left) { ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n", wmi_cmd_to_name(cmd_id)); + spin_lock_irqsave(&wmi->wmi_lock, flags); wmi->last_seq_id = 0; + spin_unlock_irqrestore(&wmi->wmi_lock, flags); mutex_unlock(&wmi->op_mutex); return -ETIMEDOUT; } -- cgit From 454994cfa9e4c18b6df9f78b60db8eadc20a6c25 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Tue, 25 Apr 2023 22:26:07 +0300 Subject: wifi: ath9k: protect WMI command response buffer replacement with a lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If ath9k_wmi_cmd() has exited with a timeout, it is possible that during next ath9k_wmi_cmd() call the wmi_rsp callback for previous wmi command writes to new wmi->cmd_rsp_buf and makes a completion. This results in an invalid ath9k_wmi_cmd() return value. Move the replacement of WMI command response buffer and length under wmi_lock. Note that last_seq_id value is updated there, too. Thus, the buffer cannot be written to by a belated wmi_rsp callback because that path is properly rejected by the last_seq_id check. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: fb9987d0f748 ("ath9k_htc: Support for AR9271 chipset.") Signed-off-by: Fedor Pchelkin Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230425192607.18015-2-pchelkin@ispras.ru --- drivers/net/wireless/ath/ath9k/wmi.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 04f363cb90fe..1476b42b52a9 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -283,7 +283,8 @@ int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, static int ath9k_wmi_cmd_issue(struct wmi *wmi, struct sk_buff *skb, - enum wmi_cmd_id cmd, u16 len) + enum wmi_cmd_id cmd, u16 len, + u8 *rsp_buf, u32 rsp_len) { struct wmi_cmd_hdr *hdr; unsigned long flags; @@ -293,6 +294,11 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); spin_lock_irqsave(&wmi->wmi_lock, flags); + + /* record the rsp buffer and length */ + wmi->cmd_rsp_buf = rsp_buf; + wmi->cmd_rsp_len = rsp_len; + wmi->last_seq_id = wmi->tx_seq_id; spin_unlock_irqrestore(&wmi->wmi_lock, flags); @@ -333,11 +339,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, goto out; } - /* record the rsp buffer and length */ - wmi->cmd_rsp_buf = rsp_buf; - wmi->cmd_rsp_len = rsp_len; - - ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); + ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len, rsp_buf, rsp_len); if (ret) goto out; -- cgit From 6edb4ba6fb5b946d112259f54f4657f82eb71e89 Mon Sep 17 00:00:00 2001 From: Minjie Du Date: Wed, 12 Jul 2023 19:47:40 +0800 Subject: wifi: ath9k: fix parameter check in ath9k_init_debug() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make IS_ERR() judge the debugfs_create_dir() function return in ath9k_init_debug() Signed-off-by: Minjie Du Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230712114740.13226-1-duminjie@vivo.com --- drivers/net/wireless/ath/ath9k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index fb7a2952d0ce..995c6e705637 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1420,7 +1420,7 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy = debugfs_create_dir("ath9k", sc->hw->wiphy->debugfsdir); - if (!sc->debug.debugfs_phy) + if (IS_ERR(sc->debug.debugfs_phy)) return -ENOMEM; #ifdef CONFIG_ATH_DEBUG -- cgit From 8b804643f42db68a1b7c56dc90a2fe5da6e5cf83 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 26 Jul 2023 21:50:08 +0300 Subject: wifi: ath9k: consistently use kstrtoX_from_user() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use 'kstrtoul_from_user()' and 'kstrtobool_from_user()' where appropriate and thus avoid some code duplication. Signed-off-by: Dmitry Antipov Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230726185046.188225-1-dmantipov@yandex.ru --- drivers/net/wireless/ath/ath9k/common-spectral.c | 53 ++++-------- drivers/net/wireless/ath/ath9k/debug.c | 106 +++++++---------------- drivers/net/wireless/ath/ath9k/dfs_debug.c | 14 +-- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 13 +-- drivers/net/wireless/ath/ath9k/tx99.c | 14 +-- 5 files changed, 61 insertions(+), 139 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index e055adfb5361..a5349c72c332 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -855,16 +855,11 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, { struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 1) return -EINVAL; @@ -903,17 +898,11 @@ static ssize_t write_file_spectral_count(struct file *file, { struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ssize_t ret; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 255) return -EINVAL; @@ -951,16 +940,11 @@ static ssize_t write_file_spectral_period(struct file *file, { struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 255) return -EINVAL; @@ -999,16 +983,11 @@ static ssize_t write_file_spectral_fft_period(struct file *file, { struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 15) return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 995c6e705637..9bc57c5a89bf 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -96,21 +96,16 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf, } static ssize_t write_file_debug(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long mask; - char buf[32]; - ssize_t len; + ssize_t ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &mask)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &mask); + if (ret) + return ret; common->debug_mask = mask; return count; @@ -191,16 +186,11 @@ static ssize_t write_file_ani(struct file *file, struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long ani; - char buf[32]; - ssize_t len; + ssize_t ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &ani)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &ani); + if (ret) + return ret; if (ani > 1) return -EINVAL; @@ -248,20 +238,15 @@ static ssize_t write_file_bt_ant_diversity(struct file *file, struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_hw_capabilities *pCap = &sc->sc_ah->caps; unsigned long bt_ant_diversity; - char buf[32]; - ssize_t len; + ssize_t ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ret = kstrtoul_from_user(user_buf, count, 0, &bt_ant_diversity); + if (ret) + return ret; if (!(pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) goto exit; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &bt_ant_diversity)) - return -EINVAL; - common->bt_ant_diversity = !!bt_ant_diversity; ath9k_ps_wakeup(sc); ath9k_hw_set_bt_ant_diversity(sc->sc_ah, common->bt_ant_diversity); @@ -792,16 +777,11 @@ static ssize_t write_file_reset(struct file *file, struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val != 1) return -EINVAL; @@ -886,16 +866,11 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, { struct ath_softc *sc = file->private_data; unsigned long regidx; - char buf[32]; - ssize_t len; + ssize_t ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, ®idx)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, ®idx); + if (ret) + return ret; sc->debug.regidx = regidx; return count; @@ -931,16 +906,11 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; unsigned long regval; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, ®val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, ®val); + if (ret) + return ret; ath9k_ps_wakeup(sc); REG_WRITE_D(ah, sc->debug.regidx, regval); @@ -1128,16 +1098,11 @@ static ssize_t write_file_wow(struct file *file, const char __user *user_buf, { struct ath_softc *sc = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val != 1) return -EINVAL; @@ -1191,17 +1156,12 @@ static ssize_t write_file_tpc(struct file *file, const char __user *user_buf, struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; unsigned long val; - char buf[32]; - ssize_t len; + ssize_t ret; bool tpc_enabled; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 1) return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 2a79c2fa8415..8e18e9b4ef48 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c @@ -99,17 +99,11 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf, { struct ath_softc *sc = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ssize_t ret; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val == DFS_STATS_RESET_MAGIC) memset(&sc->debug.stats.dfs_stats, 0, sizeof(sc->debug.stats.dfs_stats)); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index b3ed65e5c4da..1ed2b1216bce 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -375,16 +375,11 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, struct ath9k_htc_priv *priv = file->private_data; struct ath_common *common = ath9k_hw_common(priv->ah); unsigned long mask; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &mask)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &mask); + if (ret) + return ret; common->debug_mask = mask; return count; diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 8a996ed9a3be..f2144fd39093 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -172,9 +172,8 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - char buf[32]; bool start; - ssize_t len; + ssize_t ret; int r; if (count < 1) @@ -183,14 +182,9 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, if (sc->cur_chan->nvifs > 1) return -EOPNOTSUPP; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - - if (kstrtobool(buf, &start)) - return -EINVAL; + ret = kstrtobool_from_user(user_buf, count, &start); + if (ret) + return ret; mutex_lock(&sc->mutex); -- cgit From b2fd72aafb13118503df6798b18ed28f83dda2c2 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 31 Jul 2023 20:44:55 +0800 Subject: wifi: ath9k: Remove unnecessary ternary operators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ther are a little ternary operators, the true or false judgement of which is unnecessary in C language semantics. Signed-off-by: Ruan Jinjie Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230731124455.2039184-1-ruanjinjie@huawei.com --- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 3 +-- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 3caa149b1013..fd5312c2a7e3 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -572,8 +572,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, } for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = - (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false; + bool isHt40CtlMode = pCtlMode[ctlMode] == CTL_2GHT40; if (isHt40CtlMode) freq = centers.synth_center; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 27ff1ca2631f..e5414435b141 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1432,7 +1432,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); struct hif_device_usb *hif_dev = usb_get_intfdata(interface); - bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; + bool unplugged = udev->state == USB_STATE_NOTATTACHED; if (!hif_dev) return; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 51766de5ec3b..44e02cfe2438 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -719,7 +719,7 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, aggr.sta_index = ista->index; aggr.tidno = tid & 0xf; - aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false; + aggr.aggr_enable = action == IEEE80211_AMPDU_TX_START; WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); if (ret) -- cgit From 383e1b6a90c33f6e48dd39691e8b9000145247b6 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Thu, 10 Aug 2023 22:52:22 +0800 Subject: wifi: ath9k: Remove unused declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b57ba3b2f7b0 ("ath9k: move ath9k_reload_chainmask_settings to common") removed the implementation ath9k_reload_chainmask_settings() but not the declaration. Also commit 978f78bf7137 ("ath9k_hw: Move bt_stomp to hw from common.") left behind ath9k_cmn_btcoex_bt_stomp() declaration. Signed-off-by: Yue Haibing Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230810145222.34364-1-yuehaibing@huawei.com --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/common.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2cc23605c9fc..668fc07b3073 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1129,7 +1129,6 @@ void ath_restart_work(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); -void ath9k_reload_chainmask_settings(struct ath_softc *sc); u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); void ath_start_rfkill_poll(struct ath_softc *sc); void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index f0ab6f9955e4..12204cf86fcf 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -85,8 +85,6 @@ struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, struct ath_hw *ah, struct cfg80211_chan_def *chandef); int ath9k_cmn_count_streams(unsigned int chainmask, int max); -void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, - enum ath_stomp_type stomp_type); void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, u16 new_txpow, u16 *txpower); void ath9k_cmn_init_crypto(struct ath_hw *ah); -- cgit From 73582f090f053ffdd168f6c2b42b18c67906d120 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 20:55:01 +0800 Subject: net: dsa: microchip: Remove unused declarations Commit 91a98917a883 ("net: dsa: microchip: move switch chip_id detection to ksz_common") removed ksz8_switch_detect() but not its declaration. Commit 6ec23aaaac43 ("net: dsa: microchip: move ksz_dev_ops to ksz_common.c") declared but never implemented other functions. Signed-off-by: Yue Haibing Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230821125501.19624-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz8.h | 2 -- drivers/net/dsa/microchip/ksz9477.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h index e68465fdf6b9..4cea811e73ac 100644 --- a/drivers/net/dsa/microchip/ksz8.h +++ b/drivers/net/dsa/microchip/ksz8.h @@ -48,13 +48,11 @@ int ksz8_port_mirror_add(struct ksz_device *dev, int port, bool ingress, struct netlink_ext_ack *extack); void ksz8_port_mirror_del(struct ksz_device *dev, int port, struct dsa_mall_mirror_tc_entry *mirror); -int ksz8_get_stp_reg(void); void ksz8_get_caps(struct ksz_device *dev, int port, struct phylink_config *config); void ksz8_config_cpu_port(struct dsa_switch *ds); int ksz8_enable_stp_addr(struct ksz_device *dev); int ksz8_reset_switch(struct ksz_device *dev); -int ksz8_switch_detect(struct ksz_device *dev); int ksz8_switch_init(struct ksz_device *dev); void ksz8_switch_exit(struct ksz_device *dev); int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu); diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h index b6f7e3c46e3f..a6f425866a29 100644 --- a/drivers/net/dsa/microchip/ksz9477.h +++ b/drivers/net/dsa/microchip/ksz9477.h @@ -36,7 +36,6 @@ int ksz9477_port_mirror_add(struct ksz_device *dev, int port, bool ingress, struct netlink_ext_ack *extack); void ksz9477_port_mirror_del(struct ksz_device *dev, int port, struct dsa_mall_mirror_tc_entry *mirror); -int ksz9477_get_stp_reg(void); void ksz9477_get_caps(struct ksz_device *dev, int port, struct phylink_config *config); int ksz9477_fdb_dump(struct ksz_device *dev, int port, @@ -54,7 +53,6 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds); int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val); int ksz9477_enable_stp_addr(struct ksz_device *dev); int ksz9477_reset_switch(struct ksz_device *dev); -int ksz9477_dsa_init(struct ksz_device *dev); int ksz9477_switch_init(struct ksz_device *dev); void ksz9477_switch_exit(struct ksz_device *dev); void ksz9477_port_queue_split(struct ksz_device *dev, int port); -- cgit From 49e62a0462a2d669e35f97eb3e0a6f2aab20518d Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 21:02:18 +0800 Subject: net: mscc: ocelot: Remove unused declarations Commit 6c30384eb1de ("net: mscc: ocelot: register devlink ports") declared but never implemented ocelot_devlink_init() and ocelot_devlink_teardown(). Commit 2096805497e2 ("net: mscc: ocelot: automatically detect VCAP constants") declared but never implemented ocelot_detect_vcap_constants(). Commit 403ffc2c34de ("net: mscc: ocelot: add support for preemptible traffic classes") declared but never implemented ocelot_port_update_preemptible_tcs(). Signed-off-by: Yue Haibing Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20230821130218.19096-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.h | 2 -- drivers/net/ethernet/mscc/ocelot_vcap.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 87f2055c242c..e50be508c166 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -97,8 +97,6 @@ int ocelot_netdev_to_port(struct net_device *dev); int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, struct device_node *portnp); void ocelot_release_port(struct ocelot_port *ocelot_port); -int ocelot_devlink_init(struct ocelot *ocelot); -void ocelot_devlink_teardown(struct ocelot *ocelot); int ocelot_port_devlink_init(struct ocelot *ocelot, int port, enum devlink_port_flavour flavour); void ocelot_port_devlink_teardown(struct ocelot *ocelot, int port); diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h index 523611ccc48f..6f546695faa5 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ b/drivers/net/ethernet/mscc/ocelot_vcap.h @@ -15,7 +15,6 @@ int ocelot_vcap_filter_stats_update(struct ocelot *ocelot, struct ocelot_vcap_filter *rule); -void ocelot_detect_vcap_constants(struct ocelot *ocelot); int ocelot_vcap_init(struct ocelot *ocelot); int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, -- cgit From efa47e80c2bfdd6cab9c9de014fca3e630eb6cfe Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 21:47:17 +0800 Subject: ionic: Remove unused declarations Commit fbfb8031533c ("ionic: Add hardware init and device commands") declared but never implemented ionic_q_rewind()/ionic_set_dma_mask(). Commit 969f84394604 ("ionic: sync the filters in the work task") declared but never implemented ionic_rx_filters_need_sync(). Signed-off-by: Yue Haibing Reviewed-by: Brett Creeley Acked-by: Shannon Nelson Link: https://lore.kernel.org/r/20230821134717.51936-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/pensando/ionic/ionic.h | 1 - drivers/net/ethernet/pensando/ionic/ionic_dev.h | 1 - drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h index 602f4d45d529..2453a40f6ee8 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic.h +++ b/drivers/net/ethernet/pensando/ionic/ionic.h @@ -81,7 +81,6 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait); int ionic_dev_cmd_wait_nomsg(struct ionic *ionic, unsigned long max_wait); void ionic_dev_cmd_dev_err_print(struct ionic *ionic, u8 opcode, u8 status, int err); -int ionic_set_dma_mask(struct ionic *ionic); int ionic_setup(struct ionic *ionic); int ionic_identify(struct ionic *ionic); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h index 0bea208bfba2..6aac98bcb9f4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h @@ -376,7 +376,6 @@ void ionic_q_cmb_map(struct ionic_queue *q, void __iomem *base, dma_addr_t base_ void ionic_q_sg_map(struct ionic_queue *q, void *base, dma_addr_t base_pa); void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb, void *cb_arg); -void ionic_q_rewind(struct ionic_queue *q, struct ionic_desc_info *start); void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info, unsigned int stop_index); int ionic_heartbeat_check(struct ionic *ionic); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h index 87b2666f248b..ee9e99cd1b5e 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h @@ -43,7 +43,6 @@ struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif, const u8 struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif); void ionic_rx_filter_sync(struct ionic_lif *lif); int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode); -int ionic_rx_filters_need_sync(struct ionic_lif *lif); int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid); int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid); -- cgit From dff96d7c0cda7cedcbfd382f15fa1c0908e8f317 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 21:55:56 +0800 Subject: net: microchip: Remove unused declarations Commit 264a9c5c9dff ("net: sparx5: Remove unused GLAG handling in PGID") removed sparx5_pgid_alloc_glag() but not its declaration. Commit 27d293cceee5 ("net: microchip: sparx5: Add support for rule count by cookie") removed vcap_rule_iter() but not its declaration. Commit 8beef08f4618 ("net: microchip: sparx5: Adding initial VCAP API support") declared but never implemented vcap_api_set_client(). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230821135556.43224-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/sparx5/sparx5_main.h | 1 - drivers/net/ethernet/microchip/vcap/vcap_api.h | 3 --- drivers/net/ethernet/microchip/vcap/vcap_api_client.h | 3 --- 3 files changed, 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index 89a9a7afa32c..6f565c0c0c3d 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -414,7 +414,6 @@ enum sparx5_pgid_type { }; void sparx5_pgid_init(struct sparx5 *spx5); -int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_free(struct sparx5 *spx5, u16 idx); diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.h b/drivers/net/ethernet/microchip/vcap/vcap_api.h index 62db270f65af..9eccfa633c1a 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.h @@ -277,7 +277,4 @@ struct vcap_control { struct list_head list; /* list of vcap instances */ }; -/* Set client control interface on the API */ -int vcap_api_set_client(struct vcap_control *vctrl); - #endif /* __VCAP_API__ */ diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h index d9d1f7c9d762..88641508f885 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h @@ -226,9 +226,6 @@ int vcap_chain_offset(struct vcap_control *vctrl, int from_cid, int to_cid); bool vcap_is_next_lookup(struct vcap_control *vctrl, int cur_cid, int next_cid); /* Is this chain id the last lookup of all VCAPs */ bool vcap_is_last_chain(struct vcap_control *vctrl, int cid, bool ingress); -/* Provide all rules via a callback interface */ -int vcap_rule_iter(struct vcap_control *vctrl, - int (*callback)(void *, struct vcap_rule *), void *arg); /* Match a list of keys against the keysets available in a vcap type */ bool vcap_rule_find_keysets(struct vcap_rule *rule, struct vcap_keyset_list *matches); -- cgit From a491add19faf335faa75d6baa69adb0a9a588df2 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 21:40:29 +0800 Subject: net: ethernet: ti: Remove unused declarations Commit e8609e69470f ("net: ethernet: ti: am65-cpsw: Convert to PHYLINK") removed am65_cpsw_nuss_adjust_link() but not its declaration. Commit 84640e27f230 ("net: netcp: Add Keystone NetCP core ethernet driver") declared but never implemented netcp_device_find_module(). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Acked-by: Roger Quadros Link: https://lore.kernel.org/r/20230821134029.40084-1-yuehaibing@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 - drivers/net/ethernet/ti/netcp.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h index bf40c88fbd9b..f3dad2ab9828 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h @@ -192,7 +192,6 @@ struct am65_cpsw_ndev_priv { extern const struct ethtool_ops am65_cpsw_ethtool_ops_slave; -void am65_cpsw_nuss_adjust_link(struct net_device *ndev); void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common); void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common); int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx); diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h index 43d5cd59b56b..7007eb8bed36 100644 --- a/drivers/net/ethernet/ti/netcp.h +++ b/drivers/net/ethernet/ti/netcp.h @@ -233,8 +233,6 @@ int netcp_register_rxhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); int netcp_unregister_rxhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); -void *netcp_device_find_module(struct netcp_device *netcp_device, - const char *name); /* SGMII functions */ int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); -- cgit From 63c11dc2ca8bf5d8fb85a29db7d23ae083c919df Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 21 Aug 2023 17:19:23 +0300 Subject: vxlan: vnifilter: Use GFP_KERNEL instead of GFP_ATOMIC The function is not called from an atomic context so use GFP_KERNEL instead of GFP_ATOMIC. The allocation of the per-CPU stats is already performed with GFP_KERNEL. Tested using test_vxlan_vnifiltering.sh with CONFIG_DEBUG_ATOMIC_SLEEP. Signed-off-by: Ido Schimmel Reviewed-by: Simon Horman Reviewed-by: Kalesh AP Reviewed-by: Nikolay Aleksandrov Link: https://lore.kernel.org/r/20230821141923.1889776-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/vxlan/vxlan_vnifilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c index c3ff30ab782e..9c59d0bf8c3d 100644 --- a/drivers/net/vxlan/vxlan_vnifilter.c +++ b/drivers/net/vxlan/vxlan_vnifilter.c @@ -696,7 +696,7 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan, { struct vxlan_vni_node *vninode; - vninode = kzalloc(sizeof(*vninode), GFP_ATOMIC); + vninode = kzalloc(sizeof(*vninode), GFP_KERNEL); if (!vninode) return NULL; vninode->stats = netdev_alloc_pcpu_stats(struct vxlan_vni_stats_pcpu); -- cgit From 504fc6f4f7f681d2a03aa5f68aad549d90eab853 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 21 Aug 2023 17:23:39 +0300 Subject: vrf: Remove unnecessary RCU-bh critical section dev_queue_xmit_nit() already uses rcu_read_lock() / rcu_read_unlock() and nothing suggests that softIRQs should be disabled around it. Therefore, remove the rcu_read_lock_bh() / rcu_read_unlock_bh() surrounding it. Tested using [1] with lockdep enabled. [1] #!/bin/bash ip link add name vrf1 up type vrf table 100 ip link add name veth0 type veth peer name veth1 ip link set dev veth1 master vrf1 ip link set dev veth0 up ip link set dev veth1 up ip address add 192.0.2.1/24 dev veth0 ip address add 192.0.2.2/24 dev veth1 ip rule add pref 32765 table local ip rule del pref 0 tcpdump -i vrf1 -c 20 -w /dev/null & sleep 10 ping -i 0.1 -c 10 -q 192.0.2.2 Signed-off-by: Ido Schimmel Reviewed-by: Simon Horman Reviewed-by: David Ahern Link: https://lore.kernel.org/r/20230821142339.1889961-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/vrf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 6043e63b42f9..43f374444684 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -638,9 +638,7 @@ static void vrf_finish_direct(struct sk_buff *skb) eth_zero_addr(eth->h_dest); eth->h_proto = skb->protocol; - rcu_read_lock_bh(); dev_queue_xmit_nit(skb, vrf_dev); - rcu_read_unlock_bh(); skb_pull(skb, ETH_HLEN); } -- cgit From fba360a047d5eeeb9d4b7c3a9b1c8308980ce9a6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Aug 2023 21:28:01 +0200 Subject: wifi: mac80211_hwsim: drop short frames While technically some control frames like ACK are shorter and end after Address 1, such frames shouldn't be forwarded through wmediumd or similar userspace, so require the full 3-address header to avoid accessing invalid memory if shorter frames are passed in. Reported-by: syzbot+b2645b5bf1512b81fa22@syzkaller.appspotmail.com Reviewed-by: Jeff Johnson Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index f446fd0e8cd0..dd516cec4197 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -5626,14 +5626,15 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); + if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) || + frame_data_len > IEEE80211_MAX_DATA_LEN) + goto err; + /* Allocate new skb here */ skb = alloc_skb(frame_data_len, GFP_KERNEL); if (skb == NULL) goto err; - if (frame_data_len > IEEE80211_MAX_DATA_LEN) - goto err; - /* Copy the data */ skb_put_data(skb, frame_data, frame_data_len); -- cgit From d40de0ad3d1b95da2b263c9361e91b984ab9c16d Mon Sep 17 00:00:00 2001 From: EN-WEI WU Date: Tue, 15 Aug 2023 17:54:27 +0800 Subject: wifi: mac80211_hwsim: avoid calling nlmsg_free() in IRQ or IRQ disabled The nlmsg_free() ends up calling kfree_skb(), and kfree_skb() is not allowed to be called from hardware interrupt context or with hardware interrupts being disabled. Replace the mistaken usage of nlmsg_free() by dev_kfree_skb_irq(), which is safe in both cases. Signed-off-by: EN-WEI WU Link: https://lore.kernel.org/r/20230815095427.13589-1-enweiwu@FreeBSD.org Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index dd516cec4197..ec78fe13dd3e 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -6315,7 +6315,7 @@ static void hwsim_virtio_tx_done(struct virtqueue *vq) spin_lock_irqsave(&hwsim_virtio_lock, flags); while ((skb = virtqueue_get_buf(vq, &len))) - nlmsg_free(skb); + dev_kfree_skb_irq(skb); spin_unlock_irqrestore(&hwsim_virtio_lock, flags); } @@ -6384,14 +6384,14 @@ static void hwsim_virtio_rx_work(struct work_struct *work) spin_lock_irqsave(&hwsim_virtio_lock, flags); if (!hwsim_virtio_enabled) { - nlmsg_free(skb); + dev_kfree_skb_irq(skb); goto out_unlock; } vq = hwsim_vqs[HWSIM_VQ_RX]; sg_init_one(sg, skb->head, skb_end_offset(skb)); err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC); if (WARN(err, "virtqueue_add_inbuf returned %d\n", err)) - nlmsg_free(skb); + dev_kfree_skb_irq(skb); else virtqueue_kick(vq); schedule_work(&hwsim_virtio_rx); -- cgit From 1b78dd34560e9962f8e917fe4adde6f2ab0eb89f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Aug 2023 14:17:21 +0200 Subject: Revert "wifi: mac80211_hwsim: check the return value of nla_put_u32" This reverts commit b970ac68e0c4 ("wifi: mac80211_hwsim: check the return value of nla_put_u32") since it introduced a memory leak in the error path, which seems worse than sending an incomplete skb, and the put can't fail anyway since the SKB was just allocated. Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index ec78fe13dd3e..1f524030b186 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -582,9 +582,8 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, */ /* Add vendor data */ - err = nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); - if (err) - return err; + nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); + /* Send the event - this will call nla_nest_end() */ cfg80211_vendor_event(skb, GFP_KERNEL); } -- cgit From 4c0dac1ef8abc6295a91197884f5ceb5d11c2bd9 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 May 2023 17:46:47 +0200 Subject: net/mlx5: Rework devlink port alloc/free into init/cleanup In order to prepare the devlink port registration function to be common for PFs/VFs and SFs, change the existing devlink port allocation and free functions into PF/VF init and cleanup, so similar helpers could be later on introduced for SFs. Make the init/cleanup helpers responsible for setting/clearing the vport->dl_port pointer. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 65 ++++++++++++++-------- 1 file changed, 43 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 234fd4c28e79..1864bf83aaa2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -21,19 +21,16 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_ mlx5_core_is_ec_vf_vport(esw->dev, vport_num); } -static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num) +static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch *esw, + u16 vport_num, + struct devlink_port *dl_port) { struct mlx5_core_dev *dev = esw->dev; struct netdev_phys_item_id ppid = {}; - struct devlink_port *dl_port; u32 controller_num = 0; bool external; u16 pfnum; - dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL); - if (!dl_port) - return NULL; - mlx5_esw_get_port_parent_id(dev, &ppid); pfnum = mlx5_get_dev_index(dev); external = mlx5_core_is_ecpf_esw_manager(dev); @@ -55,12 +52,40 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum, vport_num - 1, false); } - return dl_port; } -static void mlx5_esw_dl_port_free(struct devlink_port *dl_port) +static int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num) +{ + struct devlink_port *dl_port; + struct mlx5_vport *vport; + + if (!mlx5_esw_devlink_port_supported(esw, vport_num)) + return 0; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL); + if (!dl_port) + return -ENOMEM; + + mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(esw, vport_num, dl_port); + + vport->dl_port = dl_port; + return 0; +} + +static void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) { - kfree(dl_port); + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport) || !vport->dl_port) + return; + + kfree(vport->dl_port); + vport->dl_port = NULL; } static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { @@ -81,16 +106,17 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ struct devlink *devlink; int err; - if (!mlx5_esw_devlink_port_supported(esw, vport_num)) - return 0; - vport = mlx5_eswitch_get_vport(esw, vport_num); if (IS_ERR(vport)) return PTR_ERR(vport); - dl_port = mlx5_esw_dl_port_alloc(esw, vport_num); + err = mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport_num); + if (err) + return err; + + dl_port = vport->dl_port; if (!dl_port) - return -ENOMEM; + return 0; devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); @@ -103,13 +129,12 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ if (err) goto rate_err; - vport->dl_port = dl_port; return 0; rate_err: devl_port_unregister(dl_port); reg_err: - mlx5_esw_dl_port_free(dl_port); + mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); return err; } @@ -117,19 +142,15 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vpo { struct mlx5_vport *vport; - if (!mlx5_esw_devlink_port_supported(esw, vport_num)) - return; - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) + if (IS_ERR(vport) || !vport->dl_port) return; mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); devl_rate_leaf_destroy(vport->dl_port); devl_port_unregister(vport->dl_port); - mlx5_esw_dl_port_free(vport->dl_port); - vport->dl_port = NULL; + mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); } struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num) -- cgit From 638002252544a20f3f62ffb2cadbfa70207bd9b8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 10:30:45 +0200 Subject: net/mlx5: Push out SF devlink port init and cleanup code to separate helpers Similar to what was done for PFs/VFs, introduce devlink port init and cleanup helpers for SFs and manage the vport->dl_port pointer there. Signed-off-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 61 ++++++++++++++++++---- 1 file changed, 51 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 1864bf83aaa2..dfb1101dfef0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -97,6 +97,48 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, }; +static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw, + struct devlink_port *dl_port, + u32 controller, u32 sfnum) +{ + struct mlx5_core_dev *dev = esw->dev; + struct netdev_phys_item_id ppid = {}; + u16 pfnum; + + pfnum = mlx5_get_dev_index(dev); + mlx5_esw_get_port_parent_id(dev, &ppid); + memcpy(dl_port->attrs.switch_id.id, &ppid.id[0], ppid.id_len); + dl_port->attrs.switch_id.id_len = ppid.id_len; + devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); +} + +static int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, + struct devlink_port *dl_port, + u32 controller, u32 sfnum) +{ + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, dl_port, controller, sfnum); + + vport->dl_port = dl_port; + return 0; +} + +static void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) +{ + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return; + + vport->dl_port = NULL; +} + int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_core_dev *dev = esw->dev; @@ -179,38 +221,37 @@ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_p u16 vport_num, u32 controller, u32 sfnum) { struct mlx5_core_dev *dev = esw->dev; - struct netdev_phys_item_id ppid = {}; unsigned int dl_port_index; struct mlx5_vport *vport; struct devlink *devlink; - u16 pfnum; int err; vport = mlx5_eswitch_get_vport(esw, vport_num); if (IS_ERR(vport)) return PTR_ERR(vport); - pfnum = mlx5_get_dev_index(dev); - mlx5_esw_get_port_parent_id(dev, &ppid); - memcpy(dl_port->attrs.switch_id.id, &ppid.id[0], ppid.id_len); - dl_port->attrs.switch_id.id_len = ppid.id_len; - devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); + err = mlx5_esw_offloads_sf_devlink_port_init(esw, vport_num, dl_port, controller, sfnum); + if (err) + return err; + devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, &mlx5_esw_dl_sf_port_ops); if (err) - return err; + goto reg_err; err = devl_rate_leaf_create(dl_port, vport, NULL); if (err) goto rate_err; - vport->dl_port = dl_port; return 0; rate_err: devl_port_unregister(dl_port); + +reg_err: + mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); return err; } @@ -226,5 +267,5 @@ void mlx5_esw_devlink_sf_port_unregister(struct mlx5_eswitch *esw, u16 vport_num devl_rate_leaf_destroy(vport->dl_port); devl_port_unregister(vport->dl_port); - vport->dl_port = NULL; + mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); } -- cgit From d9833bcfe840fff5d368b1c7c68e05c95be8d19c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 May 2023 10:01:02 +0200 Subject: net/mlx5: Push devlink port PF/VF init/cleanup calls out of devlink_port_register/unregister() In order to prepare for mlx5_esw_offloads_devlink_port_register/unregister() to be used for SFs as well, push out the PF/VF specific init/cleanup calls outside. Introduce mlx5_eswitch_load/unload_pf_vf_vport() and call them from there. Use these new helpers of PF/VF loading and make mlx5_eswitch_local/unload_vport() reusable for SFs. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 13 ++----- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 45 +++++++++++++++++----- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 4 ++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 16 ++++++++ 4 files changed, 58 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index dfb1101dfef0..5e8557f7564c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -54,7 +54,7 @@ static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch * } } -static int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num) { struct devlink_port *dl_port; struct mlx5_vport *vport; @@ -76,7 +76,7 @@ static int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u return 0; } -static void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport; @@ -152,10 +152,6 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ if (IS_ERR(vport)) return PTR_ERR(vport); - err = mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport_num); - if (err) - return err; - dl_port = vport->dl_port; if (!dl_port) return 0; @@ -165,7 +161,7 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, &mlx5_esw_pf_vf_dl_port_ops); if (err) - goto reg_err; + return err; err = devl_rate_leaf_create(dl_port, vport, NULL); if (err) @@ -175,8 +171,6 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ rate_err: devl_port_unregister(dl_port); -reg_err: - mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); return err; } @@ -192,7 +186,6 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vpo devl_rate_leaf_destroy(vport->dl_port); devl_port_unregister(vport->dl_port); - mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); } struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 4a7a13169a90..76d05e233770 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1094,6 +1094,31 @@ static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) mlx5_esw_vport_disable(esw, vport_num); } +static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num, + enum mlx5_eswitch_vport_event enabled_events) +{ + int err; + + err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport_num); + if (err) + return err; + + err = mlx5_eswitch_load_vport(esw, vport_num, enabled_events); + if (err) + goto err_load; + return 0; + +err_load: + mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num); + return err; +} + +static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) +{ + mlx5_eswitch_unload_vport(esw, vport_num); + mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num); +} + void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) { struct mlx5_vport *vport; @@ -1102,7 +1127,7 @@ void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { if (!vport->enabled) continue; - mlx5_eswitch_unload_vport(esw, vport->vport); + mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); } } @@ -1115,7 +1140,7 @@ static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { if (!vport->enabled) continue; - mlx5_eswitch_unload_vport(esw, vport->vport); + mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport); } } @@ -1127,7 +1152,7 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, int err; mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) { - err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events); + err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); if (err) goto vf_err; } @@ -1147,7 +1172,7 @@ static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_v int err; mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { - err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events); + err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events); if (err) goto vf_err; } @@ -1189,7 +1214,7 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, int ret; /* Enable PF vport */ - ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events); + ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_PF, enabled_events); if (ret) return ret; @@ -1200,7 +1225,7 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, /* Enable ECPF vport */ if (mlx5_ecpf_vport_exists(esw->dev)) { - ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events); + ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); if (ret) goto ecpf_err; if (mlx5_core_ec_sriov_enabled(esw->dev)) { @@ -1223,11 +1248,11 @@ vf_err: mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); ec_vf_err: if (mlx5_ecpf_vport_exists(esw->dev)) - mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); + mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); ecpf_err: host_pf_disable_hca(esw->dev); pf_hca_err: - mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); + mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF); return ret; } @@ -1241,11 +1266,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) if (mlx5_ecpf_vport_exists(esw->dev)) { if (mlx5_core_ec_sriov_enabled(esw->dev)) mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); - mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); + mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); } host_pf_disable_hca(esw->dev); - mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); + mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF); } static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index f3a6a1826e00..8367c639e234 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -729,6 +729,8 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, u16 vport, struct mlx5_flow_spec *spec); +int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); @@ -736,6 +738,8 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs); +int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num); struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index c0b1b7b66cff..055faaf5dbb7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2535,6 +2535,22 @@ static void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num __esw_offloads_unload_rep(esw, rep, rep_type); } +int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num) +{ + if (esw->mode != MLX5_ESWITCH_OFFLOADS) + return 0; + + return mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport_num); +} + +void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num) +{ + if (esw->mode != MLX5_ESWITCH_OFFLOADS) + return; + + mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); +} + int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) { int err; -- cgit From 382fe5747b8a2f5057f515ee67bdcc2d0ccd9240 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 May 2023 15:05:29 +0200 Subject: net/mlx5: Allow mlx5_esw_offloads_devlink_port_register() to register SFs Currently there is a separate set of functions used to register/unregister the SF. The only difference is currently the ops struct. Move the struct up and use it for SFs in mlx5_esw_offloads_devlink_port_register(). Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 5e8557f7564c..60e25fbaef5f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -139,9 +139,24 @@ static void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, vport->dl_port = NULL; } +static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = { +#ifdef CONFIG_MLX5_SF_MANAGER + .port_del = mlx5_devlink_sf_port_del, +#endif + .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, + .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, + .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, + .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, +#ifdef CONFIG_MLX5_SF_MANAGER + .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, + .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, +#endif +}; + int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_core_dev *dev = esw->dev; + const struct devlink_port_ops *ops; struct devlink_port *dl_port; unsigned int dl_port_index; struct mlx5_vport *vport; @@ -156,10 +171,14 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ if (!dl_port) return 0; + if (mlx5_esw_is_sf_vport(esw, vport_num)) + ops = &mlx5_esw_dl_sf_port_ops; + else + ops = &mlx5_esw_pf_vf_dl_port_ops; + devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, - &mlx5_esw_pf_vf_dl_port_ops); + err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, ops); if (err) return err; @@ -196,20 +215,6 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1 return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port; } -static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = { -#ifdef CONFIG_MLX5_SF_MANAGER - .port_del = mlx5_devlink_sf_port_del, -#endif - .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, - .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, - .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, - .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, -#ifdef CONFIG_MLX5_SF_MANAGER - .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, - .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, -#endif -}; - int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port, u16 vport_num, u32 controller, u32 sfnum) { -- cgit From e855afd715656a9f25cf62fa68d99c33213b83b7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 May 2023 15:01:47 +0200 Subject: net/mlx5: Introduce mlx5_eswitch_load/unload_sf_vport() and use it from SF code Similar to the PF/VF helpers, introduce a set of load/unload helpers for SF vports. From there, call mlx5_eswitch_load/unload_vport() which are common for PFs/VFs and newly introduced SF helpers. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 8 +++---- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 27 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 17 ++++++++++++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 12 ++++++++++ .../net/ethernet/mellanox/mlx5/core/sf/devlink.c | 8 +++---- 5 files changed, 64 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 60e25fbaef5f..540bebd93ea5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -112,9 +112,9 @@ static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); } -static int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, - struct devlink_port *dl_port, - u32 controller, u32 sfnum) +int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, + struct devlink_port *dl_port, + u32 controller, u32 sfnum) { struct mlx5_vport *vport; @@ -128,7 +128,7 @@ static int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 return 0; } -static void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 76d05e233770..f77237401ee9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1119,6 +1119,33 @@ static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_ mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num); } +int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, + enum mlx5_eswitch_vport_event enabled_events, + struct devlink_port *dl_port, u32 controller, u32 sfnum) +{ + int err; + + err = mlx5_esw_offloads_init_sf_rep(esw, vport_num, dl_port, controller, sfnum); + if (err) + return err; + + err = mlx5_eswitch_load_vport(esw, vport_num, enabled_events); + if (err) + goto err_load; + + return 0; + +err_load: + mlx5_esw_offloads_cleanup_sf_rep(esw, vport_num); + return err; +} + +void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) +{ + mlx5_eswitch_unload_vport(esw, vport_num); + mlx5_esw_offloads_cleanup_sf_rep(esw, vport_num); +} + void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) { struct mlx5_vport *vport; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 8367c639e234..89efeffa075d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -731,15 +731,32 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); + +int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, + struct devlink_port *dl_port, + u32 controller, u32 sfnum); +void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, u16 vport_num); + int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, + enum mlx5_eswitch_vport_event enabled_events, + struct devlink_port *dl_port, u32 controller, u32 sfnum); +void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num); + int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs); int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); + +int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, + struct devlink_port *dl_port, + u32 controller, u32 sfnum); +void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); + int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num); struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 055faaf5dbb7..998e56cf43db 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2551,6 +2551,18 @@ void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); } +int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, + struct devlink_port *dl_port, + u32 controller, u32 sfnum) +{ + return mlx5_esw_offloads_sf_devlink_port_init(esw, vport_num, dl_port, controller, sfnum); +} + +void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, u16 vport_num) +{ + mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); +} + int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) { int err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c index 6a3fa30b2bf2..f7bdbeb92eb3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c @@ -292,8 +292,8 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, if (IS_ERR(sf)) return PTR_ERR(sf); - err = mlx5_esw_offloads_sf_vport_enable(esw, &sf->dl_port, sf->hw_fn_id, - new_attr->controller, new_attr->sfnum); + err = mlx5_eswitch_load_sf_vport(esw, sf->hw_fn_id, MLX5_VPORT_UC_ADDR_CHANGE, + &sf->dl_port, new_attr->controller, new_attr->sfnum); if (err) goto esw_err; *dl_port = &sf->dl_port; @@ -400,7 +400,7 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, goto sf_err; } - mlx5_esw_offloads_sf_vport_disable(esw, sf->hw_fn_id); + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); mlx5_sf_id_erase(table, sf); mutex_lock(&table->sf_state_lock); @@ -472,7 +472,7 @@ static void mlx5_sf_deactivate_all(struct mlx5_sf_table *table) * arrive. It is safe to destroy all user created SFs. */ xa_for_each(&table->port_indices, index, sf) { - mlx5_esw_offloads_sf_vport_disable(esw, sf->hw_fn_id); + mlx5_eswitch_unload_sf_vport(esw, sf->hw_fn_id); mlx5_sf_id_erase(table, sf); mlx5_sf_dealloc(table, sf); } -- cgit From b940ec4b25beec39358f483d01a19144b88ee1aa Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 26 May 2023 15:12:55 +0200 Subject: net/mlx5: Remove no longer used mlx5_esw_offloads_sf_vport_enable/disable() Since the previous patch removed the only users of these functions, remove them. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 53 ---------------------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 7 --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 32 ------------- 3 files changed, 92 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 540bebd93ea5..b77893507476 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -214,56 +214,3 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1 vport = mlx5_eswitch_get_vport(esw, vport_num); return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port; } - -int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port, - u16 vport_num, u32 controller, u32 sfnum) -{ - struct mlx5_core_dev *dev = esw->dev; - unsigned int dl_port_index; - struct mlx5_vport *vport; - struct devlink *devlink; - int err; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return PTR_ERR(vport); - - err = mlx5_esw_offloads_sf_devlink_port_init(esw, vport_num, dl_port, controller, sfnum); - if (err) - return err; - - devlink = priv_to_devlink(dev); - dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, - &mlx5_esw_dl_sf_port_ops); - if (err) - goto reg_err; - - err = devl_rate_leaf_create(dl_port, vport, NULL); - if (err) - goto rate_err; - - return 0; - -rate_err: - devl_port_unregister(dl_port); - -reg_err: - mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); - return err; -} - -void mlx5_esw_devlink_sf_port_unregister(struct mlx5_eswitch *esw, u16 vport_num) -{ - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return; - - mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); - devl_rate_leaf_destroy(vport->dl_port); - - devl_port_unregister(vport->dl_port); - mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); -} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 89efeffa075d..e1e808105e98 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -761,13 +761,6 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num); struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num); -int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port, - u16 vport_num, u32 controller, u32 sfnum); -void mlx5_esw_devlink_sf_port_unregister(struct mlx5_eswitch *esw, u16 vport_num); - -int mlx5_esw_offloads_sf_vport_enable(struct mlx5_eswitch *esw, struct devlink_port *dl_port, - u16 vport_num, u32 controller, u32 sfnum); -void mlx5_esw_offloads_sf_vport_disable(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id); int mlx5_esw_vport_vhca_id_set(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 998e56cf43db..4b03f2bf605d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4130,38 +4130,6 @@ u32 mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw, } EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_match); -int mlx5_esw_offloads_sf_vport_enable(struct mlx5_eswitch *esw, struct devlink_port *dl_port, - u16 vport_num, u32 controller, u32 sfnum) -{ - int err; - - err = mlx5_esw_vport_enable(esw, vport_num, MLX5_VPORT_UC_ADDR_CHANGE); - if (err) - return err; - - err = mlx5_esw_devlink_sf_port_register(esw, dl_port, vport_num, controller, sfnum); - if (err) - goto devlink_err; - - err = mlx5_esw_offloads_rep_load(esw, vport_num); - if (err) - goto rep_err; - return 0; - -rep_err: - mlx5_esw_devlink_sf_port_unregister(esw, vport_num); -devlink_err: - mlx5_esw_vport_disable(esw, vport_num); - return err; -} - -void mlx5_esw_offloads_sf_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) -{ - mlx5_esw_offloads_rep_unload(esw, vport_num); - mlx5_esw_devlink_sf_port_unregister(esw, vport_num); - mlx5_esw_vport_disable(esw, vport_num); -} - static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num, u16 *vhca_id) { int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); -- cgit From 13f878a22c20d1c0e1d8ffa7aa97c33519b5bd7c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Jun 2023 09:09:12 +0200 Subject: net/mlx5: Don't register ops for non-PF/VF/SF port and avoid checks in ops Currently each PF/VF/SF devlink port op called into mlx5 code calls is_port_function_supported() to check if the port is either PF, VF or SF. So make sure that the ops are registered with devlink port only for those and avoid the is_port_function_supported() checks in ops. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/esw/devlink_port.c | 4 +++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 6 ++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 1 + .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 18 ------------------ 4 files changed, 10 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index b77893507476..69084673e7e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -173,8 +173,10 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ if (mlx5_esw_is_sf_vport(esw, vport_num)) ops = &mlx5_esw_dl_sf_port_ops; - else + else if (mlx5_eswitch_is_pf_vf_vport(esw, vport_num)) ops = &mlx5_esw_pf_vf_dl_port_ops; + else + ops = NULL; devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index f77237401ee9..5d8d4a4f3e4e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1970,6 +1970,12 @@ bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_VF); } +bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) +{ + return vport_num == MLX5_VPORT_PF || + mlx5_eswitch_is_vf_vport(esw, vport_num); +} + bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) { return mlx5_esw_check_port_type(esw, vport_num, MLX5_ESW_VPT_SF); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index e1e808105e98..ad2ebd843ed2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -680,6 +680,7 @@ struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num); bool mlx5_eswitch_is_vf_vport(struct mlx5_eswitch *esw, u16 vport_num); +bool mlx5_eswitch_is_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num); bool mlx5_esw_is_sf_vport(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type, void *data); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 4b03f2bf605d..1aa404218817 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4218,14 +4218,6 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, } EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_set); -static bool -is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num) -{ - return vport_num == MLX5_VPORT_PF || - mlx5_eswitch_is_vf_vport(esw, vport_num) || - mlx5_esw_is_sf_vport(esw, vport_num); -} - int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr, int *hw_addr_len, struct netlink_ext_ack *extack) @@ -4239,8 +4231,6 @@ int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, return PTR_ERR(esw); vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - if (!is_port_function_supported(esw, vport_num)) - return -EOPNOTSUPP; vport = mlx5_eswitch_get_vport(esw, vport_num); if (IS_ERR(vport)) { @@ -4269,11 +4259,6 @@ int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, } vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - if (!is_port_function_supported(esw, vport_num)) { - NL_SET_ERR_MSG_MOD(extack, "Port doesn't support set hw_addr"); - return -EINVAL; - } - return mlx5_eswitch_set_vport_mac(esw, vport_num, hw_addr); } @@ -4286,9 +4271,6 @@ mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *e return ERR_PTR(-EOPNOTSUPP); vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - if (!is_port_function_supported(esw, vport_num)) - return ERR_PTR(-EOPNOTSUPP); - return mlx5_eswitch_get_vport(esw, vport_num); } -- cgit From 2c5f33f6b9406cc092998cdc96ed015e73cb581b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 31 May 2023 13:34:19 +0200 Subject: net/mlx5: Embed struct devlink_port into driver structure Struct devlink_port is usually embedded in a driver-specific struct which allows to carry driver context to devlink port ops. Introduce a container struct to include devlink_port struct in preparation to also include driver context for devlink port ops. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 25 ++++++++++++---------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 12 +++++++---- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 2 +- .../net/ethernet/mellanox/mlx5/core/sf/devlink.c | 4 ++-- 5 files changed, 26 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 69084673e7e6..35cf2739a2aa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -56,7 +56,7 @@ static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch * int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num) { - struct devlink_port *dl_port; + struct mlx5_devlink_port *dl_port; struct mlx5_vport *vport; if (!mlx5_esw_devlink_port_supported(esw, vport_num)) @@ -70,7 +70,8 @@ int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vpor if (!dl_port) return -ENOMEM; - mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(esw, vport_num, dl_port); + mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(esw, vport_num, + &dl_port->dl_port); vport->dl_port = dl_port; return 0; @@ -113,7 +114,7 @@ static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw } int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, - struct devlink_port *dl_port, + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { struct mlx5_vport *vport; @@ -122,7 +123,7 @@ int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_n if (IS_ERR(vport)) return PTR_ERR(vport); - mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, dl_port, controller, sfnum); + mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, &dl_port->dl_port, controller, sfnum); vport->dl_port = dl_port; return 0; @@ -157,7 +158,7 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ { struct mlx5_core_dev *dev = esw->dev; const struct devlink_port_ops *ops; - struct devlink_port *dl_port; + struct mlx5_devlink_port *dl_port; unsigned int dl_port_index; struct mlx5_vport *vport; struct devlink *devlink; @@ -180,33 +181,35 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, ops); + err = devl_port_register_with_ops(devlink, &dl_port->dl_port, dl_port_index, ops); if (err) return err; - err = devl_rate_leaf_create(dl_port, vport, NULL); + err = devl_rate_leaf_create(&dl_port->dl_port, vport, NULL); if (err) goto rate_err; return 0; rate_err: - devl_port_unregister(dl_port); + devl_port_unregister(&dl_port->dl_port); return err; } void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num) { + struct mlx5_devlink_port *dl_port; struct mlx5_vport *vport; vport = mlx5_eswitch_get_vport(esw, vport_num); if (IS_ERR(vport) || !vport->dl_port) return; + dl_port = vport->dl_port; mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL); - devl_rate_leaf_destroy(vport->dl_port); + devl_rate_leaf_destroy(&dl_port->dl_port); - devl_port_unregister(vport->dl_port); + devl_port_unregister(&dl_port->dl_port); } struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num) @@ -214,5 +217,5 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1 struct mlx5_vport *vport; vport = mlx5_eswitch_get_vport(esw, vport_num); - return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port; + return IS_ERR(vport) ? ERR_CAST(vport) : &vport->dl_port->dl_port; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 5d8d4a4f3e4e..044d0ba9fcf6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1121,7 +1121,7 @@ static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_ int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events, - struct devlink_port *dl_port, u32 controller, u32 sfnum) + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { int err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index ad2ebd843ed2..b45013465738 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -172,6 +172,10 @@ enum mlx5_eswitch_vport_event { MLX5_VPORT_PROMISC_CHANGE = BIT(3), }; +struct mlx5_devlink_port { + struct devlink_port dl_port; +}; + struct mlx5_vport { struct mlx5_core_dev *dev; struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE]; @@ -200,7 +204,7 @@ struct mlx5_vport { bool enabled; enum mlx5_eswitch_vport_event enabled_events; int index; - struct devlink_port *dl_port; + struct mlx5_devlink_port *dl_port; }; struct mlx5_esw_indir_table; @@ -734,7 +738,7 @@ int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, - struct devlink_port *dl_port, + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum); void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, u16 vport_num); @@ -743,7 +747,7 @@ void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events, - struct devlink_port *dl_port, u32 controller, u32 sfnum); + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum); void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, @@ -754,7 +758,7 @@ int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vpor void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, - struct devlink_port *dl_port, + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum); void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 1aa404218817..b7ece8767ffe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2552,7 +2552,7 @@ void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num } int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, - struct devlink_port *dl_port, + struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { return mlx5_esw_offloads_sf_devlink_port_init(esw, vport_num, dl_port, controller, sfnum); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c index f7bdbeb92eb3..e34a8f88c518 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c @@ -12,7 +12,7 @@ #include "diag/sf_tracepoint.h" struct mlx5_sf { - struct devlink_port dl_port; + struct mlx5_devlink_port dl_port; unsigned int port_index; u32 controller; u16 id; @@ -296,7 +296,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, &sf->dl_port, new_attr->controller, new_attr->sfnum); if (err) goto esw_err; - *dl_port = &sf->dl_port; + *dl_port = &sf->dl_port.dl_port; trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum); return 0; -- cgit From 2caa2a39116f07fd06778052a90b3e35bc262c44 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 31 May 2023 14:14:50 +0200 Subject: net/mlx5: Reduce number of vport lookups passing vport pointer instead of index During devlink port init/cleanup and register/unregister calls, there are many lookups of vport. Instead of passing vport_num as argument to functions, pass the vport struct pointer directly and avoid repeated lookups. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 47 ++++--------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 79 +++++++++++++--------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 30 ++++---- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 30 ++++---- 4 files changed, 90 insertions(+), 96 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 35cf2739a2aa..2dc7b0bf38c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -54,18 +54,15 @@ static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch * } } -int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, + struct mlx5_vport *vport) { struct mlx5_devlink_port *dl_port; - struct mlx5_vport *vport; + u16 vport_num = vport->vport; if (!mlx5_esw_devlink_port_supported(esw, vport_num)) return 0; - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return PTR_ERR(vport); - dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL); if (!dl_port) return -ENOMEM; @@ -77,12 +74,10 @@ int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vpor return 0; } -void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, + struct mlx5_vport *vport) { - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport) || !vport->dl_port) + if (!vport->dl_port) return; kfree(vport->dl_port); @@ -113,30 +108,18 @@ static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); } -int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, struct mlx5_vport *vport, struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return PTR_ERR(vport); - mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, &dl_port->dl_port, controller, sfnum); vport->dl_port = dl_port; return 0; } -void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return; - vport->dl_port = NULL; } @@ -154,20 +137,16 @@ static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = { #endif }; -int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { struct mlx5_core_dev *dev = esw->dev; const struct devlink_port_ops *ops; struct mlx5_devlink_port *dl_port; + u16 vport_num = vport->vport; unsigned int dl_port_index; - struct mlx5_vport *vport; struct devlink *devlink; int err; - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return PTR_ERR(vport); - dl_port = vport->dl_port; if (!dl_port) return 0; @@ -196,13 +175,11 @@ rate_err: return err; } -void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { struct mlx5_devlink_port *dl_port; - struct mlx5_vport *vport; - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport) || !vport->dl_port) + if (!vport->dl_port) return; dl_port = vport->dl_port; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 044d0ba9fcf6..5368b33fde63 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -882,16 +882,12 @@ static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport esw_vport_cleanup_acl(esw, vport); } -int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, enum mlx5_eswitch_vport_event enabled_events) { - struct mlx5_vport *vport; + u16 vport_num = vport->vport; int ret; - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return PTR_ERR(vport); - mutex_lock(&esw->state_lock); WARN_ON(vport->enabled); @@ -912,7 +908,7 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, u16 vport_num, (!vport_num && mlx5_core_is_ecpf(esw->dev))) vport->info.trusted = true; - if (!mlx5_esw_is_manager_vport(esw, vport->vport) && + if (!mlx5_esw_is_manager_vport(esw, vport_num) && MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { ret = mlx5_esw_vport_vhca_id_set(esw, vport_num); if (ret) @@ -939,15 +935,12 @@ err_vhca_mapping: return ret; } -void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return; + u16 vport_num = vport->vport; mutex_lock(&esw->state_lock); + if (!vport->enabled) goto done; @@ -957,9 +950,9 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) /* Disable events from this vport */ if (MLX5_CAP_GEN(esw->dev, log_max_l2_table)) - arm_vport_context_events_cmd(esw->dev, vport->vport, 0); + arm_vport_context_events_cmd(esw->dev, vport_num, 0); - if (!mlx5_esw_is_manager_vport(esw, vport->vport) && + if (!mlx5_esw_is_manager_vport(esw, vport_num) && MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) mlx5_esw_vport_vhca_id_clear(esw, vport_num); @@ -1068,82 +1061,104 @@ static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) } } -static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, +static int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, enum mlx5_eswitch_vport_event enabled_events) { int err; - err = mlx5_esw_vport_enable(esw, vport_num, enabled_events); + err = mlx5_esw_vport_enable(esw, vport, enabled_events); if (err) return err; - err = mlx5_esw_offloads_load_rep(esw, vport_num); + err = mlx5_esw_offloads_load_rep(esw, vport); if (err) goto err_rep; return err; err_rep: - mlx5_esw_vport_disable(esw, vport_num); + mlx5_esw_vport_disable(esw, vport); return err; } -static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num) +static void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { - mlx5_esw_offloads_unload_rep(esw, vport_num); - mlx5_esw_vport_disable(esw, vport_num); + mlx5_esw_offloads_unload_rep(esw, vport); + mlx5_esw_vport_disable(esw, vport); } static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events) { + struct mlx5_vport *vport; int err; - err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport_num); + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport); if (err) return err; - err = mlx5_eswitch_load_vport(esw, vport_num, enabled_events); + err = mlx5_eswitch_load_vport(esw, vport, enabled_events); if (err) goto err_load; return 0; err_load: - mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num); + mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); return err; } static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num) { - mlx5_eswitch_unload_vport(esw, vport_num); - mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num); + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return; + + mlx5_eswitch_unload_vport(esw, vport); + mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport); } int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events, struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { + struct mlx5_vport *vport; int err; - err = mlx5_esw_offloads_init_sf_rep(esw, vport_num, dl_port, controller, sfnum); + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + err = mlx5_esw_offloads_init_sf_rep(esw, vport, dl_port, controller, sfnum); if (err) return err; - err = mlx5_eswitch_load_vport(esw, vport_num, enabled_events); + err = mlx5_eswitch_load_vport(esw, vport, enabled_events); if (err) goto err_load; return 0; err_load: - mlx5_esw_offloads_cleanup_sf_rep(esw, vport_num); + mlx5_esw_offloads_cleanup_sf_rep(esw, vport); return err; } void mlx5_eswitch_unload_sf_vport(struct mlx5_eswitch *esw, u16 vport_num) { - mlx5_eswitch_unload_vport(esw, vport_num); - mlx5_esw_offloads_cleanup_sf_rep(esw, vport_num); + struct mlx5_vport *vport; + + vport = mlx5_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return; + + mlx5_eswitch_unload_vport(esw, vport); + mlx5_esw_offloads_cleanup_sf_rep(esw, vport); } void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index b45013465738..8d03d4fe6eec 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -694,9 +694,9 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw); -int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, enum mlx5_eswitch_vport_event enabled_events); -void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport); int esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw, @@ -734,16 +734,16 @@ void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, u16 vport, struct mlx5_flow_spec *spec); -int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); -void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport); +void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport); -int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport, struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum); -void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport); -int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); -void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport); +void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport); int mlx5_eswitch_load_sf_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events, @@ -754,16 +754,18 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events); void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs); -int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num); -void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, + struct mlx5_vport *vport); +void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, + struct mlx5_vport *vport); -int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, struct mlx5_vport *vport, struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum); -void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num); +void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport); -int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num); -void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num); +int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport); +void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct mlx5_vport *vport); struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num); int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index b7ece8767ffe..609605c42d6d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2535,63 +2535,63 @@ static void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num __esw_offloads_unload_rep(esw, rep, rep_type); } -int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; - return mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport_num); + return mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport); } -void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { if (esw->mode != MLX5_ESWITCH_OFFLOADS) return; - mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num); + mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport); } -int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, u16 vport_num, +int mlx5_esw_offloads_init_sf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport, struct mlx5_devlink_port *dl_port, u32 controller, u32 sfnum) { - return mlx5_esw_offloads_sf_devlink_port_init(esw, vport_num, dl_port, controller, sfnum); + return mlx5_esw_offloads_sf_devlink_port_init(esw, vport, dl_port, controller, sfnum); } -void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_cleanup_sf_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { - mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport_num); + mlx5_esw_offloads_sf_devlink_port_cleanup(esw, vport); } -int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) +int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { int err; if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; - err = mlx5_esw_offloads_devlink_port_register(esw, vport_num); + err = mlx5_esw_offloads_devlink_port_register(esw, vport); if (err) return err; - err = mlx5_esw_offloads_rep_load(esw, vport_num); + err = mlx5_esw_offloads_rep_load(esw, vport->vport); if (err) goto load_err; return err; load_err: - mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); + mlx5_esw_offloads_devlink_port_unregister(esw, vport); return err; } -void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num) +void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vport) { if (esw->mode != MLX5_ESWITCH_OFFLOADS) return; - mlx5_esw_offloads_rep_unload(esw, vport_num); + mlx5_esw_offloads_rep_unload(esw, vport->vport); - mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); + mlx5_esw_offloads_devlink_port_unregister(esw, vport); } static int esw_set_slave_root_fdb(struct mlx5_core_dev *master, -- cgit From c0ae0092927222a1399465325ff778a78cc5f826 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Jun 2023 14:16:41 +0200 Subject: net/mlx5: Return -EOPNOTSUPP in mlx5_devlink_port_fn_migratable_set() directly Instead of initializing "err" variable, just return "-EOPNOTSUPP" directly where it is needed. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 609605c42d6d..87cc6ad2e17f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4309,7 +4309,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct mlx5_vport *vport; void *query_ctx; void *hca_caps; - int err = -EOPNOTSUPP; + int err; esw = mlx5_devlink_eswitch_get(port->devlink); if (IS_ERR(esw)) @@ -4317,7 +4317,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, if (!MLX5_CAP_GEN(esw->dev, migration)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration"); - return err; + return -EOPNOTSUPP; } vport = mlx5_devlink_port_fn_get_vport(port, esw); -- cgit From 5c632cc352e1ca7995e9ccea9a11f7f9a53b1717 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Jun 2023 13:59:52 +0200 Subject: net/mlx5: Relax mlx5_devlink_eswitch_get() return value checking If called from port ops, it is not needed to perform the checks in mlx5_devlink_eswitch_get(). The reason is devlink port would not be registered if the checks are not true. Introduce relaxed version mlx5_devlink_eswitch_nocheck_get() and use it in port ops. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 21 +++++++++--- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 6 +++- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 39 ++++------------------ 3 files changed, 29 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 5368b33fde63..db1c2a076364 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -77,18 +77,31 @@ static int mlx5_eswitch_check(const struct mlx5_core_dev *dev) return 0; } -struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink) +static struct mlx5_eswitch *__mlx5_devlink_eswitch_get(struct devlink *devlink, bool check) { struct mlx5_core_dev *dev = devlink_priv(devlink); int err; - err = mlx5_eswitch_check(dev); - if (err) - return ERR_PTR(err); + if (check) { + err = mlx5_eswitch_check(dev); + if (err) + return ERR_PTR(err); + } return dev->priv.eswitch; } +struct mlx5_eswitch *__must_check +mlx5_devlink_eswitch_get(struct devlink *devlink) +{ + return __mlx5_devlink_eswitch_get(devlink, true); +} + +struct mlx5_eswitch *mlx5_devlink_eswitch_nocheck_get(struct devlink *devlink) +{ + return __mlx5_devlink_eswitch_get(devlink, false); +} + struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 8d03d4fe6eec..9f94c3d6d6e5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -679,7 +679,11 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw); MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\ (last) - 1) -struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink); +struct mlx5_eswitch *__must_check +mlx5_devlink_eswitch_get(struct devlink *devlink); + +struct mlx5_eswitch *mlx5_devlink_eswitch_nocheck_get(struct devlink *devlink); + struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 87cc6ad2e17f..23b562f07c68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3634,7 +3634,7 @@ static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink) struct net *devl_net, *netdev_net; struct mlx5_eswitch *esw; - esw = mlx5_devlink_eswitch_get(devlink); + esw = mlx5_devlink_eswitch_nocheck_get(devlink); netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev); devl_net = devlink_net(devlink); @@ -4222,13 +4222,10 @@ int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr, int *hw_addr_len, struct netlink_ext_ack *extack) { - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); struct mlx5_vport *vport; u16 vport_num; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) - return PTR_ERR(esw); vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); @@ -4249,15 +4246,9 @@ int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr, int hw_addr_len, struct netlink_ext_ack *extack) { - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); u16 vport_num; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) { - NL_SET_ERR_MSG_MOD(extack, "Eswitch doesn't support set hw_addr"); - return PTR_ERR(esw); - } - vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); return mlx5_eswitch_set_vport_mac(esw, vport_num, hw_addr); } @@ -4277,13 +4268,9 @@ mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *e int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack) { - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); struct mlx5_vport *vport; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) - return PTR_ERR(esw); - if (!MLX5_CAP_GEN(esw->dev, migration)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration"); return -EOPNOTSUPP; @@ -4304,17 +4291,13 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack) { + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); - struct mlx5_eswitch *esw; struct mlx5_vport *vport; void *query_ctx; void *hca_caps; int err; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) - return PTR_ERR(esw); - if (!MLX5_CAP_GEN(esw->dev, migration)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration"); return -EOPNOTSUPP; @@ -4368,13 +4351,9 @@ out: int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack) { - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); struct mlx5_vport *vport; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) - return PTR_ERR(esw); - vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); @@ -4390,18 +4369,14 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack) { + struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); - struct mlx5_eswitch *esw; struct mlx5_vport *vport; void *query_ctx; void *hca_caps; u16 vport_num; int err; - esw = mlx5_devlink_eswitch_get(port->devlink); - if (IS_ERR(esw)) - return PTR_ERR(esw); - vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); -- cgit From eb555e34f0841c880f709559d58866ff9d9321a1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Jun 2023 14:13:31 +0200 Subject: net/mlx5: Check vhca_resource_manager capability in each op and add extack msg Since the follow-up patch is going to remove mlx5_devlink_port_fn_get_vport() entirely, move the vhca_resource_manager capability checking to individual ops. Add proper extack message on the way. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 23b562f07c68..e4d1744516f7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4258,9 +4258,6 @@ mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *e { u16 vport_num; - if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) - return ERR_PTR(-EOPNOTSUPP); - vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); return mlx5_eswitch_get_vport(esw, vport_num); } @@ -4276,6 +4273,11 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab return -EOPNOTSUPP; } + if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support VHCA management"); + return -EOPNOTSUPP; + } + vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); @@ -4303,6 +4305,11 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, return -EOPNOTSUPP; } + if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support VHCA management"); + return -EOPNOTSUPP; + } + vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); @@ -4354,6 +4361,11 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); struct mlx5_vport *vport; + if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support VHCA management"); + return -EOPNOTSUPP; + } + vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); @@ -4377,6 +4389,11 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, u16 vport_num; int err; + if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support VHCA management"); + return -EOPNOTSUPP; + } + vport = mlx5_devlink_port_fn_get_vport(port, esw); if (IS_ERR(vport)) { NL_SET_ERR_MSG_MOD(extack, "Invalid port"); -- cgit From 7d8335200c94f6f76fbc3a1682993888bc4eb665 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 31 May 2023 13:36:43 +0200 Subject: net/mlx5: Store vport in struct mlx5_devlink_port and use it in port ops Instead of using internal devlink_port->index to perform vport lookup in every devlink port op, store the vport pointer to the container struct mlx5_devlink_port and use it directly in port ops. Signed-off-by: Jiri Pirko Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 2 + drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 19 +++++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 61 +++------------------- 3 files changed, 29 insertions(+), 53 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 2dc7b0bf38c7..3c254a710006 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -71,6 +71,7 @@ int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, &dl_port->dl_port); vport->dl_port = dl_port; + mlx5_devlink_port_init(dl_port, vport); return 0; } @@ -115,6 +116,7 @@ int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, struct mlx5 mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, &dl_port->dl_port, controller, sfnum); vport->dl_port = dl_port; + mlx5_devlink_port_init(dl_port, vport); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 9f94c3d6d6e5..6fcece69d3be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -172,10 +172,29 @@ enum mlx5_eswitch_vport_event { MLX5_VPORT_PROMISC_CHANGE = BIT(3), }; +struct mlx5_vport; + struct mlx5_devlink_port { struct devlink_port dl_port; + struct mlx5_vport *vport; }; +static inline void mlx5_devlink_port_init(struct mlx5_devlink_port *dl_port, + struct mlx5_vport *vport) +{ + dl_port->vport = vport; +} + +static inline struct mlx5_devlink_port *mlx5_devlink_port_get(struct devlink_port *dl_port) +{ + return container_of(dl_port, struct mlx5_devlink_port, dl_port); +} + +static inline struct mlx5_vport *mlx5_devlink_port_vport_get(struct devlink_port *dl_port) +{ + return mlx5_devlink_port_get(dl_port)->vport; +} + struct mlx5_vport { struct mlx5_core_dev *dev; struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE]; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e4d1744516f7..67eab99f95b1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4223,17 +4223,7 @@ int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); - struct mlx5_vport *vport; - u16 vport_num; - - - vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) { - NL_SET_ERR_MSG_MOD(extack, "Invalid port"); - return PTR_ERR(vport); - } + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); mutex_lock(&esw->state_lock); ether_addr_copy(hw_addr, vport->info.mac); @@ -4247,26 +4237,16 @@ int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); - u16 vport_num; + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); - vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - return mlx5_eswitch_set_vport_mac(esw, vport_num, hw_addr); -} - -static struct mlx5_vport * -mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *esw) -{ - u16 vport_num; - - vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); - return mlx5_eswitch_get_vport(esw, vport_num); + return mlx5_eswitch_set_vport_mac(esw, vport->vport, hw_addr); } int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); - struct mlx5_vport *vport; + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); if (!MLX5_CAP_GEN(esw->dev, migration)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration"); @@ -4278,12 +4258,6 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab return -EOPNOTSUPP; } - vport = mlx5_devlink_port_fn_get_vport(port, esw); - if (IS_ERR(vport)) { - NL_SET_ERR_MSG_MOD(extack, "Invalid port"); - return PTR_ERR(vport); - } - mutex_lock(&esw->state_lock); *is_enabled = vport->info.mig_enabled; mutex_unlock(&esw->state_lock); @@ -4294,8 +4268,8 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); - struct mlx5_vport *vport; void *query_ctx; void *hca_caps; int err; @@ -4310,12 +4284,6 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, return -EOPNOTSUPP; } - vport = mlx5_devlink_port_fn_get_vport(port, esw); - if (IS_ERR(vport)) { - NL_SET_ERR_MSG_MOD(extack, "Invalid port"); - return PTR_ERR(vport); - } - mutex_lock(&esw->state_lock); if (vport->info.mig_enabled == enable) { @@ -4359,19 +4327,13 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); - struct mlx5_vport *vport; + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { NL_SET_ERR_MSG_MOD(extack, "Device doesn't support VHCA management"); return -EOPNOTSUPP; } - vport = mlx5_devlink_port_fn_get_vport(port, esw); - if (IS_ERR(vport)) { - NL_SET_ERR_MSG_MOD(extack, "Invalid port"); - return PTR_ERR(vport); - } - mutex_lock(&esw->state_lock); *is_enabled = vport->info.roce_enabled; mutex_unlock(&esw->state_lock); @@ -4382,11 +4344,11 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = mlx5_devlink_eswitch_nocheck_get(port->devlink); + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); - struct mlx5_vport *vport; + u16 vport_num = vport->vport; void *query_ctx; void *hca_caps; - u16 vport_num; int err; if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) { @@ -4394,13 +4356,6 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, return -EOPNOTSUPP; } - vport = mlx5_devlink_port_fn_get_vport(port, esw); - if (IS_ERR(vport)) { - NL_SET_ERR_MSG_MOD(extack, "Invalid port"); - return PTR_ERR(vport); - } - vport_num = vport->vport; - mutex_lock(&esw->state_lock); if (vport->info.roce_enabled == enable) { -- cgit From c338325f7a18b1b5e04f4fc21672cf8956072733 Mon Sep 17 00:00:00 2001 From: Emeel Hakim Date: Tue, 8 Aug 2023 22:14:54 +0300 Subject: net/mlx5e: Support IPsec upper protocol selector field offload for RX Support RX policy/state upper protocol selector field offload, to enable selecting RX traffic for IPsec operation based on l4 protocol UDP with specific source/destination port. Signed-off-by: Emeel Hakim Reviewed-by: Raed Salem Reviewed-by: Simon Horman Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 10 ++++------ drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c | 2 ++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index a577f0edabe8..2bbe232c2ffa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -440,9 +440,8 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, return -EINVAL; } - if (x->sel.proto != IPPROTO_IP && - (x->sel.proto != IPPROTO_UDP || x->xso.dir != XFRM_DEV_OFFLOAD_OUT)) { - NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP, and only Tx direction"); + if (x->sel.proto != IPPROTO_IP && x->sel.proto != IPPROTO_UDP) { + NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP"); return -EINVAL; } @@ -983,9 +982,8 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev, return -EINVAL; } - if (sel->proto != IPPROTO_IP && - (sel->proto != IPPROTO_UDP || x->xdo.dir != XFRM_DEV_OFFLOAD_OUT)) { - NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP, and only Tx direction"); + if (x->selector.proto != IPPROTO_IP && x->selector.proto != IPPROTO_UDP) { + NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP"); return -EINVAL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 3781c72d97f1..f5e29b7f5ba0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -1243,6 +1243,7 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) setup_fte_spi(spec, attrs->spi); setup_fte_esp(spec); setup_fte_no_frags(spec); + setup_fte_upper_proto_match(spec, &attrs->upspec); if (rx != ipsec->rx_esw) err = setup_modify_header(ipsec, attrs->type, @@ -1519,6 +1520,7 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); setup_fte_no_frags(spec); + setup_fte_upper_proto_match(spec, &attrs->upspec); switch (attrs->action) { case XFRM_POLICY_ALLOW: -- cgit From b8c697e177bba0f802232c3f06b7769b1e1fc516 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Tue, 8 Aug 2023 22:14:55 +0300 Subject: net/mlx5e: Support IPsec upper TCP protocol selector Support TCP as protocol selector for policy and state in IPsec packet offload mode. Example of state configuration is as follows: ip xfrm state add src 192.168.25.3 dst 192.168.25.1 \ proto esp spi 1001 reqid 10001 aead 'rfc4106(gcm(aes))' \ 0x54a7588d36873b031e4bd46301be5a86b3a53879 128 mode transport \ offload packet dev re0 dir in sel src 192.168.25.3 dst 192.168.25.1 \ proto tcp dport 9003 Acked-by: Raed Salem Reviewed-by: Simon Horman Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 11 ++++-- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 43 ++++++++++++++++------ 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 2bbe232c2ffa..3b88a8bb7082 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -440,8 +440,9 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, return -EINVAL; } - if (x->sel.proto != IPPROTO_IP && x->sel.proto != IPPROTO_UDP) { - NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP"); + if (x->sel.proto != IPPROTO_IP && x->sel.proto != IPPROTO_UDP && + x->sel.proto != IPPROTO_TCP) { + NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than TCP/UDP"); return -EINVAL; } @@ -982,8 +983,10 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev, return -EINVAL; } - if (x->selector.proto != IPPROTO_IP && x->selector.proto != IPPROTO_UDP) { - NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP"); + if (x->selector.proto != IPPROTO_IP && + x->selector.proto != IPPROTO_UDP && + x->selector.proto != IPPROTO_TCP) { + NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than TCP/UDP"); return -EINVAL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index f5e29b7f5ba0..a1cfddd05bc4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -936,23 +936,42 @@ static void setup_fte_reg_c4(struct mlx5_flow_spec *spec, u32 reqid) static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upspec *upspec) { - if (upspec->proto != IPPROTO_UDP) + switch (upspec->proto) { + case IPPROTO_UDP: + if (upspec->dport) { + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, + udp_dport, upspec->dport_mask); + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, + udp_dport, upspec->dport); + } + if (upspec->sport) { + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, + udp_sport, upspec->sport_mask); + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, + udp_sport, upspec->sport); + } + break; + case IPPROTO_TCP: + if (upspec->dport) { + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, + tcp_dport, upspec->dport_mask); + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, + tcp_dport, upspec->dport); + } + if (upspec->sport) { + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, + tcp_sport, upspec->sport_mask); + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, + tcp_sport, upspec->sport); + } + break; + default: return; + } spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, spec->match_criteria, ip_protocol); MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, ip_protocol, upspec->proto); - if (upspec->dport) { - MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport, - upspec->dport_mask); - MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->dport); - } - - if (upspec->sport) { - MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport, - upspec->sport_mask); - MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport); - } } static enum mlx5_flow_namespace_type ipsec_fs_get_ns(struct mlx5e_ipsec *ipsec, -- cgit From bdf79b128685458fecc42cd8709375d46407dae2 Mon Sep 17 00:00:00 2001 From: Sai Krishna Date: Mon, 21 Aug 2023 16:06:29 +0530 Subject: octeontx2-pf: Use PTP HW timestamp counter atomic update feature Some of the newer silicon versions in CN10K series supports a feature where in the current PTP timestamp in HW can be updated atomically without losing any cpu cycles unlike read/modify/write register. This patch uses this feature so that PTP accuracy can be improved while adjusting the master offset in HW. There is no need for SW timecounter when using this feature. So removed references to SW timecounter wherever appropriate. Signed-off-by: Sai Krishna Signed-off-by: Naveen Mamindlapalli Signed-off-by: Sunil Kovvuri Goutham Reviewed-by: Kalesh AP Reviewed-by: Simon Horman Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 12 ++ drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 155 +++++++++++++++--- drivers/net/ethernet/marvell/octeontx2/af/ptp.h | 3 +- drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +- drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 12 ++ .../ethernet/marvell/octeontx2/nic/otx2_common.h | 1 + .../net/ethernet/marvell/octeontx2/nic/otx2_ptp.c | 177 +++++++++++++++++---- 7 files changed, 307 insertions(+), 55 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index e2f2b2179eef..6b5b06c2b4e9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -136,6 +136,7 @@ M(GET_HW_CAP, 0x008, get_hw_cap, msg_req, get_hw_cap_rsp) \ M(LMTST_TBL_SETUP, 0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req, \ msg_rsp) \ M(SET_VF_PERM, 0x00b, set_vf_perm, set_vf_perm, msg_rsp) \ +M(PTP_GET_CAP, 0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp) \ /* CGX mbox IDs (range 0x200 - 0x3FF) */ \ M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \ M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \ @@ -1437,6 +1438,12 @@ struct npc_get_kex_cfg_rsp { u8 mkex_pfl_name[MKEX_NAME_LEN]; }; +struct ptp_get_cap_rsp { + struct mbox_msghdr hdr; +#define PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0) + u64 cap; +}; + struct flow_msg { unsigned char dmac[6]; unsigned char smac[6]; @@ -1568,6 +1575,8 @@ enum ptp_op { PTP_OP_GET_TSTMP = 2, PTP_OP_SET_THRESH = 3, PTP_OP_EXTTS_ON = 4, + PTP_OP_ADJTIME = 5, + PTP_OP_SET_CLOCK = 6, }; struct ptp_req { @@ -1576,11 +1585,14 @@ struct ptp_req { s64 scaled_ppm; u64 thresh; int extts_on; + s64 delta; + u64 clk; }; struct ptp_rsp { struct mbox_msghdr hdr; u64 clk; + u64 tsc; }; struct npc_get_field_status_req { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c index c55c2c441a1a..ffbd22797163 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c @@ -12,8 +12,8 @@ #include #include -#include "ptp.h" #include "mbox.h" +#include "ptp.h" #include "rvu.h" #define DRV_NAME "Marvell PTP Driver" @@ -40,6 +40,7 @@ #define PTP_CLOCK_CFG_TSTMP_EDGE BIT_ULL(9) #define PTP_CLOCK_CFG_TSTMP_EN BIT_ULL(8) #define PTP_CLOCK_CFG_TSTMP_IN_MASK GENMASK_ULL(15, 10) +#define PTP_CLOCK_CFG_ATOMIC_OP_MASK GENMASK_ULL(28, 26) #define PTP_CLOCK_CFG_PPS_EN BIT_ULL(30) #define PTP_CLOCK_CFG_PPS_INV BIT_ULL(31) @@ -53,36 +54,62 @@ #define PTP_TIMESTAMP 0xF20ULL #define PTP_CLOCK_SEC 0xFD0ULL #define PTP_SEC_ROLLOVER 0xFD8ULL +/* Atomic update related CSRs */ +#define PTP_FRNS_TIMESTAMP 0xFE0ULL +#define PTP_NXT_ROLLOVER_SET 0xFE8ULL +#define PTP_CURR_ROLLOVER_SET 0xFF0ULL +#define PTP_NANO_TIMESTAMP 0xFF8ULL +#define PTP_SEC_TIMESTAMP 0x1000ULL #define CYCLE_MULT 1000 +#define is_rev_A0(ptp) (((ptp)->pdev->revision & 0x0F) == 0x0) +#define is_rev_A1(ptp) (((ptp)->pdev->revision & 0x0F) == 0x1) + +/* PTP atomic update operation type */ +enum atomic_opcode { + ATOMIC_SET = 1, + ATOMIC_INC = 3, + ATOMIC_DEC = 4 +}; + static struct ptp *first_ptp_block; static const struct pci_device_id ptp_id_table[]; -static bool is_ptp_dev_cnf10kb(struct ptp *ptp) +static bool is_ptp_dev_cnf10ka(struct ptp *ptp) { - return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_PTP; + return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP; } -static bool is_ptp_dev_cn10k(struct ptp *ptp) +static bool is_ptp_dev_cn10ka(struct ptp *ptp) { - return ptp->pdev->device == PCI_DEVID_CN10K_PTP; + return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP; } static bool cn10k_ptp_errata(struct ptp *ptp) { - if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP || - ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP) + if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) && + (is_rev_A0(ptp) || is_rev_A1(ptp))) return true; + return false; } -static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp) +static bool is_tstmp_atomic_update_supported(struct rvu *rvu) { - if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP || - ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP) - return true; - return false; + struct ptp *ptp = rvu->ptp; + + if (is_rvu_otx2(rvu)) + return false; + + /* On older silicon variants of CN10K, atomic update feature + * is not available. + */ + if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) && + (is_rev_A0(ptp) || is_rev_A1(ptp))) + return false; + + return true; } static enum hrtimer_restart ptp_reset_thresh(struct hrtimer *hrtimer) @@ -222,6 +249,65 @@ void ptp_put(struct ptp *ptp) pci_dev_put(ptp->pdev); } +static void ptp_atomic_update(struct ptp *ptp, u64 timestamp) +{ + u64 regval, curr_rollover_set, nxt_rollover_set; + + /* First setup NSECs and SECs */ + writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP); + writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); + writeq(timestamp / NSEC_PER_SEC, + ptp->reg_base + PTP_SEC_TIMESTAMP); + + nxt_rollover_set = roundup(timestamp, NSEC_PER_SEC); + curr_rollover_set = nxt_rollover_set - NSEC_PER_SEC; + writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET); + writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET); + + /* Now, initiate atomic update */ + regval = readq(ptp->reg_base + PTP_CLOCK_CFG); + regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK; + regval |= (ATOMIC_SET << 26); + writeq(regval, ptp->reg_base + PTP_CLOCK_CFG); +} + +static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta) +{ + bool neg_adj = false, atomic_inc_dec = false; + u64 regval, ptp_clock_hi; + + if (delta < 0) { + delta = -delta; + neg_adj = true; + } + + /* use atomic inc/dec when delta < 1 second */ + if (delta < NSEC_PER_SEC) + atomic_inc_dec = true; + + if (!atomic_inc_dec) { + ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI); + if (neg_adj) { + if (ptp_clock_hi > delta) + ptp_clock_hi -= delta; + else + ptp_clock_hi = delta - ptp_clock_hi; + } else { + ptp_clock_hi += delta; + } + ptp_atomic_update(ptp, ptp_clock_hi); + } else { + writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP); + writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); + + /* initiate atomic inc/dec */ + regval = readq(ptp->reg_base + PTP_CLOCK_CFG); + regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK; + regval |= neg_adj ? (ATOMIC_DEC << 26) : (ATOMIC_INC << 26); + writeq(regval, ptp->reg_base + PTP_CLOCK_CFG); + } +} + static int ptp_adjfine(struct ptp *ptp, long scaled_ppm) { bool neg_adj = false; @@ -277,8 +363,9 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk) return 0; } -void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts) +void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts) { + struct ptp *ptp = rvu->ptp; struct pci_dev *pdev; u64 clock_comp; u64 clock_cfg; @@ -297,8 +384,14 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts) ptp->clock_rate = sclk * 1000000; /* Program the seconds rollover value to 1 second */ - if (is_ptp_dev_cnf10kb(ptp)) + if (is_tstmp_atomic_update_supported(rvu)) { + writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP); + writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); + writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP); + writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET); + writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET); writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER); + } /* Enable PTP clock */ clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); @@ -320,6 +413,10 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts) clock_cfg |= PTP_CLOCK_CFG_PTP_EN; clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV; writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); + clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK; + clock_cfg |= (ATOMIC_SET << 26); + writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); /* Set 50% duty cycle for 1Hz output */ writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR); @@ -350,7 +447,7 @@ static int ptp_get_tstmp(struct ptp *ptp, u64 *clk) { u64 timestamp; - if (is_ptp_dev_cn10k(ptp)) { + if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) { timestamp = readq(ptp->reg_base + PTP_TIMESTAMP); *clk = (timestamp >> 32) * NSEC_PER_SEC + (timestamp & 0xFFFFFFFF); } else { @@ -414,14 +511,12 @@ static int ptp_probe(struct pci_dev *pdev, first_ptp_block = ptp; spin_lock_init(&ptp->ptp_lock); - if (is_ptp_tsfmt_sec_nsec(ptp)) - ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec; - else - ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec; - if (cn10k_ptp_errata(ptp)) { + ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec; hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ptp->hrtimer.function = ptp_reset_thresh; + } else { + ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec; } return 0; @@ -521,6 +616,12 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req, case PTP_OP_EXTTS_ON: err = ptp_extts_on(rvu->ptp, req->extts_on); break; + case PTP_OP_ADJTIME: + ptp_atomic_adjtime(rvu->ptp, req->delta); + break; + case PTP_OP_SET_CLOCK: + ptp_atomic_update(rvu->ptp, (u64)req->clk); + break; default: err = -EINVAL; break; @@ -528,3 +629,17 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req, return err; } + +int rvu_mbox_handler_ptp_get_cap(struct rvu *rvu, struct msg_req *req, + struct ptp_get_cap_rsp *rsp) +{ + if (!rvu->ptp) + return -ENODEV; + + if (is_tstmp_atomic_update_supported(rvu)) + rsp->cap |= PTP_CAP_HW_ATOMIC_UPDATE; + else + rsp->cap &= ~BIT_ULL_MASK(0); + + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h index b9d92abc3844..1229344c7279 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h @@ -23,9 +23,10 @@ struct ptp { u32 clock_period; }; +struct rvu; struct ptp *ptp_get(void); void ptp_put(struct ptp *ptp); -void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts); +void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts); extern struct pci_driver ptp_driver; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 73df2d564545..22c395c7d040 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -3322,7 +3322,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&rvu->rswitch.switch_lock); if (rvu->fwdata) - ptp_start(rvu->ptp, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate, + ptp_start(rvu, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate, rvu->fwdata->ptp_ext_tstamp); return 0; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index e8e65fd7888d..c4d999ef5ab4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -17,6 +17,7 @@ #include "mbox.h" #include "npc.h" #include "rvu_reg.h" +#include "ptp.h" /* PCI device IDs */ #define PCI_DEVID_OCTEONTX2_RVU_AF 0xA065 @@ -26,6 +27,7 @@ #define PCI_SUBSYS_DEVID_98XX 0xB100 #define PCI_SUBSYS_DEVID_96XX 0xB200 #define PCI_SUBSYS_DEVID_CN10K_A 0xB900 +#define PCI_SUBSYS_DEVID_CNF10K_A 0xBA00 #define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00 #define PCI_SUBSYS_DEVID_CN10K_B 0xBD00 @@ -634,6 +636,16 @@ static inline bool is_rvu_otx2(struct rvu *rvu) midr == PCI_REVISION_ID_95XXMM || midr == PCI_REVISION_ID_95XXO); } +static inline bool is_cnf10ka_a0(struct rvu *rvu) +{ + struct pci_dev *pdev = rvu->pdev; + + if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A && + (pdev->revision & 0x0F) == 0x0) + return true; + return false; +} + static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu) { u64 npc_const3; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 5fd05d94de7c..4c6032ee7800 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -326,6 +326,7 @@ struct otx2_ptp { struct ptp_pin_desc extts_config; u64 (*convert_rx_ptp_tstmp)(u64 timestamp); u64 (*convert_tx_ptp_tstmp)(u64 timestamp); + u64 (*ptp_tstamp2nsec)(const struct timecounter *time_counter, u64 timestamp); struct delayed_work synctstamp_work; u64 tstamp; u32 base_ns; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c index 896b2f9bac34..3a72b0793d4a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c @@ -10,6 +10,65 @@ #include "otx2_common.h" #include "otx2_ptp.h" +static bool is_tstmp_atomic_update_supported(struct otx2_ptp *ptp) +{ + struct ptp_get_cap_rsp *rsp; + struct msg_req *req; + int err; + + if (!ptp->nic) + return false; + + mutex_lock(&ptp->nic->mbox.lock); + req = otx2_mbox_alloc_msg_ptp_get_cap(&ptp->nic->mbox); + if (!req) { + mutex_unlock(&ptp->nic->mbox.lock); + return false; + } + + err = otx2_sync_mbox_msg(&ptp->nic->mbox); + if (err) { + mutex_unlock(&ptp->nic->mbox.lock); + return false; + } + rsp = (struct ptp_get_cap_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0, + &req->hdr); + mutex_unlock(&ptp->nic->mbox.lock); + + if (IS_ERR(rsp)) + return false; + + if (rsp->cap & PTP_CAP_HW_ATOMIC_UPDATE) + return true; + + return false; +} + +static int otx2_ptp_hw_adjtime(struct ptp_clock_info *ptp_info, s64 delta) +{ + struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, + ptp_info); + struct otx2_nic *pfvf = ptp->nic; + struct ptp_req *req; + int rc; + + if (!ptp->nic) + return -ENODEV; + + mutex_lock(&pfvf->mbox.lock); + req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); + if (!req) { + mutex_unlock(&pfvf->mbox.lock); + return -ENOMEM; + } + req->op = PTP_OP_ADJTIME; + req->delta = delta; + rc = otx2_sync_mbox_msg(&ptp->nic->mbox); + mutex_unlock(&pfvf->mbox.lock); + + return rc; +} + static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp) { struct ptp_req *req; @@ -37,6 +96,49 @@ static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp) return rsp->clk; } +static int otx2_ptp_hw_gettime(struct ptp_clock_info *ptp_info, + struct timespec64 *ts) +{ + struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, + ptp_info); + u64 tstamp; + + tstamp = otx2_ptp_get_clock(ptp); + + *ts = ns_to_timespec64(tstamp); + return 0; +} + +static int otx2_ptp_hw_settime(struct ptp_clock_info *ptp_info, + const struct timespec64 *ts) +{ + struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, + ptp_info); + struct otx2_nic *pfvf = ptp->nic; + struct ptp_req *req; + u64 nsec; + int rc; + + if (!ptp->nic) + return -ENODEV; + + nsec = timespec64_to_ns(ts); + + mutex_lock(&pfvf->mbox.lock); + req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); + if (!req) { + mutex_unlock(&pfvf->mbox.lock); + return -ENOMEM; + } + + req->op = PTP_OP_SET_CLOCK; + req->clk = nsec; + rc = otx2_sync_mbox_msg(&ptp->nic->mbox); + mutex_unlock(&pfvf->mbox.lock); + + return rc; +} + static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) { struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, @@ -124,16 +226,7 @@ static u64 ptp_tstmp_read(struct otx2_ptp *ptp) return rsp->clk; } -static void otx2_get_ptpclock(struct otx2_ptp *ptp, u64 *tstamp) -{ - struct otx2_nic *pfvf = ptp->nic; - - mutex_lock(&pfvf->mbox.lock); - *tstamp = timecounter_read(&ptp->time_counter); - mutex_unlock(&pfvf->mbox.lock); -} - -static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) +static int otx2_ptp_tc_adjtime(struct ptp_clock_info *ptp_info, s64 delta) { struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, ptp_info); @@ -146,32 +239,33 @@ static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) return 0; } -static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info, - struct timespec64 *ts) +static int otx2_ptp_tc_gettime(struct ptp_clock_info *ptp_info, + struct timespec64 *ts) { struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, ptp_info); u64 tstamp; - otx2_get_ptpclock(ptp, &tstamp); + mutex_lock(&ptp->nic->mbox.lock); + tstamp = timecounter_read(&ptp->time_counter); + mutex_unlock(&ptp->nic->mbox.lock); *ts = ns_to_timespec64(tstamp); return 0; } -static int otx2_ptp_settime(struct ptp_clock_info *ptp_info, - const struct timespec64 *ts) +static int otx2_ptp_tc_settime(struct ptp_clock_info *ptp_info, + const struct timespec64 *ts) { struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, ptp_info); - struct otx2_nic *pfvf = ptp->nic; u64 nsec; nsec = timespec64_to_ns(ts); - mutex_lock(&pfvf->mbox.lock); + mutex_lock(&ptp->nic->mbox.lock); timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec); - mutex_unlock(&pfvf->mbox.lock); + mutex_unlock(&ptp->nic->mbox.lock); return 0; } @@ -190,6 +284,12 @@ static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, return 0; } +static u64 otx2_ptp_hw_tstamp2time(const struct timecounter *time_counter, u64 tstamp) +{ + /* On HW which supports atomic updates, timecounter is not initialized */ + return tstamp; +} + static void otx2_ptp_extts_check(struct work_struct *work) { struct otx2_ptp *ptp = container_of(work, struct otx2_ptp, @@ -204,7 +304,7 @@ static void otx2_ptp_extts_check(struct work_struct *work) if (tstmp != ptp->last_extts) { event.type = PTP_CLOCK_EXTTS; event.index = 0; - event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp); + event.timestamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstmp); ptp_clock_event(ptp->ptp_clock, &event); new_thresh = tstmp % 500000000; if (ptp->thresh != new_thresh) { @@ -229,7 +329,7 @@ static void otx2_sync_tstamp(struct work_struct *work) tstamp = otx2_ptp_get_clock(ptp); mutex_unlock(&pfvf->mbox.lock); - ptp->tstamp = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp); + ptp->tstamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstamp); ptp->base_ns = tstamp % NSEC_PER_SEC; schedule_delayed_work(&ptp->synctstamp_work, msecs_to_jiffies(250)); @@ -302,15 +402,6 @@ int otx2_ptp_init(struct otx2_nic *pfvf) ptp_ptr->nic = pfvf; - cc = &ptp_ptr->cycle_counter; - cc->read = ptp_cc_read; - cc->mask = CYCLECOUNTER_MASK(64); - cc->mult = 1; - cc->shift = 0; - - timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter, - ktime_to_ns(ktime_get_real())); - snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP"); ptp_ptr->extts_config.index = 0; ptp_ptr->extts_config.func = PTP_PF_NONE; @@ -324,13 +415,33 @@ int otx2_ptp_init(struct otx2_nic *pfvf) .pps = 0, .pin_config = &ptp_ptr->extts_config, .adjfine = otx2_ptp_adjfine, - .adjtime = otx2_ptp_adjtime, - .gettime64 = otx2_ptp_gettime, - .settime64 = otx2_ptp_settime, .enable = otx2_ptp_enable, .verify = otx2_ptp_verify_pin, }; + /* Check whether hardware supports atomic updates to timestamp */ + if (is_tstmp_atomic_update_supported(ptp_ptr)) { + ptp_ptr->ptp_info.adjtime = otx2_ptp_hw_adjtime; + ptp_ptr->ptp_info.gettime64 = otx2_ptp_hw_gettime; + ptp_ptr->ptp_info.settime64 = otx2_ptp_hw_settime; + + ptp_ptr->ptp_tstamp2nsec = otx2_ptp_hw_tstamp2time; + } else { + ptp_ptr->ptp_info.adjtime = otx2_ptp_tc_adjtime; + ptp_ptr->ptp_info.gettime64 = otx2_ptp_tc_gettime; + ptp_ptr->ptp_info.settime64 = otx2_ptp_tc_settime; + + cc = &ptp_ptr->cycle_counter; + cc->read = ptp_cc_read; + cc->mask = CYCLECOUNTER_MASK(64); + cc->mult = 1; + cc->shift = 0; + ptp_ptr->ptp_tstamp2nsec = timecounter_cyc2time; + + timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter, + ktime_to_ns(ktime_get_real())); + } + INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check); ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev); @@ -387,7 +498,7 @@ int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns) if (!pfvf->ptp) return -ENODEV; - *tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp); + *tsns = pfvf->ptp->ptp_tstamp2nsec(&pfvf->ptp->time_counter, tstamp); return 0; } -- cgit From eb6603246ab9a3787e9603f0fd6a321b46623e46 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 21 Aug 2023 21:00:02 +0800 Subject: qed/qede: Remove unused declarations Commit 8cd160a29415 ("qede: convert to new udp_tunnel_nic infra") removed qede_udp_tunnel_{add,del}() but not the declarations. Commit 0ebcebbef1cc ("qed: Read device port count from the shmem") removed qed_device_num_engines() but not its declaration. Commit 1e128c81290a ("qed: Add support for hardware offloaded FCoE.") declared but never implemented qed_fcoe_set_pf_params(). Signed-off-by: Yue Haibing Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 1 - drivers/net/ethernet/qlogic/qede/qede.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index d613095b78e0..1d719726f72b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -909,7 +909,6 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate); void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); -int qed_device_num_engines(struct qed_dev *cdev); void qed_set_fw_mac_addr(__le16 *fw_msb, __le16 *fw_mid, __le16 *fw_lsb, u8 *mac); diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 4d83ceebdc49..042a75f34060 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -556,9 +556,6 @@ void qede_config_rx_mode(struct net_device *ndev); void qede_fill_rss_params(struct qede_dev *edev, struct qed_update_vport_rss_params *rss, u8 *update); -void qede_udp_tunnel_add(struct net_device *dev, struct udp_tunnel_info *ti); -void qede_udp_tunnel_del(struct net_device *dev, struct udp_tunnel_info *ti); - int qede_xdp(struct net_device *dev, struct netdev_bpf *xdp); #ifdef CONFIG_DCB -- cgit From 71ab55a9af80fcffe1f42b9b8dba4d0e3dd0c351 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:15 +0200 Subject: mlx4: Get rid of the mlx4_interface.get_dev callback Simplify the mlx4 driver interface by removing mlx4_get_protocol_dev() and the associated mlx4_interface.get_dev callbacks. This is done in preparation to use an auxiliary bus to model the mlx4 driver structure. The change is motivated by the following situation: * The mlx4_en interface is being initialized by mlx4_en_add() and mlx4_en_activate(). * The latter activate function calls mlx4_en_init_netdev() -> register_netdev() to register a new net_device. * A netdev event NETDEV_REGISTER is raised for the device. * The netdev notififier mlx4_ib_netdev_event() is called and it invokes mlx4_ib_scan_netdevs() -> mlx4_get_protocol_dev() -> mlx4_en_get_netdev() [via mlx4_interface.get_dev]. This chain creates a problem when mlx4_en gets switched to be an auxiliary driver. It contains two device calls which would both need to take a respective device lock. Avoid this situation by updating mlx4_ib_scan_netdevs() to no longer call mlx4_get_protocol_dev() but instead to utilize the information passed in net_device.parent and net_device.dev_port. This data is sufficient to determine that an updated port is one that the mlx4_ib driver should take care of and to keep mlx4_ib_dev.iboe.netdevs up to date. Following that, update mlx4_ib_get_netdev() to also not call mlx4_get_protocol_dev() and instead scan all current netdevs to find find a matching one. Note that mlx4_ib_get_netdev() is called early from ib_register_device() and cannot use data tracked in mlx4_ib_dev.iboe.netdevs which is not at that point yet set. Finally, remove function mlx4_get_protocol_dev() and the mlx4_interface.get_dev callbacks (only mlx4_en_get_netdev()) as they became unused. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 8 -------- drivers/net/ethernet/mellanox/mlx4/intf.c | 21 --------------------- 2 files changed, 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index f1259bdb1a29..6a42bec6bd85 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -183,13 +183,6 @@ static void mlx4_en_get_profile(struct mlx4_en_dev *mdev) } } -static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port) -{ - struct mlx4_en_dev *endev = ctx; - - return endev->pndev[port]; -} - static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, enum mlx4_dev_event event, unsigned long port) { @@ -354,7 +347,6 @@ static struct mlx4_interface mlx4_en_interface = { .add = mlx4_en_add, .remove = mlx4_en_remove, .event = mlx4_en_event, - .get_dev = mlx4_en_get_netdev, .protocol = MLX4_PROT_ETH, .activate = mlx4_en_activate, }; diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 65482f004e50..28d7da925d36 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -245,27 +245,6 @@ void mlx4_unregister_device(struct mlx4_dev *dev) mutex_unlock(&intf_mutex); } -void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_device_context *dev_ctx; - unsigned long flags; - void *result = NULL; - - spin_lock_irqsave(&priv->ctx_lock, flags); - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) { - result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port); - break; - } - - spin_unlock_irqrestore(&priv->ctx_lock, flags); - - return result; -} -EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev); - struct devlink_port *mlx4_get_devlink_port(struct mlx4_dev *dev, int port) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; -- cgit From ef5617e34376545a1e230480beaed49466535274 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:16 +0200 Subject: mlx4: Rename member mlx4_en_dev.nb to netdev_nb Rename the mlx4_en_dev.nb notifier_block member to netdev_nb in preparation to add a mlx4 core notifier_block. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 14 +++++++------- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 +- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 6a42bec6bd85..be8ba34c9025 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -235,8 +235,8 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) iounmap(mdev->uar_map); mlx4_uar_free(dev, &mdev->priv_uar); mlx4_pd_free(dev, mdev->priv_pdn); - if (mdev->nb.notifier_call) - unregister_netdevice_notifier(&mdev->nb); + if (mdev->netdev_nb.notifier_call) + unregister_netdevice_notifier(&mdev->netdev_nb); kfree(mdev); } @@ -252,11 +252,11 @@ static void mlx4_en_activate(struct mlx4_dev *dev, void *ctx) mdev->pndev[i] = NULL; } - /* register notifier */ - mdev->nb.notifier_call = mlx4_en_netdev_event; - if (register_netdevice_notifier(&mdev->nb)) { - mdev->nb.notifier_call = NULL; - mlx4_err(mdev, "Failed to create notifier\n"); + /* register netdev notifier */ + mdev->netdev_nb.notifier_call = mlx4_en_netdev_event; + if (register_netdevice_notifier(&mdev->netdev_nb)) { + mdev->netdev_nb.notifier_call = NULL; + mlx4_err(mdev, "Failed to create netdev notifier\n"); } } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 403604ceebc8..7066c426b95c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2967,7 +2967,7 @@ int mlx4_en_netdev_event(struct notifier_block *this, if (!net_eq(dev_net(ndev), &init_net)) return NOTIFY_DONE; - mdev = container_of(this, struct mlx4_en_dev, nb); + mdev = container_of(this, struct mlx4_en_dev, netdev_nb); dev = mdev->dev; /* Go into this mode only when two network devices set on two ports diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 321f801c1d7c..72a3fea36702 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -432,7 +432,7 @@ struct mlx4_en_dev { unsigned long last_overflow_check; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; - struct notifier_block nb; + struct notifier_block netdev_nb; }; -- cgit From 7ba189ac52acab44129f09b302069e5a86fd92c2 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:17 +0200 Subject: mlx4: Use 'void *' as the event param of mlx4_dispatch_event() Function mlx4_dispatch_event() takes an 'unsigned long' as its event parameter. The actual value is none (MLX4_DEV_EVENT_CATASTROPHIC_ERROR), a pointer to mlx4_eqe (MLX4_DEV_EVENT_PORT_MGMT_CHANGE), or a 32-bit integer (remaining events). In preparation to switch mlx4_en and mlx4_ib to be an auxiliary device, the mlx4_interface.event callback is replaced with a notifier and function mlx4_dispatch_event() gets updated to invoke atomic_notifier_call_chain(). This requires forwarding the input 'param' value from the former function to the latter. A problem is that the notifier call takes 'void *' as its 'param' value, compared to 'unsigned long' used by mlx4_dispatch_event(). Re-passing the value would need either punning it to 'void *' or passing down the address of the input 'param'. Both approaches create a number of unnecessary casts. Change instead the input 'param' of mlx4_dispatch_event() from 'unsigned long' to 'void *'. A mlx4_eqe pointer can be passed directly, callers using an int value are adjusted to pass its address. Signed-off-by: Petr Pavlu Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/catas.c | 2 +- drivers/net/ethernet/mellanox/mlx4/cmd.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/en_main.c | 17 +++++++++++++++-- drivers/net/ethernet/mellanox/mlx4/eq.c | 15 ++++++++------- drivers/net/ethernet/mellanox/mlx4/intf.c | 2 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 +- 6 files changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c index 0eb7b83637d8..0d8a362c2673 100644 --- a/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c @@ -194,7 +194,7 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist) mutex_unlock(&persist->device_state_mutex); /* At that step HW was already reset, now notify clients */ - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0); + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, NULL); mlx4_cmd_wake_completions(dev); return; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index c56d2194cbfc..f5b1f8c7834f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2113,7 +2113,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) goto inform_slave_state; - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, slave); + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, &slave); /* write the version in the event field */ reply |= mlx4_comm_get_version(); @@ -2152,7 +2152,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, if (mlx4_master_activate_admin_state(priv, slave)) goto reset_slave; slave_state[slave].active = true; - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave); + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, &slave); break; case MLX4_COMM_CMD_VHCR_POST: if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) && diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index be8ba34c9025..83dae886ade6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -184,10 +184,22 @@ static void mlx4_en_get_profile(struct mlx4_en_dev *mdev) } static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, - enum mlx4_dev_event event, unsigned long port) + enum mlx4_dev_event event, void *param) { struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; struct mlx4_en_priv *priv; + int port; + + switch (event) { + case MLX4_DEV_EVENT_CATASTROPHIC_ERROR: + case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: + case MLX4_DEV_EVENT_SLAVE_INIT: + case MLX4_DEV_EVENT_SLAVE_SHUTDOWN: + break; + default: + port = *(int *)param; + break; + } switch (event) { case MLX4_DEV_EVENT_PORT_UP: @@ -205,6 +217,7 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, mlx4_err(mdev, "Internal error detected, restarting device\n"); break; + case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: case MLX4_DEV_EVENT_SLAVE_INIT: case MLX4_DEV_EVENT_SLAVE_SHUTDOWN: break; @@ -213,7 +226,7 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, !mdev->pndev[port]) return; mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, - (int) port); + port); } } diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 414e390e6b48..6598b10a9ff4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -501,7 +501,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) int port; int slave = 0; int ret; - u32 flr_slave; + int flr_slave; u8 update_slave_state; int i; enum slave_port_gen_event gen_event; @@ -606,8 +606,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) port = be32_to_cpu(eqe->event.port_change.port) >> 28; slaves_port = mlx4_phys_to_slaves_pport(dev, port); if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) { - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN, - port); + mlx4_dispatch_event( + dev, MLX4_DEV_EVENT_PORT_DOWN, &port); mlx4_priv(dev)->sense.do_sense_port[port] = 1; if (!mlx4_is_master(dev)) break; @@ -647,7 +647,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) } } } else { - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP, port); + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP, + &port); mlx4_priv(dev)->sense.do_sense_port[port] = 0; @@ -758,7 +759,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) } spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, - flr_slave); + &flr_slave); queue_work(priv->mfunc.master.comm_wq, &priv->mfunc.master.slave_flr_event_work); break; @@ -787,8 +788,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) break; case MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT: - mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_MGMT_CHANGE, - (unsigned long) eqe); + mlx4_dispatch_event( + dev, MLX4_DEV_EVENT_PORT_MGMT_CHANGE, eqe); break; case MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT: diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 28d7da925d36..a761971cd0c4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -180,7 +180,7 @@ int mlx4_do_bond(struct mlx4_dev *dev, bool enable) } void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, - unsigned long param) + void *param) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_device_context *dev_ctx; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 6ccf340660d9..de5699a4ddaa 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1048,7 +1048,7 @@ int mlx4_restart_one(struct pci_dev *pdev); int mlx4_register_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev); void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, - unsigned long param); + void *param); struct mlx4_dev_cap; struct mlx4_init_hca_param; -- cgit From 73d68002a02efd370dba6b8fc570427326e36d1a Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:18 +0200 Subject: mlx4: Replace the mlx4_interface.event callback with a notifier Use a notifier to implement mlx4_dispatch_event() in preparation to switch mlx4_en and mlx4_ib to be an auxiliary device. A problem is that if the mlx4_interface.event callback was replaced with something as mlx4_adrv.event then the implementation of mlx4_dispatch_event() would need to acquire a lock on a given device before executing this callback. That is necessary because otherwise there is no guarantee that the associated driver cannot get unbound when the callback is running. However, taking this lock is not possible because mlx4_dispatch_event() can be invoked from the hardirq context. Using an atomic notifier allows the driver to accurately record when it wants to receive these events and solves this problem. A handler registration is done by both mlx4_en and mlx4_ib at the end of their mlx4_interface.add callback. This matches the current situation when mlx4_add_device() would enable events for a given device immediately after this callback, by adding the device on the mlx4_priv.list. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Acked-by: Tariq Toukan Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 26 ++++++++++++++++++-------- drivers/net/ethernet/mellanox/mlx4/intf.c | 24 +++++++++++++++++------- drivers/net/ethernet/mellanox/mlx4/main.c | 2 ++ drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 ++ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 ++ 5 files changed, 41 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 83dae886ade6..31bf625b8158 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -183,10 +183,12 @@ static void mlx4_en_get_profile(struct mlx4_en_dev *mdev) } } -static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, - enum mlx4_dev_event event, void *param) +static int mlx4_en_event(struct notifier_block *this, unsigned long event, + void *param) { - struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; + struct mlx4_en_dev *mdev = + container_of(this, struct mlx4_en_dev, mlx_nb); + struct mlx4_dev *dev = mdev->dev; struct mlx4_en_priv *priv; int port; @@ -205,7 +207,7 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, case MLX4_DEV_EVENT_PORT_UP: case MLX4_DEV_EVENT_PORT_DOWN: if (!mdev->pndev[port]) - return; + return NOTIFY_DONE; priv = netdev_priv(mdev->pndev[port]); /* To prevent races, we poll the link state in a separate task rather than changing it here */ @@ -224,10 +226,12 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, default: if (port < 1 || port > dev->caps.num_ports || !mdev->pndev[port]) - return; - mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, + return NOTIFY_DONE; + mlx4_warn(mdev, "Unhandled event %d for port %d\n", (int)event, port); } + + return NOTIFY_DONE; } static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) @@ -235,6 +239,8 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) struct mlx4_en_dev *mdev = endev_ptr; int i; + mlx4_unregister_event_notifier(dev, &mdev->mlx_nb); + mutex_lock(&mdev->state_lock); mdev->device_up = false; mutex_unlock(&mdev->state_lock); @@ -276,7 +282,7 @@ static void mlx4_en_activate(struct mlx4_dev *dev, void *ctx) static void *mlx4_en_add(struct mlx4_dev *dev) { struct mlx4_en_dev *mdev; - int i; + int err, i; printk_once(KERN_INFO "%s", mlx4_en_version); @@ -339,6 +345,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mutex_init(&mdev->state_lock); mdev->device_up = true; + /* register mlx4 core notifier */ + mdev->mlx_nb.notifier_call = mlx4_en_event; + err = mlx4_register_event_notifier(dev, &mdev->mlx_nb); + WARN(err, "failed to register mlx4 event notifier (%d)", err); + return mdev; err_mr: @@ -359,7 +370,6 @@ err_free_res: static struct mlx4_interface mlx4_en_interface = { .add = mlx4_en_add, .remove = mlx4_en_remove, - .event = mlx4_en_event, .protocol = MLX4_PROT_ETH, .activate = mlx4_en_activate, }; diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index a761971cd0c4..fecb63e69607 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -183,17 +183,27 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, void *param) { struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_device_context *dev_ctx; - unsigned long flags; - spin_lock_irqsave(&priv->ctx_lock, flags); + atomic_notifier_call_chain(&priv->event_nh, type, param); +} - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf->event) - dev_ctx->intf->event(dev, dev_ctx->context, type, param); +int mlx4_register_event_notifier(struct mlx4_dev *dev, + struct notifier_block *nb) +{ + struct mlx4_priv *priv = mlx4_priv(dev); - spin_unlock_irqrestore(&priv->ctx_lock, flags); + return atomic_notifier_chain_register(&priv->event_nh, nb); +} +EXPORT_SYMBOL(mlx4_register_event_notifier); + +int mlx4_unregister_event_notifier(struct mlx4_dev *dev, + struct notifier_block *nb) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + + return atomic_notifier_chain_unregister(&priv->event_nh, nb); } +EXPORT_SYMBOL(mlx4_unregister_event_notifier); int mlx4_register_device(struct mlx4_dev *dev) { diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 8a5409b00530..5f3ba8385e23 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -3378,6 +3378,8 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); + ATOMIC_INIT_NOTIFIER_HEAD(&priv->event_nh); + mutex_init(&priv->port_mutex); mutex_init(&priv->bond_mutex); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index de5699a4ddaa..8dbea814a2f5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -878,6 +879,7 @@ struct mlx4_priv { struct list_head dev_list; struct list_head ctx_list; spinlock_t ctx_lock; + struct atomic_notifier_head event_nh; int pci_dev_data; int removed; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 72a3fea36702..efe3f97b874f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -433,6 +434,7 @@ struct mlx4_en_dev { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; struct notifier_block netdev_nb; + struct notifier_block mlx_nb; }; -- cgit From 13f857111cb23f2a8dbcd0271c3ff1824913d980 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:19 +0200 Subject: mlx4: Get rid of the mlx4_interface.activate callback The mlx4_interface.activate callback was introduced in commit 79857cd31fe7 ("net/mlx4: Postpone the registration of net_device"). It dealt with a situation when a netdev notifier received a NETDEV_REGISTER event for a new net_device created by mlx4_en but the same device was not yet visible to mlx4_get_protocol_dev(). The callback can be removed now that mlx4_get_protocol_dev() is gone. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 37 ++++++++++++---------------- drivers/net/ethernet/mellanox/mlx4/intf.c | 2 -- 2 files changed, 16 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 31bf625b8158..39c9befeb638 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -259,26 +259,6 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) kfree(mdev); } -static void mlx4_en_activate(struct mlx4_dev *dev, void *ctx) -{ - int i; - struct mlx4_en_dev *mdev = ctx; - - /* Create a netdev for each port */ - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { - mlx4_info(mdev, "Activating port:%d\n", i); - if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) - mdev->pndev[i] = NULL; - } - - /* register netdev notifier */ - mdev->netdev_nb.notifier_call = mlx4_en_netdev_event; - if (register_netdevice_notifier(&mdev->netdev_nb)) { - mdev->netdev_nb.notifier_call = NULL; - mlx4_err(mdev, "Failed to create netdev notifier\n"); - } -} - static void *mlx4_en_add(struct mlx4_dev *dev) { struct mlx4_en_dev *mdev; @@ -350,6 +330,22 @@ static void *mlx4_en_add(struct mlx4_dev *dev) err = mlx4_register_event_notifier(dev, &mdev->mlx_nb); WARN(err, "failed to register mlx4 event notifier (%d)", err); + /* Setup ports */ + + /* Create a netdev for each port */ + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { + mlx4_info(mdev, "Activating port:%d\n", i); + if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) + mdev->pndev[i] = NULL; + } + + /* register netdev notifier */ + mdev->netdev_nb.notifier_call = mlx4_en_netdev_event; + if (register_netdevice_notifier(&mdev->netdev_nb)) { + mdev->netdev_nb.notifier_call = NULL; + mlx4_err(mdev, "Failed to create netdev notifier\n"); + } + return mdev; err_mr: @@ -371,7 +367,6 @@ static struct mlx4_interface mlx4_en_interface = { .add = mlx4_en_add, .remove = mlx4_en_remove, .protocol = MLX4_PROT_ETH, - .activate = mlx4_en_activate, }; static void mlx4_en_verify_params(void) diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index fecb63e69607..8cbc1bcdfe77 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -64,8 +64,6 @@ static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) spin_lock_irq(&priv->ctx_lock); list_add_tail(&dev_ctx->list, &priv->ctx_list); spin_unlock_irq(&priv->ctx_lock); - if (intf->activate) - intf->activate(&priv->dev, dev_ctx->context); } else kfree(dev_ctx); -- cgit From e2fb47d4eb5cd245c38c8c57d969ac6b12efc764 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:20 +0200 Subject: mlx4: Move the bond work to the core driver Function mlx4_en_queue_bond_work() is used in mlx4_en to start a bond reconfiguration. It gathers data about a new port map setting, takes a reference on the netdev that triggered the change and queues a work object on mlx4_en_priv.mdev.workqueue to perform the operation. The scheduled work is mlx4_en_bond_work() which calls mlx4_bond()/mlx4_unbond() and consequently mlx4_do_bond(). At the same time, function mlx4_change_port_types() in mlx4_core might be invoked to change the port type configuration. As part of its logic, it re-registers the whole device by calling mlx4_unregister_device(), followed by mlx4_register_device(). The two operations can result in concurrent access to the data about currently active interfaces on the device. Functions mlx4_register_device() and mlx4_unregister_device() lock the intf_mutex to gain exclusive access to this data. The current implementation of mlx4_do_bond() doesn't do that which could result in an unexpected behavior. An updated version of mlx4_do_bond() for use with an auxiliary bus goes and locks the intf_mutex when accessing a new auxiliary device array. However, doing so can then result in the following deadlock: * A two-port mlx4 device is configured as an Ethernet bond. * One of the ports is changed from eth to ib, for instance, by writing into a mlx4_port sysfs attribute file. * mlx4_change_port_types() is called to update port types. It invokes mlx4_unregister_device() to unregister the device which locks the intf_mutex and starts removing all associated interfaces. * Function mlx4_en_remove() gets invoked and starts destroying its first netdev. This triggers mlx4_en_netdev_event() which recognizes that the configured bond is broken. It runs mlx4_en_queue_bond_work() which takes a reference on the netdev. Removing the netdev now cannot proceed until the work is completed. * Work function mlx4_en_bond_work() gets scheduled. It calls mlx4_unbond() -> mlx4_do_bond(). The latter function tries to lock the intf_mutex but that is not possible because it is held already by mlx4_unregister_device(). This particular case could be possibly solved by unregistering the mlx4_en_netdev_event() notifier in mlx4_en_remove() earlier, but it seems better to decouple mlx4_en more and break this reference order. Avoid then this scenario by recognizing that the bond reconfiguration operates only on a mlx4_dev. The logic to queue and execute the bond work can be moved into the mlx4_core driver. Only a reference on the respective mlx4_dev object is needed to be taken during the work's lifetime. This removes a call from mlx4_en that can directly result in needing to lock the intf_mutex, it remains a privilege of the core driver. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 62 +----------------------- drivers/net/ethernet/mellanox/mlx4/main.c | 65 +++++++++++++++++++++++--- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 5 ++ 3 files changed, 64 insertions(+), 68 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 7066c426b95c..33bbcced8105 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2894,63 +2894,6 @@ static const struct xdp_metadata_ops mlx4_xdp_metadata_ops = { .xmo_rx_hash = mlx4_en_xdp_rx_hash, }; -struct mlx4_en_bond { - struct work_struct work; - struct mlx4_en_priv *priv; - int is_bonded; - struct mlx4_port_map port_map; -}; - -static void mlx4_en_bond_work(struct work_struct *work) -{ - struct mlx4_en_bond *bond = container_of(work, - struct mlx4_en_bond, - work); - int err = 0; - struct mlx4_dev *dev = bond->priv->mdev->dev; - - if (bond->is_bonded) { - if (!mlx4_is_bonded(dev)) { - err = mlx4_bond(dev); - if (err) - en_err(bond->priv, "Fail to bond device\n"); - } - if (!err) { - err = mlx4_port_map_set(dev, &bond->port_map); - if (err) - en_err(bond->priv, "Fail to set port map [%d][%d]: %d\n", - bond->port_map.port1, - bond->port_map.port2, - err); - } - } else if (mlx4_is_bonded(dev)) { - err = mlx4_unbond(dev); - if (err) - en_err(bond->priv, "Fail to unbond device\n"); - } - dev_put(bond->priv->dev); - kfree(bond); -} - -static int mlx4_en_queue_bond_work(struct mlx4_en_priv *priv, int is_bonded, - u8 v2p_p1, u8 v2p_p2) -{ - struct mlx4_en_bond *bond; - - bond = kzalloc(sizeof(*bond), GFP_ATOMIC); - if (!bond) - return -ENOMEM; - - INIT_WORK(&bond->work, mlx4_en_bond_work); - bond->priv = priv; - bond->is_bonded = is_bonded; - bond->port_map.port1 = v2p_p1; - bond->port_map.port2 = v2p_p2; - dev_hold(priv->dev); - queue_work(priv->mdev->workqueue, &bond->work); - return 0; -} - int mlx4_en_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -2960,7 +2903,6 @@ int mlx4_en_netdev_event(struct notifier_block *this, struct mlx4_dev *dev; int i, num_eth_ports = 0; bool do_bond = true; - struct mlx4_en_priv *priv; u8 v2p_port1 = 0; u8 v2p_port2 = 0; @@ -2995,7 +2937,6 @@ int mlx4_en_netdev_event(struct notifier_block *this, if ((do_bond && (event != NETDEV_BONDING_INFO)) || !port) return NOTIFY_DONE; - priv = netdev_priv(ndev); if (do_bond) { struct netdev_notifier_bonding_info *notifier_info = ptr; struct netdev_bonding_info *bonding_info = @@ -3062,8 +3003,7 @@ int mlx4_en_netdev_event(struct notifier_block *this, } } - mlx4_en_queue_bond_work(priv, do_bond, - v2p_port1, v2p_port2); + mlx4_queue_bond_work(dev, do_bond, v2p_port1, v2p_port2); return NOTIFY_DONE; } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 5f3ba8385e23..0ed490b99163 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1441,7 +1441,7 @@ static int mlx4_mf_unbond(struct mlx4_dev *dev) return ret; } -int mlx4_bond(struct mlx4_dev *dev) +static int mlx4_bond(struct mlx4_dev *dev) { int ret = 0; struct mlx4_priv *priv = mlx4_priv(dev); @@ -1467,9 +1467,8 @@ int mlx4_bond(struct mlx4_dev *dev) return ret; } -EXPORT_SYMBOL_GPL(mlx4_bond); -int mlx4_unbond(struct mlx4_dev *dev) +static int mlx4_unbond(struct mlx4_dev *dev) { int ret = 0; struct mlx4_priv *priv = mlx4_priv(dev); @@ -1496,10 +1495,8 @@ int mlx4_unbond(struct mlx4_dev *dev) return ret; } -EXPORT_SYMBOL_GPL(mlx4_unbond); - -int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p) +static int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p) { u8 port1 = v2p->port1; u8 port2 = v2p->port2; @@ -1541,7 +1538,61 @@ int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p) mutex_unlock(&priv->bond_mutex); return err; } -EXPORT_SYMBOL_GPL(mlx4_port_map_set); + +struct mlx4_bond { + struct work_struct work; + struct mlx4_dev *dev; + int is_bonded; + struct mlx4_port_map port_map; +}; + +static void mlx4_bond_work(struct work_struct *work) +{ + struct mlx4_bond *bond = container_of(work, struct mlx4_bond, work); + int err = 0; + + if (bond->is_bonded) { + if (!mlx4_is_bonded(bond->dev)) { + err = mlx4_bond(bond->dev); + if (err) + mlx4_err(bond->dev, "Fail to bond device\n"); + } + if (!err) { + err = mlx4_port_map_set(bond->dev, &bond->port_map); + if (err) + mlx4_err(bond->dev, + "Fail to set port map [%d][%d]: %d\n", + bond->port_map.port1, + bond->port_map.port2, err); + } + } else if (mlx4_is_bonded(bond->dev)) { + err = mlx4_unbond(bond->dev); + if (err) + mlx4_err(bond->dev, "Fail to unbond device\n"); + } + put_device(&bond->dev->persist->pdev->dev); + kfree(bond); +} + +int mlx4_queue_bond_work(struct mlx4_dev *dev, int is_bonded, u8 v2p_p1, + u8 v2p_p2) +{ + struct mlx4_bond *bond; + + bond = kzalloc(sizeof(*bond), GFP_ATOMIC); + if (!bond) + return -ENOMEM; + + INIT_WORK(&bond->work, mlx4_bond_work); + get_device(&dev->persist->pdev->dev); + bond->dev = dev; + bond->is_bonded = is_bonded; + bond->port_map.port1 = v2p_p1; + bond->port_map.port2 = v2p_p2; + queue_work(mlx4_wq, &bond->work); + return 0; +} +EXPORT_SYMBOL(mlx4_queue_bond_work); static int mlx4_load_fw(struct mlx4_dev *dev) { diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 8dbea814a2f5..73b4fdfd63f4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -863,6 +863,11 @@ struct mlx4_steer { struct list_head steer_entries[MLX4_NUM_STEERS]; }; +struct mlx4_port_map { + u8 port1; + u8 port2; +}; + enum { MLX4_PCI_DEV_IS_VF = 1 << 0, MLX4_PCI_DEV_FORCE_SENSE_PORT = 1 << 1, -- cgit From c9452b8fd2ec249fa61e8a36726bde3af60a86d4 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:21 +0200 Subject: mlx4: Avoid resetting MLX4_INTFF_BONDING per driver The mlx4_core driver has a logic that allows a sub-driver to set the MLX4_INTFF_BONDING flag which then causes that function mlx4_do_bond() asks the sub-driver to fully re-probe a device when its bonding configuration changes. Performing this operation is disallowed in mlx4_register_interface() when it is detected that any mlx4 device is multifunction (SRIOV). The code then resets MLX4_INTFF_BONDING in the driver flags. Move this check directly into mlx4_do_bond(). It provides a better separation as mlx4_core no longer directly modifies the sub-driver flags and it will allow to get rid of explicitly keeping track of all mlx4 devices by the intf.c code when it is switched to an auxiliary bus. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/intf.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 8cbc1bcdfe77..d578f754d882 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -96,11 +96,6 @@ int mlx4_register_interface(struct mlx4_interface *intf) list_add_tail(&intf->list, &intf_list); list_for_each_entry(priv, &dev_list, dev_list) { - if (mlx4_is_mfunc(&priv->dev) && (intf->flags & MLX4_INTFF_BONDING)) { - mlx4_dbg(&priv->dev, - "SRIOV, disabling HA mode for intf proto %d\n", intf->protocol); - intf->flags &= ~MLX4_INTFF_BONDING; - } mlx4_add_device(intf, priv); } @@ -155,10 +150,18 @@ int mlx4_do_bond(struct mlx4_dev *dev, bool enable) spin_lock_irqsave(&priv->ctx_lock, flags); list_for_each_entry_safe(dev_ctx, temp_dev_ctx, &priv->ctx_list, list) { - if (dev_ctx->intf->flags & MLX4_INTFF_BONDING) { - list_add_tail(&dev_ctx->bond_list, &bond_list); - list_del(&dev_ctx->list); + if (!(dev_ctx->intf->flags & MLX4_INTFF_BONDING)) + continue; + + if (mlx4_is_mfunc(dev)) { + mlx4_dbg(dev, + "SRIOV, disabled HA mode for intf proto %d\n", + dev_ctx->intf->protocol); + continue; } + + list_add_tail(&dev_ctx->bond_list, &bond_list); + list_del(&dev_ctx->list); } spin_unlock_irqrestore(&priv->ctx_lock, flags); -- cgit From 8c2d2b87719bad9c1db4a7919e74f7818a8ca3de Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:22 +0200 Subject: mlx4: Register mlx4 devices to an auxiliary virtual bus Add an auxiliary virtual bus to model the mlx4 driver structure. The code is added along the current custom device management logic. Subsequent patches switch mlx4_en and mlx4_ib to the auxiliary bus and the old interface is then removed. Structure mlx4_priv gains a new adev dynamic array to keep track of its auxiliary devices. Access to the array is protected by the global mlx4_intf mutex. Functions mlx4_register_device() and mlx4_unregister_device() are updated to expose auxiliary devices on the bus in order to load mlx4_en and/or mlx4_ib. Functions mlx4_register_auxiliary_driver() and mlx4_unregister_auxiliary_driver() are added to substitute mlx4_register_interface() and mlx4_unregister_interface(), respectively. Function mlx4_do_bond() is adjusted to walk over the adev array and re-adds a specific auxiliary device if its driver sets the MLX4_INTFF_BONDING flag. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/Kconfig | 1 + drivers/net/ethernet/mellanox/mlx4/intf.c | 230 ++++++++++++++++++++++++++++- drivers/net/ethernet/mellanox/mlx4/main.c | 17 ++- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 6 + 4 files changed, 250 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig index 1b4b1f642317..825e05fb8607 100644 --- a/drivers/net/ethernet/mellanox/mlx4/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig @@ -27,6 +27,7 @@ config MLX4_EN_DCB config MLX4_CORE tristate depends on PCI + select AUXILIARY_BUS select NET_DEVLINK default n diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index d578f754d882..79b1eaa62ac2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -48,6 +48,89 @@ struct mlx4_device_context { static LIST_HEAD(intf_list); static LIST_HEAD(dev_list); static DEFINE_MUTEX(intf_mutex); +static DEFINE_IDA(mlx4_adev_ida); + +static const struct mlx4_adev_device { + const char *suffix; + bool (*is_supported)(struct mlx4_dev *dev); +} mlx4_adev_devices[1] = {}; + +int mlx4_adev_init(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + + priv->adev_idx = ida_alloc(&mlx4_adev_ida, GFP_KERNEL); + if (priv->adev_idx < 0) + return priv->adev_idx; + + priv->adev = kcalloc(ARRAY_SIZE(mlx4_adev_devices), + sizeof(struct mlx4_adev *), GFP_KERNEL); + if (!priv->adev) { + ida_free(&mlx4_adev_ida, priv->adev_idx); + return -ENOMEM; + } + + return 0; +} + +void mlx4_adev_cleanup(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + + kfree(priv->adev); + ida_free(&mlx4_adev_ida, priv->adev_idx); +} + +static void adev_release(struct device *dev) +{ + struct mlx4_adev *mlx4_adev = + container_of(dev, struct mlx4_adev, adev.dev); + struct mlx4_priv *priv = mlx4_priv(mlx4_adev->mdev); + int idx = mlx4_adev->idx; + + kfree(mlx4_adev); + priv->adev[idx] = NULL; +} + +static struct mlx4_adev *add_adev(struct mlx4_dev *dev, int idx) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + const char *suffix = mlx4_adev_devices[idx].suffix; + struct auxiliary_device *adev; + struct mlx4_adev *madev; + int ret; + + madev = kzalloc(sizeof(*madev), GFP_KERNEL); + if (!madev) + return ERR_PTR(-ENOMEM); + + adev = &madev->adev; + adev->id = priv->adev_idx; + adev->name = suffix; + adev->dev.parent = &dev->persist->pdev->dev; + adev->dev.release = adev_release; + madev->mdev = dev; + madev->idx = idx; + + ret = auxiliary_device_init(adev); + if (ret) { + kfree(madev); + return ERR_PTR(ret); + } + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ERR_PTR(ret); + } + return madev; +} + +static void del_adev(struct auxiliary_device *adev) +{ + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) { @@ -120,12 +203,24 @@ void mlx4_unregister_interface(struct mlx4_interface *intf) } EXPORT_SYMBOL_GPL(mlx4_unregister_interface); +int mlx4_register_auxiliary_driver(struct mlx4_adrv *madrv) +{ + return auxiliary_driver_register(&madrv->adrv); +} +EXPORT_SYMBOL_GPL(mlx4_register_auxiliary_driver); + +void mlx4_unregister_auxiliary_driver(struct mlx4_adrv *madrv) +{ + auxiliary_driver_unregister(&madrv->adrv); +} +EXPORT_SYMBOL_GPL(mlx4_unregister_auxiliary_driver); + int mlx4_do_bond(struct mlx4_dev *dev, bool enable) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_device_context *dev_ctx = NULL, *temp_dev_ctx; unsigned long flags; - int ret; + int i, ret; LIST_HEAD(bond_list); if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP)) @@ -177,6 +272,57 @@ int mlx4_do_bond(struct mlx4_dev *dev, bool enable) dev_ctx->intf->protocol, enable ? "enabled" : "disabled"); } + + mutex_lock(&intf_mutex); + + for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) { + struct mlx4_adev *madev = priv->adev[i]; + struct mlx4_adrv *madrv; + enum mlx4_protocol protocol; + + if (!madev) + continue; + + device_lock(&madev->adev.dev); + if (!madev->adev.dev.driver) { + device_unlock(&madev->adev.dev); + continue; + } + + madrv = container_of(madev->adev.dev.driver, struct mlx4_adrv, + adrv.driver); + if (!(madrv->flags & MLX4_INTFF_BONDING)) { + device_unlock(&madev->adev.dev); + continue; + } + + if (mlx4_is_mfunc(dev)) { + mlx4_dbg(dev, + "SRIOV, disabled HA mode for intf proto %d\n", + madrv->protocol); + device_unlock(&madev->adev.dev); + continue; + } + + protocol = madrv->protocol; + device_unlock(&madev->adev.dev); + + del_adev(&madev->adev); + priv->adev[i] = add_adev(dev, i); + if (IS_ERR(priv->adev[i])) { + mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i, + mlx4_adev_devices[i].suffix); + priv->adev[i] = NULL; + continue; + } + + mlx4_dbg(dev, + "Interface for protocol %d restarted with bonded mode %s\n", + protocol, enable ? "enabled" : "disabled"); + } + + mutex_unlock(&intf_mutex); + return 0; } @@ -206,10 +352,80 @@ int mlx4_unregister_event_notifier(struct mlx4_dev *dev, } EXPORT_SYMBOL(mlx4_unregister_event_notifier); +static int add_drivers(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) { + bool is_supported = false; + + if (priv->adev[i]) + continue; + + if (mlx4_adev_devices[i].is_supported) + is_supported = mlx4_adev_devices[i].is_supported(dev); + + if (!is_supported) + continue; + + priv->adev[i] = add_adev(dev, i); + if (IS_ERR(priv->adev[i])) { + mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i, + mlx4_adev_devices[i].suffix); + /* We continue to rescan drivers and leave to the caller + * to make decision if to release everything or + * continue. */ + ret = PTR_ERR(priv->adev[i]); + priv->adev[i] = NULL; + } + } + return ret; +} + +static void delete_drivers(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + bool delete_all; + int i; + + delete_all = !(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP); + + for (i = ARRAY_SIZE(mlx4_adev_devices) - 1; i >= 0; i--) { + bool is_supported = false; + + if (!priv->adev[i]) + continue; + + if (mlx4_adev_devices[i].is_supported && !delete_all) + is_supported = mlx4_adev_devices[i].is_supported(dev); + + if (is_supported) + continue; + + del_adev(&priv->adev[i]->adev); + priv->adev[i] = NULL; + } +} + +/* This function is used after mlx4_dev is reconfigured. + */ +static int rescan_drivers_locked(struct mlx4_dev *dev) +{ + lockdep_assert_held(&intf_mutex); + + delete_drivers(dev); + if (!(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP)) + return 0; + + return add_drivers(dev); +} + int mlx4_register_device(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_interface *intf; + int ret; mutex_lock(&intf_mutex); @@ -218,10 +434,18 @@ int mlx4_register_device(struct mlx4_dev *dev) list_for_each_entry(intf, &intf_list, list) mlx4_add_device(intf, priv); + ret = rescan_drivers_locked(dev); + mutex_unlock(&intf_mutex); + + if (ret) { + mlx4_unregister_device(dev); + return ret; + } + mlx4_start_catas_poll(dev); - return 0; + return ret; } void mlx4_unregister_device(struct mlx4_dev *dev) @@ -253,6 +477,8 @@ void mlx4_unregister_device(struct mlx4_dev *dev) list_del(&priv->dev_list); dev->persist->interface_state &= ~MLX4_INTERFACE_STATE_UP; + rescan_drivers_locked(dev); + mutex_unlock(&intf_mutex); } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 0ed490b99163..c4ec7377aa71 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -3429,6 +3429,10 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); + err = mlx4_adev_init(dev); + if (err) + return err; + ATOMIC_INIT_NOTIFIER_HEAD(&priv->event_nh); mutex_init(&priv->port_mutex); @@ -3455,10 +3459,11 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, err = mlx4_get_ownership(dev); if (err) { if (err < 0) - return err; + goto err_adev; else { mlx4_warn(dev, "Multiple PFs not yet supported - Skipping PF\n"); - return -EINVAL; + err = -EINVAL; + goto err_adev; } } @@ -3806,6 +3811,9 @@ err_sriov: mlx4_free_ownership(dev); kfree(dev_cap); + +err_adev: + mlx4_adev_cleanup(dev); return err; } @@ -4186,6 +4194,8 @@ static void mlx4_unload_one(struct pci_dev *pdev) mlx4_slave_destroy_special_qp_cap(dev); kfree(dev->dev_vfs); + mlx4_adev_cleanup(dev); + mlx4_clean_dev(dev); priv->pci_dev_data = pci_dev_data; priv->removed = 1; @@ -4573,6 +4583,9 @@ static int __init mlx4_init(void) { int ret; + WARN_ONCE(strcmp(MLX4_ADEV_NAME, KBUILD_MODNAME), + "mlx4_core name not in sync with kernel module name"); + if (mlx4_verify_params()) return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 73b4fdfd63f4..36de79c8d053 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -884,6 +885,8 @@ struct mlx4_priv { struct list_head dev_list; struct list_head ctx_list; spinlock_t ctx_lock; + struct mlx4_adev **adev; + int adev_idx; struct atomic_notifier_head event_nh; int pci_dev_data; @@ -1052,6 +1055,9 @@ void mlx4_catas_end(struct mlx4_dev *dev); int mlx4_crdump_init(struct mlx4_dev *dev); void mlx4_crdump_end(struct mlx4_dev *dev); int mlx4_restart_one(struct pci_dev *pdev); + +int mlx4_adev_init(struct mlx4_dev *dev); +void mlx4_adev_cleanup(struct mlx4_dev *dev); int mlx4_register_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev); void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, -- cgit From eb93ae495a73b189ab3b15d5c0e95a747cf6b6c3 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:23 +0200 Subject: mlx4: Connect the ethernet part to the auxiliary bus Use the auxiliary bus to perform device management of the ethernet part of the mlx4 driver. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 65 ++++++++++++++++++++-------- drivers/net/ethernet/mellanox/mlx4/intf.c | 13 +++++- 2 files changed, 58 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 39c9befeb638..d8f4d00ad26b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -234,9 +234,11 @@ static int mlx4_en_event(struct notifier_block *this, unsigned long event, return NOTIFY_DONE; } -static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) +static void mlx4_en_remove(struct auxiliary_device *adev) { - struct mlx4_en_dev *mdev = endev_ptr; + struct mlx4_adev *madev = container_of(adev, struct mlx4_adev, adev); + struct mlx4_dev *dev = madev->mdev; + struct mlx4_en_dev *mdev = auxiliary_get_drvdata(adev); int i; mlx4_unregister_event_notifier(dev, &mdev->mlx_nb); @@ -259,27 +261,36 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) kfree(mdev); } -static void *mlx4_en_add(struct mlx4_dev *dev) +static int mlx4_en_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) { + struct mlx4_adev *madev = container_of(adev, struct mlx4_adev, adev); + struct mlx4_dev *dev = madev->mdev; struct mlx4_en_dev *mdev; int err, i; printk_once(KERN_INFO "%s", mlx4_en_version); mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) + if (!mdev) { + err = -ENOMEM; goto err_free_res; + } - if (mlx4_pd_alloc(dev, &mdev->priv_pdn)) + err = mlx4_pd_alloc(dev, &mdev->priv_pdn); + if (err) goto err_free_dev; - if (mlx4_uar_alloc(dev, &mdev->priv_uar)) + err = mlx4_uar_alloc(dev, &mdev->priv_uar); + if (err) goto err_pd; mdev->uar_map = ioremap((phys_addr_t) mdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!mdev->uar_map) + if (!mdev->uar_map) { + err = -ENOMEM; goto err_uar; + } spin_lock_init(&mdev->uar_lock); mdev->dev = dev; @@ -291,13 +302,15 @@ static void *mlx4_en_add(struct mlx4_dev *dev) if (!mdev->LSO_support) mlx4_warn(mdev, "LSO not supported, please upgrade to later FW version to enable LSO\n"); - if (mlx4_mr_alloc(mdev->dev, mdev->priv_pdn, 0, ~0ull, - MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ, - 0, 0, &mdev->mr)) { + err = mlx4_mr_alloc(mdev->dev, mdev->priv_pdn, 0, ~0ull, + MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ, 0, 0, + &mdev->mr); + if (err) { mlx4_err(mdev, "Failed allocating memory region\n"); goto err_map; } - if (mlx4_mr_enable(mdev->dev, &mdev->mr)) { + err = mlx4_mr_enable(mdev->dev, &mdev->mr); + if (err) { mlx4_err(mdev, "Failed enabling memory region\n"); goto err_mr; } @@ -317,8 +330,10 @@ static void *mlx4_en_add(struct mlx4_dev *dev) * Note: we cannot use the shared workqueue because of deadlocks caused * by the rtnl lock */ mdev->workqueue = create_singlethread_workqueue("mlx4_en"); - if (!mdev->workqueue) + if (!mdev->workqueue) { + err = -ENOMEM; goto err_mr; + } /* At this stage all non-port specific tasks are complete: * mark the card state as up */ @@ -346,7 +361,8 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mlx4_err(mdev, "Failed to create netdev notifier\n"); } - return mdev; + auxiliary_set_drvdata(adev, mdev); + return 0; err_mr: (void) mlx4_mr_free(dev, &mdev->mr); @@ -360,12 +376,23 @@ err_pd: err_free_dev: kfree(mdev); err_free_res: - return NULL; + return err; } -static struct mlx4_interface mlx4_en_interface = { - .add = mlx4_en_add, - .remove = mlx4_en_remove, +static const struct auxiliary_device_id mlx4_en_id_table[] = { + { .name = MLX4_ADEV_NAME ".eth" }, + {}, +}; + +MODULE_DEVICE_TABLE(auxiliary, mlx4_en_id_table); + +static struct mlx4_adrv mlx4_en_adrv = { + .adrv = { + .name = "eth", + .probe = mlx4_en_probe, + .remove = mlx4_en_remove, + .id_table = mlx4_en_id_table, + }, .protocol = MLX4_PROT_ETH, }; @@ -395,12 +422,12 @@ static int __init mlx4_en_init(void) mlx4_en_verify_params(); mlx4_en_init_ptys2ethtool_map(); - return mlx4_register_interface(&mlx4_en_interface); + return mlx4_register_auxiliary_driver(&mlx4_en_adrv); } static void __exit mlx4_en_cleanup(void) { - mlx4_unregister_interface(&mlx4_en_interface); + mlx4_unregister_auxiliary_driver(&mlx4_en_adrv); } module_init(mlx4_en_init); diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 79b1eaa62ac2..95ff0ea435e2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -50,10 +50,21 @@ static LIST_HEAD(dev_list); static DEFINE_MUTEX(intf_mutex); static DEFINE_IDA(mlx4_adev_ida); +static bool is_eth_supported(struct mlx4_dev *dev) +{ + for (int port = 1; port <= dev->caps.num_ports; port++) + if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) + return true; + + return false; +} + static const struct mlx4_adev_device { const char *suffix; bool (*is_supported)(struct mlx4_dev *dev); -} mlx4_adev_devices[1] = {}; +} mlx4_adev_devices[] = { + { "eth", is_eth_supported }, +}; int mlx4_adev_init(struct mlx4_dev *dev) { -- cgit From 7d22b1cb9d84d209bdd6f43ef683d7322682d6b4 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:24 +0200 Subject: mlx4: Connect the infiniband part to the auxiliary bus Use the auxiliary bus to perform device management of the infiniband part of the mlx4 driver. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/intf.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 95ff0ea435e2..7579031786ac 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -59,11 +59,24 @@ static bool is_eth_supported(struct mlx4_dev *dev) return false; } +static bool is_ib_supported(struct mlx4_dev *dev) +{ + for (int port = 1; port <= dev->caps.num_ports; port++) + if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB) + return true; + + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE) + return true; + + return false; +} + static const struct mlx4_adev_device { const char *suffix; bool (*is_supported)(struct mlx4_dev *dev); } mlx4_adev_devices[] = { { "eth", is_eth_supported }, + { "ib", is_ib_supported }, }; int mlx4_adev_init(struct mlx4_dev *dev) -- cgit From c138cdb89a14ce00d45e77d3db18263e4b9f9465 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Mon, 21 Aug 2023 15:12:25 +0200 Subject: mlx4: Delete custom device management logic After the conversion to use the auxiliary bus, the custom device management is not needed anymore and can be deleted. Signed-off-by: Petr Pavlu Tested-by: Leon Romanovsky Reviewed-by: Leon Romanovsky Acked-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/intf.c | 125 ------------------------------ drivers/net/ethernet/mellanox/mlx4/main.c | 28 ------- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 3 - 3 files changed, 156 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 7579031786ac..a371b970ac1e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -38,15 +38,6 @@ #include "mlx4.h" -struct mlx4_device_context { - struct list_head list; - struct list_head bond_list; - struct mlx4_interface *intf; - void *context; -}; - -static LIST_HEAD(intf_list); -static LIST_HEAD(dev_list); static DEFINE_MUTEX(intf_mutex); static DEFINE_IDA(mlx4_adev_ida); @@ -156,77 +147,6 @@ static void del_adev(struct auxiliary_device *adev) auxiliary_device_uninit(adev); } -static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL); - if (!dev_ctx) - return; - - dev_ctx->intf = intf; - dev_ctx->context = intf->add(&priv->dev); - - if (dev_ctx->context) { - spin_lock_irq(&priv->ctx_lock); - list_add_tail(&dev_ctx->list, &priv->ctx_list); - spin_unlock_irq(&priv->ctx_lock); - } else - kfree(dev_ctx); - -} - -static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf == intf) { - spin_lock_irq(&priv->ctx_lock); - list_del(&dev_ctx->list); - spin_unlock_irq(&priv->ctx_lock); - - intf->remove(&priv->dev, dev_ctx->context); - kfree(dev_ctx); - return; - } -} - -int mlx4_register_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - if (!intf->add || !intf->remove) - return -EINVAL; - - mutex_lock(&intf_mutex); - - list_add_tail(&intf->list, &intf_list); - list_for_each_entry(priv, &dev_list, dev_list) { - mlx4_add_device(intf, priv); - } - - mutex_unlock(&intf_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_register_interface); - -void mlx4_unregister_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - mutex_lock(&intf_mutex); - - list_for_each_entry(priv, &dev_list, dev_list) - mlx4_remove_device(intf, priv); - - list_del(&intf->list); - - mutex_unlock(&intf_mutex); -} -EXPORT_SYMBOL_GPL(mlx4_unregister_interface); - int mlx4_register_auxiliary_driver(struct mlx4_adrv *madrv) { return auxiliary_driver_register(&madrv->adrv); @@ -242,10 +162,7 @@ EXPORT_SYMBOL_GPL(mlx4_unregister_auxiliary_driver); int mlx4_do_bond(struct mlx4_dev *dev, bool enable) { struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_device_context *dev_ctx = NULL, *temp_dev_ctx; - unsigned long flags; int i, ret; - LIST_HEAD(bond_list); if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP)) return -EOPNOTSUPP; @@ -267,36 +184,6 @@ int mlx4_do_bond(struct mlx4_dev *dev, bool enable) dev->flags &= ~MLX4_FLAG_BONDED; } - spin_lock_irqsave(&priv->ctx_lock, flags); - list_for_each_entry_safe(dev_ctx, temp_dev_ctx, &priv->ctx_list, list) { - if (!(dev_ctx->intf->flags & MLX4_INTFF_BONDING)) - continue; - - if (mlx4_is_mfunc(dev)) { - mlx4_dbg(dev, - "SRIOV, disabled HA mode for intf proto %d\n", - dev_ctx->intf->protocol); - continue; - } - - list_add_tail(&dev_ctx->bond_list, &bond_list); - list_del(&dev_ctx->list); - } - spin_unlock_irqrestore(&priv->ctx_lock, flags); - - list_for_each_entry(dev_ctx, &bond_list, bond_list) { - dev_ctx->intf->remove(dev, dev_ctx->context); - dev_ctx->context = dev_ctx->intf->add(dev); - - spin_lock_irqsave(&priv->ctx_lock, flags); - list_add_tail(&dev_ctx->list, &priv->ctx_list); - spin_unlock_irqrestore(&priv->ctx_lock, flags); - - mlx4_dbg(dev, "Interface for protocol %d restarted with bonded mode %s\n", - dev_ctx->intf->protocol, enable ? - "enabled" : "disabled"); - } - mutex_lock(&intf_mutex); for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) { @@ -447,16 +334,11 @@ static int rescan_drivers_locked(struct mlx4_dev *dev) int mlx4_register_device(struct mlx4_dev *dev) { - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; int ret; mutex_lock(&intf_mutex); dev->persist->interface_state |= MLX4_INTERFACE_STATE_UP; - list_add_tail(&priv->dev_list, &dev_list); - list_for_each_entry(intf, &intf_list, list) - mlx4_add_device(intf, priv); ret = rescan_drivers_locked(dev); @@ -474,9 +356,6 @@ int mlx4_register_device(struct mlx4_dev *dev) void mlx4_unregister_device(struct mlx4_dev *dev) { - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; - if (!(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP)) return; @@ -495,10 +374,6 @@ void mlx4_unregister_device(struct mlx4_dev *dev) } mutex_lock(&intf_mutex); - list_for_each_entry(intf, &intf_list, list) - mlx4_remove_device(intf, priv); - - list_del(&priv->dev_list); dev->persist->interface_state &= ~MLX4_INTERFACE_STATE_UP; rescan_drivers_locked(dev); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index c4ec7377aa71..2581226836b5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -1091,27 +1090,6 @@ free_mem: return err; } -static void mlx4_request_modules(struct mlx4_dev *dev) -{ - int port; - int has_ib_port = false; - int has_eth_port = false; -#define EN_DRV_NAME "mlx4_en" -#define IB_DRV_NAME "mlx4_ib" - - for (port = 1; port <= dev->caps.num_ports; port++) { - if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB) - has_ib_port = true; - else if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) - has_eth_port = true; - } - - if (has_eth_port) - request_module_nowait(EN_DRV_NAME); - if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) - request_module_nowait(IB_DRV_NAME); -} - /* * Change the port configuration of the device. * Every user of this function must hold the port mutex. @@ -1147,7 +1125,6 @@ int mlx4_change_port_types(struct mlx4_dev *dev, mlx4_err(dev, "Failed to register device\n"); goto out; } - mlx4_request_modules(dev); } out: @@ -3426,9 +3403,6 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, devl_assert_locked(devlink); dev = &priv->dev; - INIT_LIST_HEAD(&priv->ctx_list); - spin_lock_init(&priv->ctx_lock); - err = mlx4_adev_init(dev); if (err) return err; @@ -3732,8 +3706,6 @@ slave_start: if (err) goto err_port; - mlx4_request_modules(dev); - mlx4_sense_init(dev); mlx4_start_sense(dev); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 36de79c8d053..d7d856d1758a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -882,9 +882,6 @@ enum { struct mlx4_priv { struct mlx4_dev dev; - struct list_head dev_list; - struct list_head ctx_list; - spinlock_t ctx_lock; struct mlx4_adev **adev; int adev_idx; struct atomic_notifier_head event_nh; -- cgit From 45f9cb6bd9716461faf0613dcc13f181a526a9e2 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 21 Aug 2023 21:35:28 +0800 Subject: dp83640: Use list_for_each_entry() helper Convert list_for_each() to list_for_each_entry() where applicable. No functional changed. Signed-off-by: Jinjie Ruan Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ef8b14135133..2657be7cc049 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -631,7 +631,6 @@ static void recalibrate(struct dp83640_clock *clock) s64 now, diff; struct phy_txts event_ts; struct timespec64 ts; - struct list_head *this; struct dp83640_private *tmp; struct phy_device *master = clock->chosen->phydev; u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val; @@ -648,8 +647,7 @@ static void recalibrate(struct dp83640_clock *clock) /* * enable broadcast, disable status frames, enable ptp clock */ - list_for_each(this, &clock->phylist) { - tmp = list_entry(this, struct dp83640_private, list); + list_for_each_entry(tmp, &clock->phylist, list) { enable_broadcast(tmp->phydev, clock->page, 1); tmp->cfg0 = ext_read(tmp->phydev, PAGE5, PSF_CFG0); ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, 0); @@ -667,10 +665,8 @@ static void recalibrate(struct dp83640_clock *clock) evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT; evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT; - list_for_each(this, &clock->phylist) { - tmp = list_entry(this, struct dp83640_private, list); + list_for_each_entry(tmp, &clock->phylist, list) ext_write(0, tmp->phydev, PAGE5, PTP_EVNT, evnt); - } ext_write(0, master, PAGE5, PTP_EVNT, evnt); /* @@ -709,8 +705,7 @@ static void recalibrate(struct dp83640_clock *clock) event_ts.sec_hi = ext_read(master, PAGE4, PTP_EDATA); now = phy2txts(&event_ts); - list_for_each(this, &clock->phylist) { - tmp = list_entry(this, struct dp83640_private, list); + list_for_each_entry(tmp, &clock->phylist, list) { val = ext_read(tmp->phydev, PAGE4, PTP_STS); phydev_info(tmp->phydev, "slave PTP_STS 0x%04hx\n", val); val = ext_read(tmp->phydev, PAGE4, PTP_ESTS); @@ -730,10 +725,8 @@ static void recalibrate(struct dp83640_clock *clock) /* * restore status frames */ - list_for_each(this, &clock->phylist) { - tmp = list_entry(this, struct dp83640_private, list); + list_for_each_entry(tmp, &clock->phylist, list) ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, tmp->cfg0); - } ext_write(0, master, PAGE5, PSF_CFG0, cfg0); mutex_unlock(&clock->extreg_lock); -- cgit From dae64749db25be11ebfef2cf704cd451a25d3cfa Mon Sep 17 00:00:00 2001 From: Feng Liu Date: Mon, 21 Aug 2023 10:27:13 -0400 Subject: virtio_net: Introduce skb_vnet_common_hdr to avoid typecasting The virtio_net driver currently deals with different versions and types of virtio net headers, such as virtio_net_hdr_mrg_rxbuf, virtio_net_hdr_v1_hash, etc. Due to these variations, the code relies on multiple type casts to convert memory between different structures, potentially leading to bugs when there are changes in these structures. Introduces the "struct skb_vnet_common_hdr" as a unifying header structure using a union. With this approach, various virtio net header structures can be converted by accessing different members of this structure, thus eliminating the need for type casting and reducing the risk of potential bugs. For example following code: static struct sk_buff *page_to_skb(struct virtnet_info *vi, struct receive_queue *rq, struct page *page, unsigned int offset, unsigned int len, unsigned int truesize, unsigned int headroom) { [...] struct virtio_net_hdr_mrg_rxbuf *hdr; [...] hdr_len = vi->hdr_len; [...] ok: hdr = skb_vnet_hdr(skb); memcpy(hdr, hdr_p, hdr_len); [...] } When VIRTIO_NET_F_HASH_REPORT feature is enabled, hdr_len = 20 But the sizeof(*hdr) is 12, memcpy(hdr, hdr_p, hdr_len); will copy 20 bytes to the hdr, which make a potential risk of bug. And this risk can be avoided by introducing struct skb_vnet_common_hdr. Change log v1->v2 feedback from Willem de Bruijn feedback from Simon Horman 1. change to use net-next tree. 2. move skb_vnet_common_hdr inside kernel file instead of the UAPI header. v2->v3 feedback from Willem de Bruijn 1. fix typo in commit message. 2. add original struct virtio_net_hdr into union 3. remove virtio_net_hdr_mrg_rxbuf variable in receive_buf; Signed-off-by: Feng Liu Reviewed-by: Jiri Pirko Reviewed-by: Willem de Bruijn Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 494242bb9cf6..231ad91a919d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -312,6 +312,14 @@ struct padded_vnet_hdr { char padding[12]; }; +struct virtio_net_common_hdr { + union { + struct virtio_net_hdr hdr; + struct virtio_net_hdr_mrg_rxbuf mrg_hdr; + struct virtio_net_hdr_v1_hash hash_v1_hdr; + }; +}; + static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf); static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf); @@ -353,9 +361,10 @@ static int rxq2vq(int rxq) return rxq * 2; } -static inline struct virtio_net_hdr_mrg_rxbuf *skb_vnet_hdr(struct sk_buff *skb) +static inline struct virtio_net_common_hdr * +skb_vnet_common_hdr(struct sk_buff *skb) { - return (struct virtio_net_hdr_mrg_rxbuf *)skb->cb; + return (struct virtio_net_common_hdr *)skb->cb; } /* @@ -478,7 +487,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, unsigned int headroom) { struct sk_buff *skb; - struct virtio_net_hdr_mrg_rxbuf *hdr; + struct virtio_net_common_hdr *hdr; unsigned int copy, hdr_len, hdr_padded_len; struct page *page_to_free = NULL; int tailroom, shinfo_size; @@ -563,7 +572,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, give_pages(rq, page); ok: - hdr = skb_vnet_hdr(skb); + hdr = skb_vnet_common_hdr(skb); memcpy(hdr, hdr_p, hdr_len); if (page_to_free) put_page(page_to_free); @@ -975,7 +984,7 @@ static struct sk_buff *receive_small_build_skb(struct virtnet_info *vi, return NULL; buf += header_offset; - memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len); + memcpy(skb_vnet_common_hdr(skb), buf, vi->hdr_len); return skb; } @@ -1586,7 +1595,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, { struct net_device *dev = vi->dev; struct sk_buff *skb; - struct virtio_net_hdr_mrg_rxbuf *hdr; + struct virtio_net_common_hdr *hdr; if (unlikely(len < vi->hdr_len + ETH_HLEN)) { pr_debug("%s: short packet %i\n", dev->name, len); @@ -1606,9 +1615,9 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, if (unlikely(!skb)) return; - hdr = skb_vnet_hdr(skb); + hdr = skb_vnet_common_hdr(skb); if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report) - virtio_skb_set_hash((const struct virtio_net_hdr_v1_hash *)hdr, skb); + virtio_skb_set_hash(&hdr->hash_v1_hdr, skb); if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2114,7 +2123,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) if (can_push) hdr = (struct virtio_net_hdr_mrg_rxbuf *)(skb->data - hdr_len); else - hdr = skb_vnet_hdr(skb); + hdr = &skb_vnet_common_hdr(skb)->mrg_hdr; if (virtio_net_hdr_from_skb(skb, &hdr->hdr, virtio_is_little_endian(vi->vdev), false, -- cgit From 2e0c8ee2b56ffaf4ceac934d75f131a9c9becf72 Mon Sep 17 00:00:00 2001 From: Alexis Lothoré Date: Tue, 22 Aug 2023 10:41:12 +0200 Subject: net: dsa: rzn1-a5psw: remove redundant logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove debug logs in port vlan management, since there are already multiple tracepoints defined for those operations in DSA Signed-off-by: Alexis Lothoré Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/rzn1_a5psw.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 9167e83fbceb..2eda10b33f2e 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -735,10 +735,6 @@ static int a5psw_port_vlan_add(struct dsa_switch *ds, int port, u16 vid = vlan->vid; int vlan_res_id; - dev_dbg(a5psw->dev, "Add VLAN %d on port %d, %s, %s\n", - vid, port, tagged ? "tagged" : "untagged", - pvid ? "PVID" : "no PVID"); - vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); if (vlan_res_id < 0) { vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid); @@ -767,8 +763,6 @@ static int a5psw_port_vlan_del(struct dsa_switch *ds, int port, u16 vid = vlan->vid; int vlan_res_id; - dev_dbg(a5psw->dev, "Removing VLAN %d on port %d\n", vid, port); - vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); if (vlan_res_id < 0) return -EINVAL; -- cgit From e3b3a87967cef1fa157d93fd726960b1b812401d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Aug 2023 14:51:42 -0700 Subject: bnxt: use the NAPI skb allocation cache All callers of build_skb() (*) in bnxt are in NAPI context. The budget checking is somewhat convoluted because in the shared completion queue cases Rx packets are discarded by netpoll by forcing an error (E). But that happens before skb allocation. Only a call chain starting at __bnxt_poll_work() can lead to an skb allocation and it checks budget (b). * bnxt_rx_multi_page_skb * bnxt_rx_skb ` bp->rx_skb_func * bnxt_tpa_end ` bnxt_rx_pkt E bnxt_force_rx_discard E bnxt_poll_nitroa0 b __bnxt_poll_work Use napi_build_skb() to take advantage of the skb cache. In iperf tests with HW-GRO enabled it barely makes a difference but in cases where HW-GRO is not as effective (or disabled) it can give even a >10% boost (20.7Gbps -> 23.1Gbps). Signed-off-by: Jakub Kicinski Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 5d6ea2782c2f..5cc0dbe12132 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -994,7 +994,7 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, dma_addr -= bp->rx_dma_offset; dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, bp->rx_dir); - skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE); + skb = napi_build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE); if (!skb) { page_pool_recycle_direct(rxr->page_pool, page); return NULL; @@ -1069,7 +1069,7 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp, return NULL; } - skb = build_skb(data, bp->rx_buf_size); + skb = napi_build_skb(data, bp->rx_buf_size); dma_unmap_single_attrs(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size, bp->rx_dir, DMA_ATTR_WEAK_ORDERING); if (!skb) { @@ -1677,7 +1677,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, tpa_info->data_ptr = new_data + bp->rx_offset; tpa_info->mapping = new_mapping; - skb = build_skb(data, bp->rx_buf_size); + skb = napi_build_skb(data, bp->rx_buf_size); dma_unmap_single_attrs(&bp->pdev->dev, mapping, bp->rx_buf_use_size, bp->rx_dir, DMA_ATTR_WEAK_ORDERING); -- cgit From 5f48e91624b35fc85d087978feaea70a8c35be56 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:34:40 +0800 Subject: wifi: rsi: rsi_91x_coex: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_coex_ctrl_block *) or (struct rsi_common *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073440.3666204-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_coex.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_coex.c b/drivers/net/wireless/rsi/rsi_91x_coex.c index 45ac9371f262..372eaaa2b9ef 100644 --- a/drivers/net/wireless/rsi/rsi_91x_coex.c +++ b/drivers/net/wireless/rsi/rsi_91x_coex.c @@ -52,8 +52,7 @@ static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb) static void rsi_coex_scheduler_thread(struct rsi_common *common) { - struct rsi_coex_ctrl_block *coex_cb = - (struct rsi_coex_ctrl_block *)common->coex_cb; + struct rsi_coex_ctrl_block *coex_cb = common->coex_cb; u32 timeout = EVENT_WAIT_FOREVER; do { @@ -100,9 +99,8 @@ static inline int rsi_map_coex_q(u8 hal_queue) int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 hal_queue) { - struct rsi_common *common = (struct rsi_common *)priv; - struct rsi_coex_ctrl_block *coex_cb = - (struct rsi_coex_ctrl_block *)common->coex_cb; + struct rsi_common *common = priv; + struct rsi_coex_ctrl_block *coex_cb = common->coex_cb; struct skb_info *tx_params = NULL; enum rsi_coex_queues coex_q; int status; @@ -168,8 +166,7 @@ int rsi_coex_attach(struct rsi_common *common) void rsi_coex_detach(struct rsi_common *common) { - struct rsi_coex_ctrl_block *coex_cb = - (struct rsi_coex_ctrl_block *)common->coex_cb; + struct rsi_coex_ctrl_block *coex_cb = common->coex_cb; int cnt; rsi_kill_thread(&coex_cb->coex_tx_thread); -- cgit From 148924e537df01598870c7c55092e61859df292c Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:34:55 +0800 Subject: wifi: rsi: rsi_91x_debugfs: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_91x_sdiodev *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073455.3666306-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_debugfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c index bf22fd948276..c528e6ca2c8d 100644 --- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c +++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c @@ -28,8 +28,7 @@ static int rsi_sdio_stats_read(struct seq_file *seq, void *data) { struct rsi_common *common = seq->private; struct rsi_hw *adapter = common->priv; - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; seq_printf(seq, "total_sdio_interrupts: %d\n", dev->rx_info.sdio_int_counter); -- cgit From 52424e0c49d614cbeec3a7a9f5e0fcfe123a5601 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:07 +0800 Subject: wifi: rsi: rsi_91x_hal: Remove unnecessary conversions No need cast (struct rsi_hw *) to (struct rsi_hw *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073507.3666471-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_hal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index d4489b943873..2cebe562a1f4 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -424,7 +424,7 @@ out: int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb) { - struct rsi_hw *adapter = (struct rsi_hw *)common->priv; + struct rsi_hw *adapter = common->priv; struct rsi_data_desc *bcn_frm; struct ieee80211_hw *hw = common->priv->hw; struct ieee80211_conf *conf = &hw->conf; -- cgit From 6d5d2dbd00bfc320d642f7c3911dee4f43db5fea Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:17 +0800 Subject: wifi: rsi: rsi_91x_mac80211: Remove unnecessary conversions No need cast (struct rsi_hw *) to (struct rsi_hw *), or cast (struct rsi_common *) to (struct rsi_common *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073517.3666559-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index bc1f038d1655..05890536e353 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1763,8 +1763,8 @@ static int rsi_mac80211_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *chan, int duration, enum ieee80211_roc_type type) { - struct rsi_hw *adapter = (struct rsi_hw *)hw->priv; - struct rsi_common *common = (struct rsi_common *)adapter->priv; + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; int status = 0; rsi_dbg(INFO_ZONE, "***** Remain on channel *****\n"); -- cgit From db2be1a01fc540ba12135b8ae9ec1acc0634dfa8 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:29 +0800 Subject: wifi: rsi: rsi_91x_main: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_common *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073529.3666653-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c index f9f004446b07..2112d8d277a9 100644 --- a/drivers/net/wireless/rsi/rsi_91x_main.c +++ b/drivers/net/wireless/rsi/rsi_91x_main.c @@ -270,14 +270,14 @@ static void rsi_tx_scheduler_thread(struct rsi_common *common) #ifdef CONFIG_RSI_COEX enum rsi_host_intf rsi_get_host_intf(void *priv) { - struct rsi_common *common = (struct rsi_common *)priv; + struct rsi_common *common = priv; return common->priv->rsi_host_intf; } void rsi_set_bt_context(void *priv, void *bt_context) { - struct rsi_common *common = (struct rsi_common *)priv; + struct rsi_common *common = priv; common->bt_adapter = bt_context; } -- cgit From f9bf6e729f4ebcd81729ee96ecbc465796318ebd Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:39 +0800 Subject: wifi: rsi: rsi_91x_sdio: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_91x_sdiodev *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073539.3666735-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 39 ++++++++++++--------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 1911fef3bbad..8e7b757475d2 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -144,8 +144,7 @@ static int rsi_issue_sdiocommand(struct sdio_func *func, static void rsi_handle_interrupt(struct sdio_func *function) { struct rsi_hw *adapter = sdio_get_drvdata(function); - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED) return; @@ -337,8 +336,7 @@ static void rsi_reset_card(struct sdio_func *pfunction) */ static void rsi_setclock(struct rsi_hw *adapter, u32 freq) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; struct mmc_host *host = dev->pfunction->card->host; u32 clock; @@ -358,8 +356,7 @@ static void rsi_setclock(struct rsi_hw *adapter, u32 freq) */ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; int status; rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__); @@ -380,8 +377,7 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length) */ static int rsi_setupcard(struct rsi_hw *adapter) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; int status = 0; rsi_setclock(adapter, 50000); @@ -407,8 +403,7 @@ int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u8 fun_num = 0; int status; @@ -441,8 +436,7 @@ int rsi_sdio_write_register(struct rsi_hw *adapter, u32 addr, u8 *data) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; int status = 0; if (likely(dev->sdio_irq_task != current)) @@ -495,8 +489,7 @@ static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter, u8 *data, u16 count) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u32 status; if (likely(dev->sdio_irq_task != current)) @@ -527,8 +520,7 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u8 *data, u16 count) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; int status; if (dev->write_fail > 1) { @@ -762,8 +754,7 @@ static int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter, u8 *pkt, u32 len) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u32 block_size = dev->tx_blk_size; u32 num_blocks, address, length; u32 queueno; @@ -1045,7 +1036,7 @@ static int rsi_probe(struct sdio_func *pfunction, goto fail_free_adapter; } - sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; + sdev = adapter->rsi_dev; rsi_init_event(&sdev->rx_thread.event); status = rsi_create_kthread(adapter->priv, &sdev->rx_thread, rsi_sdio_rx_thread, "SDIO-RX-Thread"); @@ -1221,7 +1212,7 @@ static void rsi_disconnect(struct sdio_func *pfunction) if (!adapter) return; - dev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; + dev = adapter->rsi_dev; rsi_kill_thread(&dev->rx_thread); sdio_claim_host(pfunction); @@ -1255,8 +1246,7 @@ static void rsi_disconnect(struct sdio_func *pfunction) #ifdef CONFIG_PM static int rsi_set_sdio_pm_caps(struct rsi_hw *adapter) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; struct sdio_func *func = dev->pfunction; int ret; @@ -1407,7 +1397,7 @@ static int rsi_freeze(struct device *dev) return -ENODEV; } common = adapter->priv; - sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; + sdev = adapter->rsi_dev; if ((common->wow_flags & RSI_WOW_ENABLED) && (common->wow_flags & RSI_WOW_NO_CONNECTION)) @@ -1457,8 +1447,7 @@ static void rsi_shutdown(struct device *dev) { struct sdio_func *pfunction = dev_to_sdio_func(dev); struct rsi_hw *adapter = sdio_get_drvdata(pfunction); - struct rsi_91x_sdiodev *sdev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *sdev = adapter->rsi_dev; struct ieee80211_hw *hw = adapter->hw; rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); -- cgit From 361beddbfb7cfa2f280faca5d9df43eace381db6 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:50 +0800 Subject: wifi: rsi: rsi_91x_sdio_ops: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_91x_sdiodev *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073550.3666829-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c index b2b47a0abcbf..597b238e2294 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c @@ -88,8 +88,7 @@ void rsi_sdio_rx_thread(struct rsi_common *common) static int rsi_process_pkt(struct rsi_common *common) { struct rsi_hw *adapter = common->priv; - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u8 num_blks = 0; u32 rcv_pkt_len = 0; int status = 0; @@ -147,8 +146,7 @@ static int rsi_process_pkt(struct rsi_common *common) */ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u8 function = 0; u8 byte; int status = 0; @@ -233,8 +231,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) static void rsi_rx_handler(struct rsi_hw *adapter) { struct rsi_common *common = adapter->priv; - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; int status; u8 isr_status = 0; u8 fw_status = 0; @@ -339,8 +336,7 @@ static void rsi_rx_handler(struct rsi_hw *adapter) int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num) { struct rsi_common *common = adapter->priv; - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; u8 buf_status = 0; int status = 0; static int counter = 4; @@ -409,8 +405,7 @@ out: */ int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter) { - struct rsi_91x_sdiodev *dev = - (struct rsi_91x_sdiodev *)adapter->rsi_dev; + struct rsi_91x_sdiodev *dev = adapter->rsi_dev; /* Once buffer full is seen, event timeout to occur every 2 msecs */ if (dev->rx_info.buffer_full) -- cgit From f543235c394837275366669a3b769d17d5015d10 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:35:58 +0800 Subject: wifi: rsi: rsi_91x_usb: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_91x_usbdev *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073558.3666936-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_usb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index 66fe386ec9cc..10a465686439 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -43,7 +43,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter, u16 len, u8 endpoint) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; int status; u8 *seg = dev->tx_buffer; int transfer; @@ -91,7 +91,7 @@ static int rsi_write_multiple(struct rsi_hw *adapter, if (endpoint == 0) return -EINVAL; - dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + dev = adapter->rsi_dev; if (dev->write_fail) return -ENETDOWN; @@ -109,7 +109,7 @@ static int rsi_write_multiple(struct rsi_hw *adapter, static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface, struct rsi_hw *adapter) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; __le16 buffer_size; @@ -306,7 +306,7 @@ out: static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1]; struct urb *urb = rx_cb->rx_urb; @@ -323,7 +323,7 @@ static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num) */ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t mem_flags) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1]; struct urb *urb = rx_cb->rx_urb; int status; @@ -362,7 +362,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t mem_flags) static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr, u8 *data, u16 count) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; u8 *buf; u16 transfer; int status; @@ -412,7 +412,7 @@ static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr, static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr, u8 *data, u16 count) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; u8 *buf; u16 transfer; int status = 0; @@ -559,7 +559,7 @@ static struct rsi_host_intf_ops usb_host_intf_ops = { */ static void rsi_deinit_usb_interface(struct rsi_hw *adapter) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; rsi_kill_thread(&dev->rx_thread); @@ -572,7 +572,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter) static int rsi_usb_init_rx(struct rsi_hw *adapter) { - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; struct rx_usb_ctrl_block *rx_cb; u8 idx, num_rx_cb; @@ -822,7 +822,7 @@ static int rsi_probe(struct usb_interface *pfunction, goto err1; } - dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + dev = adapter->rsi_dev; status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2); if (status < 0) -- cgit From 7d8473c799be80a89ab8b1f26f021e5cf0d4aa20 Mon Sep 17 00:00:00 2001 From: Wu Yunchuan Date: Thu, 3 Aug 2023 15:36:06 +0800 Subject: wifi: rsi: rsi_91x_usb_ops: Remove unnecessary (void*) conversions No need cast (void*) to (struct rsi_91x_usbdev *). Signed-off-by: Wu Yunchuan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230803073606.3667062-1-yunchuan@nfschina.com --- drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c index 5130b0e72adc..25c2b232394a 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c @@ -28,7 +28,7 @@ void rsi_usb_rx_thread(struct rsi_common *common) { struct rsi_hw *adapter = common->priv; - struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; + struct rsi_91x_usbdev *dev = adapter->rsi_dev; int status; struct sk_buff *skb; -- cgit From eaa8023e9bb30926b154af72be0cadbebfc8e878 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Thu, 10 Aug 2023 19:49:39 +0800 Subject: wifi: wfx: Use devm_kmemdup to replace devm_kmalloc + memcpy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the helper function devm_kmemdup() rather than duplicating its implementation, which helps to enhance code readability. Signed-off-by: Li Zetao Reviewed-by: Jérôme Pouiller Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230810114939.2104013-1-lizetao1@huawei.com --- drivers/net/wireless/silabs/wfx/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c index 0b50f7058bbb..ede822d771aa 100644 --- a/drivers/net/wireless/silabs/wfx/main.c +++ b/drivers/net/wireless/silabs/wfx/main.c @@ -293,13 +293,12 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_da hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; hw->wiphy->n_iface_combinations = ARRAY_SIZE(wfx_iface_combinations); hw->wiphy->iface_combinations = wfx_iface_combinations; - hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmalloc(dev, sizeof(wfx_band_2ghz), GFP_KERNEL); + /* FIXME: also copy wfx_rates and wfx_2ghz_chantable */ + hw->wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(dev, &wfx_band_2ghz, + sizeof(wfx_band_2ghz), GFP_KERNEL); if (!hw->wiphy->bands[NL80211_BAND_2GHZ]) goto err; - /* FIXME: also copy wfx_rates and wfx_2ghz_chantable */ - memcpy(hw->wiphy->bands[NL80211_BAND_2GHZ], &wfx_band_2ghz, sizeof(wfx_band_2ghz)); - wdev = hw->priv; wdev->hw = hw; wdev->dev = dev; -- cgit From 821b5192c955144bd2f0aeea6cd153e1aedd16e1 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Fri, 11 Aug 2023 14:34:54 +0800 Subject: wifi: rt2x00: limit MT7620 TX power based on eeprom calibration In the vendor driver, the current channel power is queried from EEPROM_TXPOWER_BG1 and EEPROM_TXPOWER_BG2. And then the mixed value will be written into the low half-word of the TX_ALC_CFG_0 register. The high half-word of the TX_ALC_CFG_0 is a fixed value 0x2f2f. We can't get the accurate TX power. Based on my tests and the new MediaTek mt76 driver source code, the real TX power is approximately equal to channel_power + (max) rate_power. Usually max rate_power is the gain of the OFDM 6M rate, which can be readed from the offset EEPROM_TXPOWER_BYRATE +1. Based on these eeprom values, this patch adds basic TX power control for the MT7620 and limits its maximum TX power. This can avoid the link speed decrease caused by chip overheating. rt2800_config_alc() function has also been renamed to rt2800_config_alc_rt6352() because it's only used by RT6352 (MT7620). Notice: It's still need some work to sync the max channel power to the user interface. This part is missing from the rt2x00 driver framework. If we set the power exceed the calibration value, it won't take effect. Signed-off-by: Shiji Yang Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/TYAP286MB03159090ED14044215E59FD6BC10A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 57 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index ab374c50c35d..e65cc00fa17c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3865,28 +3865,51 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev, } } -static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev, - struct ieee80211_channel *chan, - int power_level) { - u16 eeprom, target_power, max_power; +static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev, + struct ieee80211_channel *chan, + int power_level) +{ + int cur_channel = rt2x00dev->rf_channel; + u16 eeprom, chan_power, rate_power, target_power; + u16 tx_power[2]; + s8 *power_group[2]; u32 mac_sys_ctrl; - u32 reg; + u32 cnt, reg; u8 bbp; - /* hardware unit is 0.5dBm, limited to 23.5dBm */ - power_level *= 2; - if (power_level > 0x2f) - power_level = 0x2f; + if (WARN_ON(cur_channel < 1 || cur_channel > 14)) + return; + + /* get per chain power, 2 chains in total, unit is 0.5dBm */ + power_level = (power_level - 3) * 2; - max_power = chan->max_power * 2; - if (max_power > 0x2f) - max_power = 0x2f; + /* We can't get the accurate TX power. Based on some tests, the real + * TX power is approximately equal to channel_power + (max)rate_power. + * Usually max rate_power is the gain of the OFDM 6M rate. The antenna + * gain and externel PA gain are not included as we are unable to + * obtain these values. + */ + rate_power = rt2800_eeprom_read_from_array(rt2x00dev, + EEPROM_TXPOWER_BYRATE, 1); + rate_power &= 0x3f; + power_level -= rate_power; + if (power_level < 1) + power_level = 1; + + power_group[0] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + power_group[1] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + for (cnt = 0; cnt < 2; cnt++) { + chan_power = power_group[cnt][cur_channel - 1]; + if (chan_power >= 0x20 || chan_power == 0) + chan_power = 0x10; + tx_power[cnt] = power_level < chan_power ? power_level : chan_power; + } reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0); - rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, power_level); - rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, power_level); - rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, max_power); - rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, max_power); + rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, tx_power[0]); + rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, tx_power[1]); + rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, 0x2f); + rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, 0x2f); eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) { @@ -5268,7 +5291,7 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t); rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg); - rt2800_config_alc(rt2x00dev, chan, power_level); + rt2800_config_alc_rt6352(rt2x00dev, chan, power_level); /* TODO: temperature compensation code! */ } -- cgit From 35a7a1ce7c7d61664ee54f5239a1f120ab95a87e Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 14 Aug 2023 12:49:57 +0300 Subject: wifi: mwifiex: avoid possible NULL skb pointer dereference In 'mwifiex_handle_uap_rx_forward()', always check the value returned by 'skb_copy()' to avoid potential NULL pointer dereference in 'mwifiex_uap_queue_bridged_pkt()', and drop original skb in case of copying failure. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 838e4f449297 ("mwifiex: improve uAP RX handling") Acked-by: Brian Norris Signed-off-by: Dmitry Antipov Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230814095041.16416-1-dmantipov@yandex.ru --- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index b9866f2e2644..318bd4ed8399 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -253,7 +253,15 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, if (is_multicast_ether_addr(ra)) { skb_uap = skb_copy(skb, GFP_ATOMIC); - mwifiex_uap_queue_bridged_pkt(priv, skb_uap); + if (likely(skb_uap)) { + mwifiex_uap_queue_bridged_pkt(priv, skb_uap); + } else { + mwifiex_dbg(adapter, ERROR, + "failed to copy skb for uAP\n"); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return -1; + } } else { if (mwifiex_get_sta_entry(priv, ra)) { /* Requeue Intra-BSS packet */ -- cgit From c4125bf88341056a2051c6c083a7f69661733fc6 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Sat, 19 Aug 2023 18:21:00 +0800 Subject: wifi: wilc1000: Remove unused declarations Commit 8399918f3056 ("staging: wilc1000: use RCU list to maintain vif interfaces list") removed wilc_get_interface() but not its declaration. Commit 9bc061e88054 ("staging: wilc1000: added support to dynamically add/remove interfaces") declared but never implemented wilc_cfg_alloc() and wilc_netdev_interface(). Signed-off-by: Yue Haibing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230819102100.13720-1-yuehaibing@huawei.com --- drivers/net/wireless/microchip/wilc1000/cfg80211.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.h b/drivers/net/wireless/microchip/wilc1000/cfg80211.h index 37b294cb3b37..8c65951cfaf9 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.h +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.h @@ -8,15 +8,12 @@ #define WILC_CFG80211_H #include "netdev.h" -struct wiphy *wilc_cfg_alloc(void); int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, const struct wilc_hif_func *ops); struct wilc *wilc_create_wiphy(struct device *dev); void wilc_deinit_host_int(struct net_device *net); int wilc_init_host_int(struct net_device *net); void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); -struct wilc_vif *wilc_netdev_interface(struct wilc *wl, const char *name, - enum nl80211_iftype type); void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked); struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, const char *name, @@ -24,7 +21,6 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy, struct wireless_dev *wdev, struct mgmt_frame_regs *upd); -struct wilc_vif *wilc_get_interface(struct wilc *wl); struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl); void wlan_deinit_locks(struct wilc *wilc); #endif -- cgit From 400ece6c7f346b0a30867bd00b03b5b2563d4357 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Aug 2023 16:42:24 +0300 Subject: wifi: ath11k: Don't drop tx_status when peer cannot be found When a station idles for a long time, hostapd will try to send a QoS Null frame to the station as "poll". NL80211_CMD_PROBE_CLIENT is used for this purpose. And the skb will be added to ack_status_frame - waiting for a completion via ieee80211_report_ack_skb(). But when the peer was already removed before the tx_complete arrives, the peer will be missing. And when using dev_kfree_skb_any (instead of going through mac80211), the entry will stay inside ack_status_frames. This IDR will therefore run full after 8K request were generated for such clients. At this point, the access point will then just stall and not allow any new clients because idr_alloc() for ack_status_frame will fail. ieee80211_free_txskb() on the other hand will (when required) call ieee80211_report_ack_skb() and make sure that (when required) remove the entry from the ack_status_frame. Tested-on: IPQ6018 hw1.0 WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 Fixes: 6257c702264c ("wifi: ath11k: fix tx status reporting in encap offload mode") Fixes: 94739d45c388 ("ath11k: switch to using ieee80211_tx_status_ext()") Cc: stable@vger.kernel.org Signed-off-by: Sven Eckelmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802-ath11k-ack_status_leak-v2-1-c0af729d6229@narfation.org --- drivers/net/wireless/ath/ath11k/dp_tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index a34833de7c67..27c976f52c7a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -369,7 +369,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab, "dp_tx: failed to find the peer with peer_id %d\n", ts->peer_id); spin_unlock_bh(&ab->base_lock); - dev_kfree_skb_any(msdu); + ieee80211_free_txskb(ar->hw, msdu); return; } spin_unlock_bh(&ab->base_lock); @@ -624,7 +624,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, "dp_tx: failed to find the peer with peer_id %d\n", ts->peer_id); spin_unlock_bh(&ab->base_lock); - dev_kfree_skb_any(msdu); + ieee80211_free_txskb(ar->hw, msdu); return; } arsta = (struct ath11k_sta *)peer->sta->drv_priv; -- cgit From 29d15589f084d71a4ea8c544039c5839db0236e2 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 22 Aug 2023 16:42:24 +0300 Subject: wifi: ath11k: Cleanup mac80211 references on failure during tx_complete When a function is using functions from mac80211 to free an skb then it should do it consistently and not switch to the generic dev_kfree_skb_any (or similar functions). Otherwise (like in the error handlers), mac80211 will will not be aware of the freed skb and thus not clean up related information in its internal data structures. Not doing so lead in the past to filled up structure which then prevented new clients to connect. Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Fixes: 6257c702264c ("wifi: ath11k: fix tx status reporting in encap offload mode") Cc: stable@vger.kernel.org Signed-off-by: Sven Eckelmann Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230802-ath11k-ack_status_leak-v2-2-c0af729d6229@narfation.org --- drivers/net/wireless/ath/ath11k/dp_tx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 27c976f52c7a..b85a4a03b37a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -344,7 +344,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab, dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); if (!skb_cb->vif) { - dev_kfree_skb_any(msdu); + ieee80211_free_txskb(ar->hw, msdu); return; } @@ -566,12 +566,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { - dev_kfree_skb_any(msdu); + ieee80211_free_txskb(ar->hw, msdu); return; } if (unlikely(!skb_cb->vif)) { - dev_kfree_skb_any(msdu); + ieee80211_free_txskb(ar->hw, msdu); return; } -- cgit From 9476cda44c136089f14f8951ae5197d63e91735c Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 21 Aug 2023 07:13:36 -0700 Subject: wifi: ath11k: Consistently use ath11k_vif_to_arvif() Helper function ath11k_vif_to_arvif() exists to retrieve a struct ath11k_vif from a struct ieee80211_vif. However, in multiple places this logic is open-coded with inline typecasting. Since the typecasting prevents the compiler from type-checking the source and destination, update the driver to consistently use the helper function. No functional changes, compile tested only. Signed-off-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 64 +++++++++++++++--------------- drivers/net/wireless/ath/ath11k/testmode.c | 2 +- 2 files changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 2aadf2c387b6..c071bf5841af 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -566,7 +566,7 @@ static void ath11k_get_arvif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct ath11k_vif_iter *arvif_iter = data; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); if (arvif->vdev_id == arvif_iter->vdev_id) arvif_iter->arvif = arvif; @@ -1464,7 +1464,7 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif) u32 params = 0; u8 i = 0; - tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + tx_arvif = ath11k_vif_to_arvif(arvif->vif->mbssid_tx_vif); beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, tx_arvif->vif, 0); @@ -1520,8 +1520,8 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif) struct sk_buff *bcn; int ret; - if (arvif->vif->mbssid_tx_vif) { - tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + if (vif->mbssid_tx_vif) { + tx_arvif = ath11k_vif_to_arvif(vif->mbssid_tx_vif); if (tx_arvif != arvif) { ar = tx_arvif->ar; ab = ar->ab; @@ -1562,7 +1562,7 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) * non-transmitting interfaces, and results in a crash if sent. */ if (vif->mbssid_tx_vif && - arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) + arvif != ath11k_vif_to_arvif(vif->mbssid_tx_vif) && arvif->is_up) return 0; if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif) @@ -1626,7 +1626,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, ether_addr_copy(arvif->bssid, info->bssid); if (arvif->vif->mbssid_tx_vif) - tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv; + tx_arvif = ath11k_vif_to_arvif(arvif->vif->mbssid_tx_vif); ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, arvif->bssid, @@ -1649,7 +1649,7 @@ static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac, { struct sk_buff *skb = data; struct ieee80211_mgmt *mgmt = (void *)skb->data; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); if (vif->type != NL80211_IFTYPE_STATION) return; @@ -1672,7 +1672,7 @@ static void ath11k_mac_handle_beacon_miss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { u32 *vdev_id = data; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k *ar = arvif->ar; struct ieee80211_hw *hw = ar->hw; @@ -1718,7 +1718,7 @@ static void ath11k_peer_assoc_h_basic(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); u32 aid; lockdep_assert_held(&ar->conf_mutex); @@ -1746,7 +1746,7 @@ static void ath11k_peer_assoc_h_crypto(struct ath11k *ar, struct ieee80211_bss_conf *info = &vif->bss_conf; struct cfg80211_chan_def def; struct cfg80211_bss *bss; - struct ath11k_vif *arvif = (struct ath11k_vif *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); const u8 *rsnie = NULL; const u8 *wpaie = NULL; @@ -1804,7 +1804,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; struct cfg80211_chan_def def; const struct ieee80211_supported_band *sband; @@ -1867,7 +1867,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar, struct peer_assoc_params *arg) { const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -2064,7 +2064,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, struct peer_assoc_params *arg) { const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; u16 *vht_mcs_mask; @@ -2261,7 +2261,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct cfg80211_chan_def def; const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; enum nl80211_band band; @@ -2584,7 +2584,7 @@ static void ath11k_peer_assoc_h_qos(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); switch (arvif->vdev_type) { case WMI_VDEV_TYPE_AP: @@ -2747,7 +2747,7 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -2933,7 +2933,7 @@ static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta_he_cap *he_cap) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ieee80211_he_cap_elem he_cap_elem = {0}; struct ieee80211_sta_he_cap *cap_band = NULL; struct cfg80211_chan_def def; @@ -2995,7 +2995,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf) { struct ath11k *ar = hw->priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct peer_assoc_params peer_arg; struct ieee80211_sta *ap_sta; struct ath11k_peer *peer; @@ -3111,7 +3111,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath11k *ar = hw->priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); int ret; lockdep_assert_held(&ar->conf_mutex); @@ -3160,7 +3160,7 @@ static void ath11k_recalculate_mgmt_rate(struct ath11k *ar, struct ieee80211_vif *vif, struct cfg80211_chan_def *def) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); const struct ieee80211_supported_band *sband; u8 basic_rate_idx; int hw_rate_code; @@ -4632,7 +4632,7 @@ static int ath11k_station_disassoc(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); int ret = 0; lockdep_assert_held(&ar->conf_mutex); @@ -5160,7 +5160,7 @@ static int ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath11k *ar = hw->priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); int ret = 0; s16 txpwr; @@ -5210,7 +5210,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k_peer *peer; u32 bw, smps; @@ -5337,7 +5337,7 @@ static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct ath11k *ar = hw->priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct wmi_wmm_params_arg *p = NULL; int ret; @@ -6455,7 +6455,7 @@ static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif, return 0; } - tx_arvif = (void *)tx_vif->drv_priv; + tx_arvif = ath11k_vif_to_arvif(tx_vif); if (arvif->vif->bss_conf.nontransmitted) { if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) @@ -7408,7 +7408,7 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, /* TODO: Update ar->rx_channel */ for (i = 0; i < n_vifs; i++) { - arvif = (void *)vifs[i].vif->drv_priv; + arvif = ath11k_vif_to_arvif(vifs[i].vif); if (WARN_ON(!arvif->is_started)) continue; @@ -7450,7 +7450,7 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, mbssid_tx_vif = arvif->vif->mbssid_tx_vif; if (mbssid_tx_vif) - tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv; + tx_arvif = ath11k_vif_to_arvif(mbssid_tx_vif); ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, arvif->bssid, @@ -7546,7 +7546,7 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); int ret; if (WARN_ON(arvif->is_started)) @@ -7596,7 +7596,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); int ret; struct peer_create_params param; @@ -7686,7 +7686,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k_peer *peer; int ret; @@ -8307,7 +8307,7 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct cfg80211_chan_def def; struct ath11k_pdev_cap *cap; struct ath11k *ar = arvif->ar; @@ -8904,7 +8904,7 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw, enum ieee80211_roc_type type) { struct ath11k *ar = hw->priv; - struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct scan_req_params arg; int ret; u32 scan_time_msec; diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c index 8fc5cddb28bd..43bb23265d34 100644 --- a/drivers/net/wireless/ath/ath11k/testmode.c +++ b/drivers/net/wireless/ath/ath11k/testmode.c @@ -350,7 +350,7 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[], if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM && (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { if (vif) { - arvif = (struct ath11k_vif *)vif->drv_priv; + arvif = ath11k_vif_to_arvif(vif); *ptr = arvif->vdev_id; } else { ret = -EINVAL; -- cgit From 3ced39049d4d87231c3ddabfb335fe78a99591c2 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 22 Aug 2023 07:50:48 -0700 Subject: wifi: ath10k: Fix a few spelling errors Fix a few issues flagged by 'codespell'. Signed-off-by: Jeff Johnson Acked-by: Randy Dunlap Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822-ath_spelling-v1-1-8e2698759564@quicinc.com --- drivers/net/wireless/ath/ath10k/htt.h | 4 ++-- drivers/net/wireless/ath/ath10k/pci.c | 2 +- drivers/net/wireless/ath/ath10k/sdio.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index e0c9f45e7476..7b24297146e7 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -69,7 +69,7 @@ struct htt_ver_req { * The HTT tx descriptor is defined in two manners: by a struct with * bitfields, and by a series of [dword offset, bit mask, bit shift] * definitions. - * The target should use the struct def, for simplicitly and clarity, + * The target should use the struct def, for simplicity and clarity, * but the host shall use the bit-mast + bit-shift defs, to be endian- * neutral. Specifically, the host shall use the get/set macros built * around the mask + shift defs. @@ -2086,7 +2086,7 @@ static inline bool ath10k_htt_rx_proc_rx_frag_ind(struct ath10k_htt *htt, * for correctly accessing rx descriptor data. */ -/* base struct used for abstracting the rx descritor representation */ +/* base struct used for abstracting the rx descriptor representation */ struct htt_rx_desc { union { /* This field is filled on the host using the msdu buffer diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index a7f44f6335fb..57177890a463 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1636,7 +1636,7 @@ static int ath10k_pci_dump_memory_generic(struct ath10k *ar, buf, current_region->len); - /* No individiual memory sections defined so we can + /* No individual memory sections defined so we can * copy the entire memory region. */ ret = ath10k_pci_diag_read_mem(ar, diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 79e09c7a82b3..56fbcfb80bf8 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -2389,7 +2389,7 @@ static int ath10k_sdio_dump_memory_generic(struct ath10k *ar, buf, current_region->len); - /* No individiual memory sections defined so we can + /* No individual memory sections defined so we can * copy the entire memory region. */ if (fast_dump) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 6d04a66fe5e0..b112e8826093 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3854,9 +3854,9 @@ enum wmi_pdev_param { * retransmitting frames. */ WMI_PDEV_PARAM_DYNAMIC_BW, - /* Non aggregrate/ 11g sw retry threshold.0-disable */ + /* Non aggregate/ 11g sw retry threshold.0-disable */ WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, - /* aggregrate sw retry threshold. 0-disable*/ + /* aggregate sw retry threshold. 0-disable*/ WMI_PDEV_PARAM_AGG_SW_RETRY_TH, /* Station kickout threshold (non of consecutive failures).0-disable */ WMI_PDEV_PARAM_STA_KICKOUT_TH, @@ -3953,9 +3953,9 @@ enum wmi_10x_pdev_param { WMI_10X_PDEV_PARAM_PROTECTION_MODE, /* Dynamic bandwidth 0: disable 1: enable */ WMI_10X_PDEV_PARAM_DYNAMIC_BW, - /* Non aggregrate/ 11g sw retry threshold.0-disable */ + /* Non aggregate/ 11g sw retry threshold.0-disable */ WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, - /* aggregrate sw retry threshold. 0-disable*/ + /* aggregate sw retry threshold. 0-disable*/ WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, /* Station kickout threshold (non of consecutive failures).0-disable */ WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, -- cgit From d68a283bfc39aeed2a51c67804e014bf4b35c7e1 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 22 Aug 2023 07:50:49 -0700 Subject: wifi: ath11k: Fix a few spelling errors Fix a few issues flagged by 'codespell'. Signed-off-by: Jeff Johnson Acked-by: Randy Dunlap Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822-ath_spelling-v1-2-8e2698759564@quicinc.com --- drivers/net/wireless/ath/ath11k/dp.h | 2 +- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- drivers/net/wireless/ath/ath11k/dp_tx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index d04f78ab6b37..15815af453b2 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -635,7 +635,7 @@ enum htt_ppdu_stats_tag_type { * b'24 - status_swap: 1 is to swap status TLV * b'25 - pkt_swap: 1 is to swap packet TLV * b'26:31 - rsvd1: reserved for future use - * dword1 - b'0:16 - ring_buffer_size: size of bufferes referenced by rx ring, + * dword1 - b'0:16 - ring_buffer_size: size of buffers referenced by rx ring, * in byte units. * Valid only for HW_TO_SW_RING and SW_TO_HW_RING * - b'16:31 - rsvd2: Reserved for future use diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 1e488eed282b..62bc98852f0f 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -3423,7 +3423,7 @@ static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_ti ath11k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie, ab->hw_params.hal_params->rx_buf_rbm); - /* Fill mpdu details into reo entrace ring */ + /* Fill mpdu details into reo entrance ring */ srng = &ab->hal.srng_list[ab->dp.reo_reinject_ring.ring_id]; spin_lock_bh(&srng->lock); diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index b85a4a03b37a..0dda76f7a4b5 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -238,7 +238,7 @@ tcl_ring_sel: spin_unlock_bh(&tcl_ring->lock); ret = -ENOMEM; - /* Checking for available tcl descritors in another ring in + /* Checking for available tcl descriptors in another ring in * case of failure due to full tcl ring now, is better than * checking this ring earlier for each pkt tx. * Restart ring selection if some rings are not checked yet. -- cgit From 4f1dbb4904c3d06b0f0d5f2dda8ccff839110726 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 22 Aug 2023 07:50:50 -0700 Subject: wifi: ath12k: Fix a few spelling errors Fix a few issues flagged by 'codespell'. Signed-off-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822-ath_spelling-v1-3-8e2698759564@quicinc.com --- drivers/net/wireless/ath/ath12k/dp.h | 2 +- drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +- drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +- drivers/net/wireless/ath/ath12k/mac.c | 2 +- drivers/net/wireless/ath/ath12k/rx_desc.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index 7c5dafce5a68..6e7b7281d549 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -712,7 +712,7 @@ enum htt_stats_internal_ppdu_frametype { * b'24 - status_swap: 1 is to swap status TLV * b'25 - pkt_swap: 1 is to swap packet TLV * b'26:31 - rsvd1: reserved for future use - * dword1 - b'0:16 - ring_buffer_size: size of bufferes referenced by rx ring, + * dword1 - b'0:16 - ring_buffer_size: size of buffers referenced by rx ring, * in byte units. * Valid only for HW_TO_SW_RING and SW_TO_HW_RING * - b'16:31 - rsvd2: Reserved for future use diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 67f8c140840f..e6e64d437c47 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -3027,7 +3027,7 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar, desc_info->cookie, HAL_RX_BUF_RBM_SW3_BM); - /* Fill mpdu details into reo entrace ring */ + /* Fill mpdu details into reo entrance ring */ srng = &ab->hal.srng_list[dp->reo_reinject_ring.ring_id]; spin_lock_bh(&srng->lock); diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index d661fe586651..8874c815d7fa 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -301,7 +301,7 @@ tcl_ring_sel: spin_unlock_bh(&tcl_ring->lock); ret = -ENOMEM; - /* Checking for available tcl descritors in another ring in + /* Checking for available tcl descriptors in another ring in * case of failure due to full tcl ring now, is better than * checking this ring earlier for each pkt tx. * Restart ring selection if some rings are not checked yet. diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 0f2af2f14ef7..6bb82064ff99 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -6771,7 +6771,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, /* After trigger disconnect, then upper layer will * trigger connect again, then the PN number of * upper layer will be reset to keep up with AP - * side, hence PN number mis-match will not happened. + * side, hence PN number mismatch will not happen. */ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA && diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h index f99556a253e5..bfa87cb8d021 100644 --- a/drivers/net/wireless/ath/ath12k/rx_desc.h +++ b/drivers/net/wireless/ath/ath12k/rx_desc.h @@ -221,7 +221,7 @@ struct rx_mpdu_start_qcn9274 { * PPE routing even if RXOLE CCE or flow search indicate 'Use_PPE' * This is set by SW for peers which are being handled by a * host SW/accelerator subsystem that also handles packet - * uffer management for WiFi-to-PPE routing. + * buffer management for WiFi-to-PPE routing. * * This is cleared by SW for peers which are being handled * by a different subsystem, completely disabling WiFi-to-PPE -- cgit From 749a660b39030bfbacc366cd8670df2ee0e878b2 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 4 Aug 2023 17:12:55 +0800 Subject: wifi: ath11k: simplify the code with module_platform_driver The init/exit() of driver only calls platform_driver_register/unregister, it can be simpilfied with module_platform_driver. Signed-off-by: Yang Yingliang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230804091255.1347178-1-yangyingliang@huawei.com --- drivers/net/wireless/ath/ath11k/ahb.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index ceb3ccbb1827..20eee5881a31 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -1306,17 +1306,7 @@ static struct platform_driver ath11k_ahb_driver = { .shutdown = ath11k_ahb_shutdown, }; -static int ath11k_ahb_init(void) -{ - return platform_driver_register(&ath11k_ahb_driver); -} -module_init(ath11k_ahb_init); - -static void ath11k_ahb_exit(void) -{ - platform_driver_unregister(&ath11k_ahb_driver); -} -module_exit(ath11k_ahb_exit); +module_platform_driver(ath11k_ahb_driver); MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices"); MODULE_LICENSE("Dual BSD/GPL"); -- cgit From 6763ef191d672ff3c2db0622652d49b0c0a60c4a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 10 Aug 2023 11:12:23 +0200 Subject: wifi: ath11k: fix Wvoid-pointer-to-enum-cast warning 'hw_rev' is an enum, thus cast of pointer on 64-bit compile test with W=1 causes: h11k/ahb.c:1124:11: error: cast to smaller integer type 'enum ath11k_hw_rev' from 'const void *' [-Werror,-Wvoid-pointer-to-enum-cast] Signed-off-by: Krzysztof Kozlowski Acked-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230810091224.70088-1-krzysztof.kozlowski@linaro.org --- drivers/net/wireless/ath/ath11k/ahb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 20eee5881a31..1215ebdf173a 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -1096,7 +1096,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) return -EINVAL; } - hw_rev = (enum ath11k_hw_rev)of_id->data; + hw_rev = (uintptr_t)of_id->data; switch (hw_rev) { case ATH11K_HW_IPQ8074: -- cgit From de43b07db2a1af0d11ed167bb028f1038ae04086 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 10 Aug 2023 11:12:24 +0200 Subject: wifi: ath10k: fix Wvoid-pointer-to-enum-cast warning 'hw_rev' is an enum, thus cast of pointer on 64-bit compile test with W=1 causes: ath10k/ahb.c:736:11: error: cast to smaller integer type 'enum ath10k_hw_rev' from 'const void *' [-Werror,-Wvoid-pointer-to-enum-cast] Signed-off-by: Krzysztof Kozlowski Acked-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230810091224.70088-2-krzysztof.kozlowski@linaro.org --- drivers/net/wireless/ath/ath10k/ahb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 76efea2f1138..a378bc48b1d2 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -733,7 +733,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev) int ret; struct ath10k_bus_params bus_params = {}; - hw_rev = (enum ath10k_hw_rev)of_device_get_match_data(&pdev->dev); + hw_rev = (uintptr_t)of_device_get_match_data(&pdev->dev); if (!hw_rev) { dev_err(&pdev->dev, "OF data missing\n"); return -EINVAL; -- cgit From adb0b206709f4f2f1256a1ea20619ab98e99f2e7 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 11 Aug 2023 18:44:13 +0800 Subject: wifi: ath11k: Remove unused declarations Commit 2c3960c2253d ("ath11k: setup ce tasklet for control path") declared but never implemented ath11k_ce_map_service_to_pipe(). Commit e3396b8bddd2 ("ath11k: ce: support different CE configurations") declared but never implemented ath11k_ce_attr_attach(). Commit d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") declared but never implemented ath11k_qmi_event_work()/ath11k_qmi_msg_recv_work(). Signed-off-by: Yue Haibing Acked-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230811104413.33668-1-yuehaibing@huawei.com --- drivers/net/wireless/ath/ath11k/ce.h | 3 --- drivers/net/wireless/ath/ath11k/qmi.h | 2 -- 2 files changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath11k/ce.h b/drivers/net/wireless/ath/ath11k/ce.h index 1fc6360e7f01..c0f6a0ba86df 100644 --- a/drivers/net/wireless/ath/ath11k/ce.h +++ b/drivers/net/wireless/ath/ath11k/ce.h @@ -203,9 +203,6 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab); void ath11k_ce_free_pipes(struct ath11k_base *ab); int ath11k_ce_get_attr_flags(struct ath11k_base *ab, int ce_id); void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id); -int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe); -int ath11k_ce_attr_attach(struct ath11k_base *ab); void ath11k_ce_get_shadow_config(struct ath11k_base *ab, u32 **shadow_cfg, u32 *shadow_cfg_len); void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab); diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h index b0407abf90cd..d477e2be814b 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -514,8 +514,6 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 { int ath11k_qmi_firmware_start(struct ath11k_base *ab, u32 mode); void ath11k_qmi_firmware_stop(struct ath11k_base *ab); -void ath11k_qmi_event_work(struct work_struct *work); -void ath11k_qmi_msg_recv_work(struct work_struct *work); void ath11k_qmi_deinit_service(struct ath11k_base *ab); int ath11k_qmi_init_service(struct ath11k_base *ab); void ath11k_qmi_free_resource(struct ath11k_base *ab); -- cgit From 3b86f86d0f163454c4043a629f0ba95641d371bc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 14 Aug 2023 09:32:23 +0200 Subject: wifi: ath: remove unused-but-set parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This has never been used since the driver was merged, but it now causes a W=1 warning in recent clang versions drivers/net/wireless/ath/ath9k/main.c:1566:21: error: parameter 'changed_flags' set but not used [-Werror,-Wunused-but-set-parameter] drivers/net/wireless/ath/ath9k/htc_drv_main.c:1258:25: error: parameter 'changed_flags' set but not used [-Werror,-Wunused-but-set-parameter] drivers/net/wireless/ath/ath5k/mac80211-ops.c:367:62: error: parameter 'changed_flags' set but not used [-Werror,-Wunused-but-set-parameter] Remove the bit manipulation on the otherwise unused parameter. Signed-off-by: Arnd Bergmann Reviewed-by: Jeff Johnson Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230814073255.1065242-1-arnd@kernel.org --- drivers/net/wireless/ath/ath12k/mac.c | 5 ++--- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 1 - drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 - drivers/net/wireless/ath/ath9k/main.c | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 6bb82064ff99..88346e66bb75 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -5660,7 +5660,6 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); - changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; ar->filter_flags = *total_flags; @@ -5678,8 +5677,8 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw, "fail to set monitor filter: %d\n", ret); } ath12k_dbg(ar->ab, ATH12K_DBG_MAC, - "changed_flags:0x%x, total_flags:0x%x, reset_flag:%d\n", - changed_flags, *total_flags, reset_flag); + "total_flags:0x%x, reset_flag:%d\n", + *total_flags, reset_flag); mutex_unlock(&ar->conf_mutex); } diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 11ed30d6b595..c630343ca4f9 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -382,7 +382,6 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, mfilt[1] = multicast >> 32; /* Only deal with supported flags */ - changed_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS; /* If HW detects any phy or radar errors, leave those filters on. diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 44e02cfe2438..9a9b5212051a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1264,7 +1264,6 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, u32 rfilt; mutex_lock(&priv->mutex); - changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; if (test_bit(ATH_OP_INVALID, &common->op_flags)) { diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6360d3356e25..1494feedb27d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1571,7 +1571,6 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, struct ath_chanctx *ctx; u32 rfilt; - changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; spin_lock_bh(&sc->chan_lock); -- cgit From e10ec6ea612ca54e3266996875b0742619dac20f Mon Sep 17 00:00:00 2001 From: Mahmoud Maatuq Date: Tue, 15 Aug 2023 08:08:19 +0400 Subject: wifi: ath5k: ath5k_hw_get_median_noise_floor(): use swap() coccinielle reported the following: ./drivers/net/wireless/ath/ath5k/phy.c:1573:25-26: WARNING opportunity for swap() while trying to fix the above warning, it reveals that ath5k_hw_get_median_noise_floor() had open-coded sort() functionality. Since ath5k_hw_get_median_noise_floor() only executes once every 10 seconds, any extra overhead due to sort() calling its "compare" and "swap" functions can be ignored, so replace the existing logic with a call to sort(). Signed-off-by: Mahmoud Maatuq Suggested-by: Jiri Slaby Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230815040819.649455-1-mahmoudmatook.mm@gmail.com --- drivers/net/wireless/ath/ath5k/phy.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 5797ef9c73d7..7ee4e1616f45 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -26,6 +26,7 @@ #include #include +#include #include #include "ath5k.h" @@ -1554,6 +1555,11 @@ static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) hist->nfval[hist->index] = noise_floor; } +static int cmps16(const void *a, const void *b) +{ + return *(s16 *)a - *(s16 *)b; +} + /** * ath5k_hw_get_median_noise_floor() - Get median NF from history buffer * @ah: The &struct ath5k_hw @@ -1561,25 +1567,16 @@ static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) { - s16 sort[ATH5K_NF_CAL_HIST_MAX]; - s16 tmp; - int i, j; - - memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort)); - for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) { - for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { - if (sort[j] > sort[j - 1]) { - tmp = sort[j]; - sort[j] = sort[j - 1]; - sort[j - 1] = tmp; - } - } - } + s16 sorted_nfval[ATH5K_NF_CAL_HIST_MAX]; + int i; + + memcpy(sorted_nfval, ah->ah_nfcal_hist.nfval, sizeof(sorted_nfval)); + sort(sorted_nfval, ATH5K_NF_CAL_HIST_MAX, sizeof(s16), cmps16, NULL); for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, - "cal %d:%d\n", i, sort[i]); + "cal %d:%d\n", i, sorted_nfval[i]); } - return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; + return sorted_nfval[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; } /** -- cgit From afb522b36e76acaa9f8fc06d0a9742d841c47c16 Mon Sep 17 00:00:00 2001 From: Rajat Soni Date: Tue, 22 Aug 2023 16:42:23 +0300 Subject: wifi: ath12k: Fix memory leak in rx_desc and tx_desc Currently when ath12k_dp_cc_desc_init() is called we allocate memory to rx_descs and tx_descs. In ath12k_dp_cc_cleanup(), during descriptor cleanup rx_descs and tx_descs memory is not freed. This is cause of memory leak. These allocated memory should be freed in ath12k_dp_cc_cleanup. In ath12k_dp_cc_desc_init(), we can save base address of rx_descs and tx_descs. In ath12k_dp_cc_cleanup(), we can free rx_descs and tx_descs memory using their base address. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Rajat Soni Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230718053510.30894-1-quic_rajson@quicinc.com --- drivers/net/wireless/ath/ath12k/dp.c | 30 +++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath12k/dp.h | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index ae1645d0f42a..f933896f2a68 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -1129,6 +1129,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) struct ath12k_dp *dp = &ab->dp; struct sk_buff *skb; int i; + u32 pool_id, tx_spt_page; if (!dp->spt_info) return; @@ -1148,6 +1149,14 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) dev_kfree_skb_any(skb); } + for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) { + if (!dp->spt_info->rxbaddr[i]) + continue; + + kfree(dp->spt_info->rxbaddr[i]); + dp->spt_info->rxbaddr[i] = NULL; + } + spin_unlock_bh(&dp->rx_desc_lock); /* TX Descriptor cleanup */ @@ -1170,6 +1179,21 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) spin_unlock_bh(&dp->tx_desc_lock[i]); } + for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES; pool_id++) { + spin_lock_bh(&dp->tx_desc_lock[pool_id]); + + for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) { + tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL; + if (!dp->spt_info->txbaddr[tx_spt_page]) + continue; + + kfree(dp->spt_info->txbaddr[tx_spt_page]); + dp->spt_info->txbaddr[tx_spt_page] = NULL; + } + + spin_unlock_bh(&dp->tx_desc_lock[pool_id]); + } + /* unmap SPT pages */ for (i = 0; i < dp->num_spt_pages; i++) { if (!dp->spt_info[i].vaddr) @@ -1343,6 +1367,8 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) return -ENOMEM; } + dp->spt_info->rxbaddr[i] = &rx_descs[0]; + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j); rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; @@ -1368,8 +1394,10 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) return -ENOMEM; } + tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL; + dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0]; + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { - tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL; ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page; tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j); tx_descs[j].pool_id = pool_id; diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index 6e7b7281d549..61f765432516 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -289,6 +289,8 @@ struct ath12k_tx_desc_info { struct ath12k_spt_info { dma_addr_t paddr; u64 *vaddr; + struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES]; + struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES]; }; struct ath12k_reo_queue_ref { -- cgit From 664c84c26d7a77d4b19813831466d67253f2326e Mon Sep 17 00:00:00 2001 From: Yu Liao Date: Tue, 22 Aug 2023 10:14:55 +0800 Subject: net: dm9051: Use PTR_ERR_OR_ZERO() to simplify code Use the standard error pointer macro to shorten the code and simplify. Signed-off-by: Yu Liao Link: https://lore.kernel.org/r/20230822021455.205101-2-liaoyu15@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/davicom/dm9051.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/davicom/dm9051.c b/drivers/net/ethernet/davicom/dm9051.c index 2caaf1e9f42f..bcfe52c11804 100644 --- a/drivers/net/ethernet/davicom/dm9051.c +++ b/drivers/net/ethernet/davicom/dm9051.c @@ -1158,9 +1158,7 @@ static int dm9051_phy_connect(struct board_info *db) db->phydev = phy_connect(db->ndev, phy_id, dm9051_handle_link_change, PHY_INTERFACE_MODE_MII); - if (IS_ERR(db->phydev)) - return PTR_ERR_OR_ZERO(db->phydev); - return 0; + return PTR_ERR_OR_ZERO(db->phydev); } static int dm9051_probe(struct spi_device *spi) -- cgit From e83fabb797b98a9ead4b5bb50c85fb499966ad7e Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Tue, 22 Aug 2023 14:52:55 +0800 Subject: net: fec: add exception tracing for XDP As we already added the exception tracing for XDP_TX, I think it is necessary to add the exception tracing for other XDP actions, such as XDP_REDIRECT, XDP_ABORTED and unknown error actions. Signed-off-by: Wei Fang Suggested-by: Jakub Kicinski Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20230822065255.606739-1-wei.fang@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index e23a55977183..8909899e9a31 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1583,25 +1583,18 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, case XDP_REDIRECT: rxq->stats[RX_XDP_REDIRECT]++; err = xdp_do_redirect(fep->netdev, xdp, prog); - if (!err) { - ret = FEC_ENET_XDP_REDIR; - } else { - ret = FEC_ENET_XDP_CONSUMED; - page = virt_to_head_page(xdp->data); - page_pool_put_page(rxq->page_pool, page, sync, true); - } + if (unlikely(err)) + goto xdp_err; + + ret = FEC_ENET_XDP_REDIR; break; case XDP_TX: err = fec_enet_xdp_tx_xmit(fep, cpu, xdp, sync); - if (unlikely(err)) { - ret = FEC_ENET_XDP_CONSUMED; - page = virt_to_head_page(xdp->data); - page_pool_put_page(rxq->page_pool, page, sync, true); - trace_xdp_exception(fep->netdev, prog, act); - } else { - ret = FEC_ENET_XDP_TX; - } + if (unlikely(err)) + goto xdp_err; + + ret = FEC_ENET_XDP_TX; break; default: @@ -1613,9 +1606,12 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, case XDP_DROP: rxq->stats[RX_XDP_DROP]++; +xdp_err: ret = FEC_ENET_XDP_CONSUMED; page = virt_to_head_page(xdp->data); page_pool_put_page(rxq->page_pool, page, sync, true); + if (act != XDP_DROP) + trace_xdp_exception(fep->netdev, prog, act); break; } -- cgit From cfb5677de5babe3664356155a391e2ff781c9ee1 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 22 Aug 2023 17:31:24 +0100 Subject: net: ethernet: mtk_eth_soc: fix register definitions for MT7988 More register macros need to be adjusted for the 3rd GMAC on MT7988. Account for added bit in SYSCFG0_SGMII_MASK. Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") Signed-off-by: Daniel Golle Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/1c8da012e2ca80939906d85f314138c552139f0f.1692721443.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 4a2470fbad2c..8d2d35b32235 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -133,10 +133,12 @@ #define MTK_GDMA_XGDM_SEL BIT(31) /* Unicast Filter MAC Address Register - Low */ -#define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) +#define MTK_GDMA_MAC_ADRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x548 : 0x508 + (_x * 0x1000); }) /* Unicast Filter MAC Address Register - High */ -#define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000)) +#define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x54C : 0x50C + (_x * 0x1000); }) /* FE global misc reg*/ #define MTK_FE_GLO_MISC 0x124 @@ -503,7 +505,7 @@ #define ETHSYS_SYSCFG0 0x14 #define SYSCFG0_GE_MASK 0x3 #define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2))) -#define SYSCFG0_SGMII_MASK GENMASK(9, 8) +#define SYSCFG0_SGMII_MASK GENMASK(9, 7) #define SYSCFG0_SGMII_GMAC1 ((2 << 8) & SYSCFG0_SGMII_MASK) #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) -- cgit From 88c1e6efb7a58ff64ce196ec09d831263793c858 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 22 Aug 2023 17:32:03 +0100 Subject: net: ethernet: mtk_eth_soc: add reset bits for MT7988 Add bits needed to reset the frame engine on MT7988. Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/89b6c38380e7a3800c1362aa7575600717bc7543.1692721443.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 76 +++++++++++++++++++++-------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 ++++-- 2 files changed, 68 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index fe05c9020269..2482f4731308 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -3613,19 +3613,34 @@ static void mtk_hw_reset(struct mtk_eth *eth) { u32 val; - if (mtk_is_netsys_v2_or_greater(eth)) { + if (mtk_is_netsys_v2_or_greater(eth)) regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); + + if (mtk_is_netsys_v3_or_greater(eth)) { + val = RSTCTRL_PPE0_V3; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + val |= RSTCTRL_PPE1_V3; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) + val |= RSTCTRL_PPE2; + + val |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; + } else if (mtk_is_netsys_v2_or_greater(eth)) { val = RSTCTRL_PPE0_V2; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + val |= RSTCTRL_PPE1; } else { val = RSTCTRL_PPE0; } - if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) - val |= RSTCTRL_PPE1; - ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); - if (mtk_is_netsys_v2_or_greater(eth)) + if (mtk_is_netsys_v3_or_greater(eth)) + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, + 0x6f8ff); + else if (mtk_is_netsys_v2_or_greater(eth)) regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff); } @@ -3651,13 +3666,21 @@ static void mtk_hw_warm_reset(struct mtk_eth *eth) return; } - if (mtk_is_netsys_v2_or_greater(eth)) + if (mtk_is_netsys_v3_or_greater(eth)) { + rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V3; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + rst_mask |= RSTCTRL_PPE1_V3; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) + rst_mask |= RSTCTRL_PPE2; + + rst_mask |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; + } else if (mtk_is_netsys_v2_or_greater(eth)) { rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; - else + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + rst_mask |= RSTCTRL_PPE1; + } else { rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) - rst_mask |= RSTCTRL_PPE1; + } regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); @@ -4009,11 +4032,17 @@ static void mtk_prepare_for_reset(struct mtk_eth *eth) u32 val; int i; - /* disabe FE P3 and P4 */ - val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) - val |= MTK_FE_LINK_DOWN_P4; - mtk_w32(eth, val, MTK_FE_GLO_CFG); + /* set FE PPE ports link down */ + for (i = MTK_GMAC1_ID; + i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); + i += 2) { + val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) | MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + val |= MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) + val |= MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); + mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); + } /* adjust PPE configurations to prepare for reset */ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) @@ -4074,11 +4103,18 @@ static void mtk_pending_work(struct work_struct *work) } } - /* enabe FE P3 and P4 */ - val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) - val &= ~MTK_FE_LINK_DOWN_P4; - mtk_w32(eth, val, MTK_FE_GLO_CFG); + /* set FE PPE ports link up */ + for (i = MTK_GMAC1_ID; + i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); + i += 2) { + val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) & ~MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) + val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) + val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); + + mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); + } clear_bit(MTK_RESETTING, ð->state); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 8d2d35b32235..cf9381a3d68b 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -76,9 +76,8 @@ #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 /* Frame Engine Global Configuration */ -#define MTK_FE_GLO_CFG 0x00 -#define MTK_FE_LINK_DOWN_P3 BIT(11) -#define MTK_FE_LINK_DOWN_P4 BIT(12) +#define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00) +#define MTK_FE_LINK_DOWN_P(x) BIT(((x) + 8) % 16) /* Frame Engine Global Reset Register */ #define MTK_RST_GL 0x04 @@ -522,9 +521,15 @@ /* ethernet reset control register */ #define ETHSYS_RSTCTRL 0x34 #define RSTCTRL_FE BIT(6) +#define RSTCTRL_WDMA0 BIT(24) +#define RSTCTRL_WDMA1 BIT(25) +#define RSTCTRL_WDMA2 BIT(26) #define RSTCTRL_PPE0 BIT(31) #define RSTCTRL_PPE0_V2 BIT(30) #define RSTCTRL_PPE1 BIT(31) +#define RSTCTRL_PPE0_V3 BIT(29) +#define RSTCTRL_PPE1_V3 BIT(30) +#define RSTCTRL_PPE2 BIT(31) #define RSTCTRL_ETH BIT(23) /* ethernet reset check idle register */ @@ -931,6 +936,7 @@ enum mkt_eth_capabilities { MTK_QDMA_BIT, MTK_SOC_MT7628_BIT, MTK_RSTCTRL_PPE1_BIT, + MTK_RSTCTRL_PPE2_BIT, MTK_U3_COPHY_V2_BIT, /* MUX BITS*/ @@ -965,6 +971,7 @@ enum mkt_eth_capabilities { #define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) #define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) +#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ @@ -1047,7 +1054,8 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1) -#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) +#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ + MTK_RSTCTRL_PPE2) struct mtk_tx_dma_desc_info { dma_addr_t addr; -- cgit From ebb1e4f9cf38da2139b37e24b5e10bff3dcc4187 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 22 Aug 2023 17:32:54 +0100 Subject: net: ethernet: mtk_eth_soc: add support for in-SoC SRAM MT7981, MT7986 and MT7988 come with in-SoC SRAM dedicated for Ethernet DMA rings. Support using the SRAM without breaking existing device tree bindings, ie. only new SoC starting from MT7988 will have the SRAM declared as additional resource in device tree. For MT7981 and MT7986 an offset on top of the main I/O base is used. Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/e45e0f230c63ad58869e8fe35b95a2fb8925b625.1692721443.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 88 ++++++++++++++++++++++------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 +++- 2 files changed, 78 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 2482f4731308..ec6a251a0f02 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1135,10 +1135,13 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) dma_addr_t dma_addr; int i; - eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, - cnt * soc->txrx.txd_size, - ð->phy_scratch_ring, - GFP_KERNEL); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, + cnt * soc->txrx.txd_size, + ð->phy_scratch_ring, + GFP_KERNEL); if (unlikely(!eth->scratch_ring)) return -ENOMEM; @@ -2446,8 +2449,14 @@ static int mtk_tx_alloc(struct mtk_eth *eth) if (!ring->buf) goto no_tx_mem; - ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, - &ring->phys, GFP_KERNEL); + if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) { + ring->dma = eth->sram_base + ring_size * sz; + ring->phys = eth->phy_scratch_ring + ring_size * (dma_addr_t)sz; + } else { + ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, + &ring->phys, GFP_KERNEL); + } + if (!ring->dma) goto no_tx_mem; @@ -2546,8 +2555,7 @@ static void mtk_tx_clean(struct mtk_eth *eth) kfree(ring->buf); ring->buf = NULL; } - - if (ring->dma) { + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { dma_free_coherent(eth->dma_dev, ring->dma_size * soc->txrx.txd_size, ring->dma, ring->phys); @@ -2566,9 +2574,14 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) { const struct mtk_reg_map *reg_map = eth->soc->reg_map; struct mtk_rx_ring *ring; - int rx_data_len, rx_dma_size; + int rx_data_len, rx_dma_size, tx_ring_size; int i; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) + tx_ring_size = MTK_QDMA_RING_SIZE; + else + tx_ring_size = MTK_DMA_SIZE; + if (rx_flag == MTK_RX_FLAGS_QDMA) { if (ring_no) return -EINVAL; @@ -2603,9 +2616,20 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) ring->page_pool = pp; } - ring->dma = dma_alloc_coherent(eth->dma_dev, - rx_dma_size * eth->soc->txrx.rxd_size, - &ring->phys, GFP_KERNEL); + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, + rx_dma_size * eth->soc->txrx.rxd_size, + &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * + eth->soc->txrx.txd_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * + eth->soc->txrx.txd_size * (ring_no + 1); + } + if (!ring->dma) return -ENOMEM; @@ -2690,7 +2714,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) return 0; } -static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) +static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) { int i; @@ -2713,7 +2737,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) ring->data = NULL; } - if (ring->dma) { + if (!in_sram && ring->dma) { dma_free_coherent(eth->dma_dev, ring->dma_size * eth->soc->txrx.rxd_size, ring->dma, ring->phys); @@ -3073,7 +3097,7 @@ static void mtk_dma_free(struct mtk_eth *eth) for (i = 0; i < MTK_MAX_DEVS; i++) if (eth->netdev[i]) netdev_reset_queue(eth->netdev[i]); - if (eth->scratch_ring) { + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { dma_free_coherent(eth->dma_dev, MTK_QDMA_RING_SIZE * soc->txrx.txd_size, eth->scratch_ring, eth->phy_scratch_ring); @@ -3081,13 +3105,13 @@ static void mtk_dma_free(struct mtk_eth *eth) eth->phy_scratch_ring = 0; } mtk_tx_clean(eth); - mtk_rx_clean(eth, ð->rx_ring[0]); - mtk_rx_clean(eth, ð->rx_ring_qdma); + mtk_rx_clean(eth, ð->rx_ring[0], MTK_HAS_CAPS(soc->caps, MTK_SRAM)); + mtk_rx_clean(eth, ð->rx_ring_qdma, false); if (eth->hwlro) { mtk_hwlro_rx_uninit(eth); for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) - mtk_rx_clean(eth, ð->rx_ring[i]); + mtk_rx_clean(eth, ð->rx_ring[i], false); } kfree(eth->scratch_head); @@ -4676,7 +4700,7 @@ static int mtk_sgmii_init(struct mtk_eth *eth) static int mtk_probe(struct platform_device *pdev) { - struct resource *res = NULL; + struct resource *res = NULL, *res_sram; struct device_node *mac_np; struct mtk_eth *eth; int err, i; @@ -4696,6 +4720,20 @@ static int mtk_probe(struct platform_device *pdev) if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) eth->ip_align = NET_IP_ALIGN; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { + /* SRAM is actual memory and supports transparent access just like DRAM. + * Hence we don't require __iomem being set and don't need to use accessor + * functions to read from or write to SRAM. + */ + if (mtk_is_netsys_v3_or_greater(eth)) { + eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(eth->sram_base)) + return PTR_ERR(eth->sram_base); + } else { + eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET; + } + } + spin_lock_init(ð->page_lock); spin_lock_init(ð->tx_irq_lock); spin_lock_init(ð->rx_irq_lock); @@ -4759,6 +4797,18 @@ static int mtk_probe(struct platform_device *pdev) err = -EINVAL; goto err_destroy_sgmii; } + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { + if (mtk_is_netsys_v3_or_greater(eth)) { + res_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res_sram) { + err = -EINVAL; + goto err_destroy_sgmii; + } + eth->phy_scratch_ring = res_sram->start; + } else { + eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET; + } + } } if (eth->soc->offload_version) { diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index cf9381a3d68b..7e961fff94f3 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -139,6 +139,9 @@ #define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ 0x54C : 0x50C + (_x * 0x1000); }) +/* Internal SRAM offset */ +#define MTK_ETH_SRAM_OFFSET 0x40000 + /* FE global misc reg*/ #define MTK_FE_GLO_MISC 0x124 @@ -938,6 +941,7 @@ enum mkt_eth_capabilities { MTK_RSTCTRL_PPE1_BIT, MTK_RSTCTRL_PPE2_BIT, MTK_U3_COPHY_V2_BIT, + MTK_SRAM_BIT, /* MUX BITS*/ MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, @@ -973,6 +977,7 @@ enum mkt_eth_capabilities { #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) +#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) @@ -1048,14 +1053,14 @@ enum mkt_eth_capabilities { #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ - MTK_RSTCTRL_PPE1) + MTK_RSTCTRL_PPE1 | MTK_SRAM) #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1) + MTK_RSTCTRL_PPE1 | MTK_SRAM) #define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ - MTK_RSTCTRL_PPE2) + MTK_RSTCTRL_PPE2 | MTK_SRAM) struct mtk_tx_dma_desc_info { dma_addr_t addr; @@ -1215,6 +1220,7 @@ struct mtk_eth { struct device *dev; struct device *dma_dev; void __iomem *base; + void *sram_base; spinlock_t page_lock; spinlock_t tx_irq_lock; spinlock_t rx_irq_lock; -- cgit From 2d75891ebc09ba9cf30697dfd54497ef0220308f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 22 Aug 2023 17:33:12 +0100 Subject: net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988 Systems having 4 GiB of RAM and more require DMA addressing beyond the current 32-bit limit. Starting from MT7988 the hardware now supports 36-bit DMA addressing, let's use that new capability in the driver to avoid running into swiotlb on systems with 4 GiB of RAM or more. Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/95b919c98876c9e49761e44662e7c937479eecb8.1692721443.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++++++++++++++++++++++-- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 22 +++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index ec6a251a0f02..6ad42e3b488f 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1328,6 +1328,10 @@ static void mtk_tx_set_dma_desc_v2(struct net_device *dev, void *txd, data = TX_DMA_PLEN0(info->size); if (info->last) data |= TX_DMA_LS0; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) + data |= TX_DMA_PREP_ADDR64(info->addr); + WRITE_ONCE(desc->txd3, data); /* set forward port */ @@ -1997,6 +2001,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, bool xdp_flush = false; int idx; struct sk_buff *skb; + u64 addr64 = 0; u8 *data, *new_data; struct mtk_rx_dma_v2 *rxd, trxd; int done = 0, bytes = 0; @@ -2112,7 +2117,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, goto release_desc; } - dma_unmap_single(eth->dma_dev, trxd.rxd1, + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) + addr64 = RX_DMA_GET_ADDR64(trxd.rxd2); + + dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64), ring->buf_size, DMA_FROM_DEVICE); skb = build_skb(data, ring->frag_size); @@ -2178,6 +2186,9 @@ release_desc: else rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) + rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); + ring->calc_idx = idx; done++; } @@ -2670,6 +2681,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) else rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) + rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); + rxd->rxd3 = 0; rxd->rxd4 = 0; if (mtk_is_netsys_v2_or_greater(eth)) { @@ -2716,6 +2730,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) { + u64 addr64 = 0; int i; if (ring->data && ring->dma) { @@ -2729,7 +2744,10 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ if (!rxd->rxd1) continue; - dma_unmap_single(eth->dma_dev, rxd->rxd1, + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) + addr64 = RX_DMA_GET_ADDR64(rxd->rxd2); + + dma_unmap_single(eth->dma_dev, ((u64)rxd->rxd1 | addr64), ring->buf_size, DMA_FROM_DEVICE); mtk_rx_put_buff(ring, ring->data[i], false); } @@ -4734,6 +4752,14 @@ static int mtk_probe(struct platform_device *pdev) } } + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); + if (err) { + dev_err(&pdev->dev, "Wrong DMA config\n"); + return -EINVAL; + } + } + spin_lock_init(ð->page_lock); spin_lock_init(ð->tx_irq_lock); spin_lock_init(ð->rx_irq_lock); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 7e961fff94f3..403219d987ef 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -331,6 +331,14 @@ #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) #define TX_DMA_SWC BIT(14) #define TX_DMA_PQID GENMASK(3, 0) +#define TX_DMA_ADDR64_MASK GENMASK(3, 0) +#if IS_ENABLED(CONFIG_64BIT) +# define TX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(TX_DMA_ADDR64_MASK, (x))) << 32) +# define TX_DMA_PREP_ADDR64(x) FIELD_PREP(TX_DMA_ADDR64_MASK, ((x) >> 32)) +#else +# define TX_DMA_GET_ADDR64(x) (0) +# define TX_DMA_PREP_ADDR64(x) (0) +#endif /* PDMA on MT7628 */ #define TX_DMA_DONE BIT(31) @@ -343,6 +351,14 @@ #define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) #define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) #define RX_DMA_VTAG BIT(15) +#define RX_DMA_ADDR64_MASK GENMASK(3, 0) +#if IS_ENABLED(CONFIG_64BIT) +# define RX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(RX_DMA_ADDR64_MASK, (x))) << 32) +# define RX_DMA_PREP_ADDR64(x) FIELD_PREP(RX_DMA_ADDR64_MASK, ((x) >> 32)) +#else +# define RX_DMA_GET_ADDR64(x) (0) +# define RX_DMA_PREP_ADDR64(x) (0) +#endif /* QDMA descriptor rxd3 */ #define RX_DMA_VID(x) ((x) & VLAN_VID_MASK) @@ -942,6 +958,7 @@ enum mkt_eth_capabilities { MTK_RSTCTRL_PPE2_BIT, MTK_U3_COPHY_V2_BIT, MTK_SRAM_BIT, + MTK_36BIT_DMA_BIT, /* MUX BITS*/ MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, @@ -978,6 +995,7 @@ enum mkt_eth_capabilities { #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) #define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) +#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT) #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) @@ -1059,8 +1077,8 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1 | MTK_SRAM) -#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ - MTK_RSTCTRL_PPE2 | MTK_SRAM) +#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ + MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) struct mtk_tx_dma_desc_info { dma_addr_t addr; -- cgit From 59da9885767a75df697c84c06aaf2296e10d85a4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 23 Aug 2023 10:56:32 +0200 Subject: net: dsa: use capital "OR" for multiple licenses in SPDX Documentation/process/license-rules.rst and checkpatch expect the SPDX identifier syntax for multiple licenses to use capital "OR". Correct it to keep consistent format and avoid copy-paste issues. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Kurt Kanzenbach Reviewed-by: FLorian Fainelli Link: https://lore.kernel.org/r/20230823085632.116725-1-krzysztof.kozlowski@linaro.org Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_serdes.c | 2 +- drivers/net/dsa/b53/b53_serdes.h | 2 +- drivers/net/dsa/hirschmann/hellcreek.c | 2 +- drivers/net/dsa/hirschmann/hellcreek.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c index b0ccebcd3ffa..3f8a491ce885 100644 --- a/drivers/net/dsa/b53/b53_serdes.c +++ b/drivers/net/dsa/b53/b53_serdes.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Northstar Plus switch SerDes/SGMII PHY main logic * diff --git a/drivers/net/dsa/b53/b53_serdes.h b/drivers/net/dsa/b53/b53_serdes.h index ef81f5da5f81..3d367c4df4d9 100644 --- a/drivers/net/dsa/b53/b53_serdes.h +++ b/drivers/net/dsa/b53/b53_serdes.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Northstar Plus switch SerDes/SGMII PHY definitions * diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 720f4e4ed0b0..11ef1d7ea229 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 or MIT) +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* * DSA driver for: * Hirschmann Hellcreek TSN switch. diff --git a/drivers/net/dsa/hirschmann/hellcreek.h b/drivers/net/dsa/hirschmann/hellcreek.h index 4a678f7d61ae..6874cb9dc361 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.h +++ b/drivers/net/dsa/hirschmann/hellcreek.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 or MIT) */ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ /* * DSA driver for: * Hirschmann Hellcreek TSN switch. -- cgit From 3ed247e789114c5bbb3380c3666eb819336b94e5 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 28 Jul 2023 17:17:59 -0700 Subject: igc: Add support for multiple in-flight TX timestamps Add support for using the four sets of timestamping registers that i225/i226 have available for TX. In some workloads, where multiple applications request hardware transmission timestamps, it was possible that some of those requests were denied because the only in use register was already occupied. This is also in preparation to future support for hardware timestamping with multiple PTP domains. With multiple domains chances of multiple TX timestamps being requested at the same time increase. Before: $ sudo ./ntpperf -i enp3s0 -m 10:22:22:22:22:21 -d 192.168.1.3 -s 172.18.0.0/16 -I -H -o 37 | responses | TX timestamp offset (ns) rate clients | lost invalid basic xleave | min mean max stddev 1000 100 0.00% 0.00% 0.00% 100.00% +1 +41 +73 13 1500 150 0.00% 0.00% 0.00% 100.00% +9 +49 +87 15 2250 225 0.00% 0.00% 0.00% 100.00% +9 +42 +79 13 3375 337 0.00% 0.00% 0.00% 100.00% +11 +46 +81 13 5062 506 0.00% 0.00% 0.00% 100.00% +7 +44 +80 13 7593 759 0.00% 0.00% 0.00% 100.00% +9 +44 +79 12 11389 1138 0.00% 0.00% 0.00% 100.00% +14 +51 +87 13 17083 1708 0.00% 0.00% 0.00% 100.00% +1 +41 +80 14 25624 2562 0.00% 0.00% 0.00% 100.00% +11 +50 +5107 51 38436 3843 0.00% 0.00% 0.00% 100.00% -2 +36 +7843 38 57654 5765 0.00% 0.00% 0.00% 100.00% +4 +42 +10503 69 86481 8648 0.00% 0.00% 0.00% 100.00% +11 +54 +5492 65 129721 12972 0.00% 0.00% 0.00% 100.00% +31 +2680 +6942 2606 194581 16384 16.79% 0.00% 0.87% 82.34% +73 +4444 +15879 3116 291871 16384 35.05% 0.00% 1.53% 63.42% +188 +5381 +17019 3035 437806 16384 54.95% 0.00% 2.55% 42.50% +233 +6302 +13885 2846 After: $ sudo ./ntpperf -i enp3s0 -m 10:22:22:22:22:21 -d 192.168.1.3 -s 172.18.0.0/16 -I -H -o 37 | responses | TX timestamp offset (ns) rate clients | lost invalid basic xleave | min mean max stddev 1000 100 0.00% 0.00% 0.00% 100.00% -20 +12 +43 13 1500 150 0.00% 0.00% 0.00% 100.00% -23 +18 +57 14 2250 225 0.00% 0.00% 0.00% 100.00% -2 +33 +67 13 3375 337 0.00% 0.00% 0.00% 100.00% +1 +38 +76 13 5062 506 0.00% 0.00% 0.00% 100.00% +9 +52 +93 14 7593 759 0.00% 0.00% 0.00% 100.00% +11 +47 +82 13 11389 1138 0.00% 0.00% 0.00% 100.00% -9 +27 +74 13 17083 1708 0.00% 0.00% 0.00% 100.00% -13 +25 +66 14 25624 2562 0.00% 0.00% 0.00% 100.00% -8 +28 +65 13 38436 3843 0.00% 0.00% 0.00% 100.00% -13 +28 +69 13 57654 5765 0.00% 0.00% 0.00% 100.00% -11 +32 +71 14 86481 8648 0.00% 0.00% 0.00% 100.00% +2 +44 +83 14 129721 12972 15.36% 0.00% 0.35% 84.29% -2 +2248 +22907 4252 194581 16384 42.98% 0.00% 1.98% 55.04% -4 +5278 +65039 5856 291871 16384 54.33% 0.00% 2.21% 43.46% -3 +6306 +22608 5665 We can see that with 4 registers, as expected, we are able to handle a increasing number of requests more consistently, but as soon as all registers are in use, the decrease in quality of service happens in a sharp step. Signed-off-by: Vinicius Costa Gomes Reviewed-by: Vladimir Oltean Reviewed-by: Muhammad Husaini Zulkifli Reviewed-by: Kurt Kanzenbach Tested-by: Naama Meir Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igc/igc.h | 18 ++- drivers/net/ethernet/intel/igc/igc_base.h | 3 + drivers/net/ethernet/intel/igc/igc_defines.h | 7 ++ drivers/net/ethernet/intel/igc/igc_main.c | 41 ++++++- drivers/net/ethernet/intel/igc/igc_ptp.c | 174 ++++++++++++++++++--------- drivers/net/ethernet/intel/igc/igc_regs.h | 12 ++ 6 files changed, 192 insertions(+), 63 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 1c6ab340c020..8ebe6999a528 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -38,6 +38,8 @@ void igc_ethtool_set_ops(struct net_device *); #define MAX_FLEX_FILTER 32 +#define IGC_MAX_TX_TSTAMP_REGS 4 + enum igc_mac_filter_type { IGC_MAC_FILTER_TYPE_DST = 0, IGC_MAC_FILTER_TYPE_SRC @@ -70,6 +72,15 @@ struct igc_rx_packet_stats { u64 other_packets; }; +struct igc_tx_timestamp_request { + struct sk_buff *skb; /* reference to the packet being timestamped */ + unsigned long start; /* when the tstamp request started (jiffies) */ + u32 mask; /* _TSYNCTXCTL_TXTT_{X} bit for this request */ + u32 regl; /* which TXSTMPL_{X} register should be used */ + u32 regh; /* which TXSTMPH_{X} register should be used */ + u32 flags; /* flags that should be added to the tx_buffer */ +}; + struct igc_ring_container { struct igc_ring *ring; /* pointer to linked list of rings */ unsigned int total_bytes; /* total bytes processed this int */ @@ -245,9 +256,8 @@ struct igc_adapter { * ptp_tx_lock. */ spinlock_t ptp_tx_lock; - struct sk_buff *ptp_tx_skb; + struct igc_tx_timestamp_request tx_tstamp[IGC_MAX_TX_TSTAMP_REGS]; struct hwtstamp_config tstamp_config; - unsigned long ptp_tx_start; unsigned int ptp_flags; /* System time value lock */ spinlock_t tmreg_lock; @@ -455,6 +465,10 @@ enum igc_tx_flags { /* olinfo flags */ IGC_TX_FLAGS_IPV4 = 0x10, IGC_TX_FLAGS_CSUM = 0x20, + + IGC_TX_FLAGS_TSTAMP_1 = 0x100, + IGC_TX_FLAGS_TSTAMP_2 = 0x200, + IGC_TX_FLAGS_TSTAMP_3 = 0x400, }; enum igc_boards { diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h index 9f3827eda157..f7d6491d4c60 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.h +++ b/drivers/net/ethernet/intel/igc/igc_base.h @@ -34,6 +34,9 @@ struct igc_adv_tx_context_desc { /* Adv Transmit Descriptor Config Masks */ #define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ +#define IGC_ADVTXD_TSTAMP_REG_1 0x00010000 /* Select register 1 for timestamp */ +#define IGC_ADVTXD_TSTAMP_REG_2 0x00020000 /* Select register 2 for timestamp */ +#define IGC_ADVTXD_TSTAMP_REG_3 0x00030000 /* Select register 3 for timestamp */ #define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ #define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 2f780cc90883..700827bdd626 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -454,6 +454,9 @@ /* Time Sync Transmit Control bit definitions */ #define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */ +#define IGC_TSYNCTXCTL_TXTT_1 0x00000002 /* Tx timestamp reg 1 valid */ +#define IGC_TSYNCTXCTL_TXTT_2 0x00000004 /* Tx timestamp reg 2 valid */ +#define IGC_TSYNCTXCTL_TXTT_3 0x00000008 /* Tx timestamp reg 3 valid */ #define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ #define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ #define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ @@ -461,6 +464,10 @@ #define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ #define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */ +#define IGC_TSYNCTXCTL_TXTT_ANY ( \ + IGC_TSYNCTXCTL_TXTT_0 | IGC_TSYNCTXCTL_TXTT_1 | \ + IGC_TSYNCTXCTL_TXTT_2 | IGC_TSYNCTXCTL_TXTT_3) + /* Timer selection bits */ #define IGC_AUX_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for auxiliary time stamp */ #define IGC_AUX_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for auxiliary time stamp */ diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index e7701866d8b4..293b45717683 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -1271,10 +1271,21 @@ static u32 igc_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSO, (IGC_ADVTXD_DCMD_TSE)); - /* set timestamp bit if present */ + /* set timestamp bit if present, will select the register set + * based on the _TSTAMP(_X) bit. + */ cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP, (IGC_ADVTXD_MAC_TSTAMP)); + cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_1, + (IGC_ADVTXD_TSTAMP_REG_1)); + + cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_2, + (IGC_ADVTXD_TSTAMP_REG_2)); + + cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_3, + (IGC_ADVTXD_TSTAMP_REG_3)); + /* insert frame checksum */ cmd_type ^= IGC_SET_FLAG(skb->no_fcs, 1, IGC_ADVTXD_DCMD_IFCS); @@ -1533,6 +1544,26 @@ static int igc_tso(struct igc_ring *tx_ring, return 1; } +static bool igc_request_tx_tstamp(struct igc_adapter *adapter, struct sk_buff *skb, u32 *flags) +{ + int i; + + for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) { + struct igc_tx_timestamp_request *tstamp = &adapter->tx_tstamp[i]; + + if (tstamp->skb) + continue; + + tstamp->skb = skb_get(skb); + tstamp->start = jiffies; + *flags = tstamp->flags; + + return true; + } + + return false; +} + static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, struct igc_ring *tx_ring) { @@ -1614,14 +1645,12 @@ done: * timestamping request. */ unsigned long flags; + u32 tstamp_flags; spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - if (!adapter->ptp_tx_skb) { + if (igc_request_tx_tstamp(adapter, skb, &tstamp_flags)) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - tx_flags |= IGC_TX_FLAGS_TSTAMP; - - adapter->ptp_tx_skb = skb_get(skb); - adapter->ptp_tx_start = jiffies; + tx_flags |= IGC_TX_FLAGS_TSTAMP | tstamp_flags; } else { adapter->tx_hwtstamp_skipped++; } diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index f0b979a70655..928f38792203 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -558,11 +558,16 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter) static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter) { unsigned long flags; + int i; spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - dev_kfree_skb_any(adapter->ptp_tx_skb); - adapter->ptp_tx_skb = NULL; + for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) { + struct igc_tx_timestamp_request *tstamp = &adapter->tx_tstamp[i]; + + dev_kfree_skb_any(tstamp->skb); + tstamp->skb = NULL; + } spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } @@ -659,61 +664,106 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, } /* Requires adapter->ptp_tx_lock held by caller. */ -static void igc_ptp_tx_timeout(struct igc_adapter *adapter) +static void igc_ptp_tx_timeout(struct igc_adapter *adapter, + struct igc_tx_timestamp_request *tstamp) { - struct igc_hw *hw = &adapter->hw; - - dev_kfree_skb_any(adapter->ptp_tx_skb); - adapter->ptp_tx_skb = NULL; + dev_kfree_skb_any(tstamp->skb); + tstamp->skb = NULL; adapter->tx_hwtstamp_timeouts++; - /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */ - rd32(IGC_TXSTMPH); + netdev_warn(adapter->netdev, "Tx timestamp timeout\n"); } void igc_ptp_tx_hang(struct igc_adapter *adapter) { + struct igc_tx_timestamp_request *tstamp; + struct igc_hw *hw = &adapter->hw; unsigned long flags; + bool found = false; + int i; spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - if (!adapter->ptp_tx_skb) - goto unlock; + for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) { + tstamp = &adapter->tx_tstamp[i]; + + if (!tstamp->skb) + continue; - if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT)) - goto unlock; + if (time_is_after_jiffies(tstamp->start + IGC_PTP_TX_TIMEOUT)) + continue; - igc_ptp_tx_timeout(adapter); + igc_ptp_tx_timeout(adapter, tstamp); + found = true; + } + + if (found) { + /* Reading the high register of the first set of timestamp registers + * clears all the equivalent bits in the TSYNCTXCTL register. + */ + rd32(IGC_TXSTMPH_0); + } -unlock: spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } +static void igc_ptp_tx_reg_to_stamp(struct igc_adapter *adapter, + struct igc_tx_timestamp_request *tstamp, u64 regval) +{ + struct skb_shared_hwtstamps shhwtstamps; + struct sk_buff *skb; + int adjust = 0; + + skb = tstamp->skb; + if (!skb) + return; + + if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval)) + return; + + switch (adapter->link_speed) { + case SPEED_10: + adjust = IGC_I225_TX_LATENCY_10; + break; + case SPEED_100: + adjust = IGC_I225_TX_LATENCY_100; + break; + case SPEED_1000: + adjust = IGC_I225_TX_LATENCY_1000; + break; + case SPEED_2500: + adjust = IGC_I225_TX_LATENCY_2500; + break; + } + + shhwtstamps.hwtstamp = + ktime_add_ns(shhwtstamps.hwtstamp, adjust); + + tstamp->skb = NULL; + + skb_tstamp_tx(skb, &shhwtstamps); + dev_kfree_skb_any(skb); +} + /** * igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp * @adapter: Board private structure * - * If we were asked to do hardware stamping and such a time stamp is - * available, then it must have been for this skb here because we only - * allow only one such packet into the queue. + * Check against the ready mask for which of the timestamp register + * sets are ready to be retrieved, then retrieve that and notify the + * rest of the stack. * * Context: Expects adapter->ptp_tx_lock to be held by caller. */ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) { - struct sk_buff *skb = adapter->ptp_tx_skb; - struct skb_shared_hwtstamps shhwtstamps; struct igc_hw *hw = &adapter->hw; - u32 tsynctxctl; - int adjust = 0; u64 regval; + u32 mask; + int i; - if (WARN_ON_ONCE(!skb)) - return; - - tsynctxctl = rd32(IGC_TSYNCTXCTL); - tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0; - if (tsynctxctl) { + mask = rd32(IGC_TSYNCTXCTL) & IGC_TSYNCTXCTL_TXTT_ANY; + if (mask & IGC_TSYNCTXCTL_TXTT_0) { regval = rd32(IGC_TXSTMPL); regval |= (u64)rd32(IGC_TXSTMPH) << 32; } else { @@ -742,37 +792,30 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) txstmpl_new = rd32(IGC_TXSTMPL); if (txstmpl_old == txstmpl_new) - return; + goto done; regval = txstmpl_new; regval |= (u64)rd32(IGC_TXSTMPH) << 32; } - if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval)) - return; - switch (adapter->link_speed) { - case SPEED_10: - adjust = IGC_I225_TX_LATENCY_10; - break; - case SPEED_100: - adjust = IGC_I225_TX_LATENCY_100; - break; - case SPEED_1000: - adjust = IGC_I225_TX_LATENCY_1000; - break; - case SPEED_2500: - adjust = IGC_I225_TX_LATENCY_2500; - break; - } + igc_ptp_tx_reg_to_stamp(adapter, &adapter->tx_tstamp[0], regval); - shhwtstamps.hwtstamp = - ktime_add_ns(shhwtstamps.hwtstamp, adjust); +done: + /* Now that the problematic first register was handled, we can + * use retrieve the timestamps from the other registers + * (starting from '1') with less complications. + */ + for (i = 1; i < IGC_MAX_TX_TSTAMP_REGS; i++) { + struct igc_tx_timestamp_request *tstamp = &adapter->tx_tstamp[i]; - adapter->ptp_tx_skb = NULL; + if (!(tstamp->mask & mask)) + continue; - /* Notify the stack and free the skb after we've unlocked */ - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); + regval = rd32(tstamp->regl); + regval |= (u64)rd32(tstamp->regh) << 32; + + igc_ptp_tx_reg_to_stamp(adapter, tstamp, regval); + } } /** @@ -788,12 +831,8 @@ void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter) spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - if (!adapter->ptp_tx_skb) - goto unlock; - igc_ptp_tx_hwtstamp(adapter); -unlock: spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } @@ -1006,9 +1045,34 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp, void igc_ptp_init(struct igc_adapter *adapter) { struct net_device *netdev = adapter->netdev; + struct igc_tx_timestamp_request *tstamp; struct igc_hw *hw = &adapter->hw; int i; + tstamp = &adapter->tx_tstamp[0]; + tstamp->mask = IGC_TSYNCTXCTL_TXTT_0; + tstamp->regl = IGC_TXSTMPL_0; + tstamp->regh = IGC_TXSTMPH_0; + tstamp->flags = 0; + + tstamp = &adapter->tx_tstamp[1]; + tstamp->mask = IGC_TSYNCTXCTL_TXTT_1; + tstamp->regl = IGC_TXSTMPL_1; + tstamp->regh = IGC_TXSTMPH_1; + tstamp->flags = IGC_TX_FLAGS_TSTAMP_1; + + tstamp = &adapter->tx_tstamp[2]; + tstamp->mask = IGC_TSYNCTXCTL_TXTT_2; + tstamp->regl = IGC_TXSTMPL_2; + tstamp->regh = IGC_TXSTMPH_2; + tstamp->flags = IGC_TX_FLAGS_TSTAMP_2; + + tstamp = &adapter->tx_tstamp[3]; + tstamp->mask = IGC_TSYNCTXCTL_TXTT_3; + tstamp->regl = IGC_TXSTMPL_3; + tstamp->regh = IGC_TXSTMPH_3; + tstamp->flags = IGC_TX_FLAGS_TSTAMP_3; + switch (hw->mac.type) { case igc_i225: for (i = 0; i < IGC_N_SDP; i++) { diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index dba5a5759b1c..20e17f5fbce3 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h @@ -243,6 +243,18 @@ #define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */ #define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */ +/* TX Timestamp Low */ +#define IGC_TXSTMPL_0 0x0B618 +#define IGC_TXSTMPL_1 0x0B698 +#define IGC_TXSTMPL_2 0x0B6B8 +#define IGC_TXSTMPL_3 0x0B6D8 + +/* TX Timestamp High */ +#define IGC_TXSTMPH_0 0x0B61C +#define IGC_TXSTMPH_1 0x0B69C +#define IGC_TXSTMPH_2 0x0B6BC +#define IGC_TXSTMPH_3 0x0B6DC + #define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ #define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ -- cgit From 6b8aa753a9f93c835abc140e5e33db136322d428 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Thu, 20 Jul 2023 06:48:35 +0300 Subject: igc: Decrease PTM short interval from 10 us to 1 us With the 10us interval, we were seeing PTM transactions take around 12us. Hardware team suggested this interval could be lowered to 1us which was confirmed with PCIe sniffer. With the 1us interval, PTM dialogs took around 2us. Suggested-by: Vinicius Costa Gomes Signed-off-by: Sasha Neftin Tested-by: Muhammad Husaini Zulkifli Reviewed-by: Muhammad Husaini Zulkifli Tested-by: Naama Meir Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igc/igc_defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 700827bdd626..b3037016f31d 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -556,7 +556,7 @@ #define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x3f) << 2) #define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8) -#define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */ +#define IGC_PTM_SHORT_CYC_DEFAULT 1 /* Default short cycle interval */ #define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */ #define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */ -- cgit From 1fe4f45ea461986a3213e78e00631beede3a12c2 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 18 Jul 2023 19:28:57 +0300 Subject: e1000e: Add support for the next LOM generation Add devices IDs for the next LOM generations that will be available on the next Intel Client platforms. This patch provides the initial support for these devices. Signed-off-by: Sasha Neftin Tested-by: Naama Meir Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/e1000e/ethtool.c | 2 ++ drivers/net/ethernet/intel/e1000e/hw.h | 3 +++ drivers/net/ethernet/intel/e1000e/ich8lan.c | 7 +++++++ drivers/net/ethernet/intel/e1000e/netdev.c | 4 ++++ drivers/net/ethernet/intel/e1000e/ptp.c | 1 + 5 files changed, 17 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 721f86fd5802..9835e6a90d56 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -917,6 +917,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: mask |= BIT(18); break; default: @@ -1585,6 +1586,7 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: fext_nvm11 = er32(FEXTNVM11); fext_nvm11 &= ~E1000_FEXTNVM11_DISABLE_MULR_FIX; ew32(FEXTNVM11, fext_nvm11); diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index 29f9fae35f42..1fef6bb5a5fb 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -122,6 +122,8 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_PTP_I219_V26 0x57B6 #define E1000_DEV_ID_PCH_PTP_I219_LM27 0x57B7 #define E1000_DEV_ID_PCH_PTP_I219_V27 0x57B8 +#define E1000_DEV_ID_PCH_NVL_I219_LM29 0x57B9 +#define E1000_DEV_ID_PCH_NVL_I219_V29 0x57BA #define E1000_REVISION_4 4 @@ -150,6 +152,7 @@ enum e1000_mac_type { e1000_pch_mtp, e1000_pch_lnp, e1000_pch_ptp, + e1000_pch_nvp, }; enum e1000_media_type { diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 0c7fd10312c8..39e9fc601bf5 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -323,6 +323,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: if (e1000_phy_is_accessible_pchlan(hw)) break; @@ -470,6 +471,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ @@ -717,6 +719,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: case e1000_pchlan: /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; @@ -1685,6 +1688,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: rc = e1000_init_phy_params_pchlan(hw); break; default: @@ -2142,6 +2146,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: @@ -3188,6 +3193,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: bank1_offset = nvm->flash_bank_size; act_offset = E1000_ICH_NVM_SIG_WORD; @@ -4129,6 +4135,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: word = NVM_COMPAT; valid_csum_mask = NVM_COMPAT_VALID_CSUM; break; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 18a5e73b8680..f536c856727c 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3545,6 +3545,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { /* Stable 24MHz frequency */ incperiod = INCPERIOD_24MHZ; @@ -4061,6 +4062,7 @@ void e1000e_reset(struct e1000_adapter *adapter) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: fc->refresh_time = 0xFFFF; fc->pause_time = 0xFFFF; @@ -7913,6 +7915,8 @@ static const struct pci_device_id e1000_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V26), board_pch_mtp }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM27), board_pch_mtp }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V27), board_pch_mtp }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_LM29), board_pch_mtp }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_V29), board_pch_mtp }, { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ }; diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c index def4566a916f..02d871bc112a 100644 --- a/drivers/net/ethernet/intel/e1000e/ptp.c +++ b/drivers/net/ethernet/intel/e1000e/ptp.c @@ -288,6 +288,7 @@ void e1000e_ptp_init(struct e1000_adapter *adapter) case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: + case e1000_pch_nvp: if ((hw->mac.type < e1000_pch_lpt) || (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { adapter->ptp_clock_info.max_adj = 24000000 - 1; -- cgit From 84a58e60038fa0366006977dba85eae16b2e3d78 Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Mon, 21 Aug 2023 16:05:54 -0700 Subject: net/mlx5: Dynamic cyclecounter shift calculation for PTP free running clock Use a dynamic calculation to determine the shift value for the internal timer cyclecounter that will lead to the highest precision frequency adjustments. Previously used a constant for the shift value assuming all devices supported by the driver had a nominal frequency of 1GHz. However, there are devices that operate at different frequencies. The previous shift value constant would break the PHC functionality for those devices. Reported-by: Vadim Fedorenko Closes: https://lore.kernel.org/netdev/20230815151507.3028503-1-vadfed@meta.com/ Fixes: 6a4010927562 ("net/mlx5: Update cyclecounter shift value to improve ptp free running mode precision") Signed-off-by: Rahul Rameshbabu Tested-by: Vadim Fedorenko Reviewed-by: Jacob Keller Reviewed-by: Simon Horman Acked-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230821230554.236210-1-rrameshbabu@nvidia.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlx5/core/lib/clock.c | 32 ++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 377372f0578a..aa29f09e8356 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -32,16 +32,13 @@ #include #include +#include #include #include #include "lib/eq.h" #include "en.h" #include "clock.h" -enum { - MLX5_CYCLES_SHIFT = 31 -}; - enum { MLX5_PIN_MODE_IN = 0x0, MLX5_PIN_MODE_OUT = 0x1, @@ -93,6 +90,31 @@ static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev) return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify); } +static u32 mlx5_ptp_shift_constant(u32 dev_freq_khz) +{ + /* Optimal shift constant leads to corrections above just 1 scaled ppm. + * + * Two sets of equations are needed to derive the optimal shift + * constant for the cyclecounter. + * + * dev_freq_khz * 1000 / 2^shift_constant = 1 scaled_ppm + * ppb = scaled_ppm * 1000 / 2^16 + * + * Using the two equations together + * + * dev_freq_khz * 1000 / 1 scaled_ppm = 2^shift_constant + * dev_freq_khz * 2^16 / 1 ppb = 2^shift_constant + * dev_freq_khz = 2^(shift_constant - 16) + * + * then yields + * + * shift_constant = ilog2(dev_freq_khz) + 16 + */ + + return min(ilog2(dev_freq_khz) + 16, + ilog2((U32_MAX / NSEC_PER_MSEC) * dev_freq_khz)); +} + static s32 mlx5_ptp_getmaxphase(struct ptp_clock_info *ptp) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); @@ -909,7 +931,7 @@ static void mlx5_timecounter_init(struct mlx5_core_dev *mdev) dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); timer->cycles.read = read_internal_timer; - timer->cycles.shift = MLX5_CYCLES_SHIFT; + timer->cycles.shift = mlx5_ptp_shift_constant(dev_freq); timer->cycles.mult = clocksource_khz2mult(dev_freq, timer->cycles.shift); timer->nominal_c_mult = timer->cycles.mult; -- cgit From 10ea77e49c5761008d0e2bf6d30b434cbc62446d Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 15 Aug 2023 12:37:25 +1000 Subject: net/mlx5e: fix up for "net/mlx5e: Move MACsec flow steering operations to be used as core library" Recent merge had a conflict in: drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c between commit: aeb660171b06 ("net/mlx5e: fix double free in macsec_fs_tx_create_crypto_table_groups") from Linus' tree and commit: cb5ebe4896f9 ("net/mlx5e: Move MACsec flow steering operations to be used as core library") from the mlx5-next tree. This was missed and the former commit got lost, bring it back. Fixes: 3c5066c6b0a5 ("Merge branch 'mlx5-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux") Signed-off-by: Stephen Rothwell Link: https://lore.kernel.org/r/20230815123725.4ef5b7b9@canb.auug.org.au Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c index 2f2cb67717cd..4a078113e292 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c @@ -278,6 +278,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5_macsec_flow_table if (!in) { kfree(ft->g); + ft->g = NULL; return -ENOMEM; } -- cgit From d55595f04dcc8bd6f6ff33f451dda8de3f1232da Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:28 +0800 Subject: net: pcs: xpcs: add specific vendor supoprt for Wangxun 10Gb NICs Since Wangxun 10Gb NICs require some special configuration on the IP of Synopsys Designware XPCS, introduce dev_flag for different vendors. Read OUI from device identifier registers, to detect Wangxun devices. And xpcs_soft_reset() is skipped to avoid the reset of device identifier registers. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/pcs/pcs-xpcs.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 44b037646865..8b56b2f9f24d 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -238,6 +238,29 @@ static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val) return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val); } +static int xpcs_dev_flag(struct dw_xpcs *xpcs) +{ + int ret, oui; + + ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID1); + if (ret < 0) + return ret; + + oui = ret; + + ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID2); + if (ret < 0) + return ret; + + ret = (ret >> 10) & 0x3F; + oui |= ret << 16; + + if (oui == DW_OUI_WX) + xpcs->dev_flag = DW_DEV_TXGBE; + + return 0; +} + static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev) { /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ @@ -1284,6 +1307,10 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, goto out; } + ret = xpcs_dev_flag(xpcs); + if (ret) + goto out; + xpcs->pcs.ops = &xpcs_phylink_ops; xpcs->pcs.neg_mode = true; if (compat->an_mode == DW_10GBASER) @@ -1291,9 +1318,11 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, xpcs->pcs.poll = true; - ret = xpcs_soft_reset(xpcs, compat); - if (ret) - goto out; + if (xpcs->dev_flag != DW_DEV_TXGBE) { + ret = xpcs_soft_reset(xpcs, compat); + if (ret) + goto out; + } return xpcs; } -- cgit From f629acc6f21043fdc80ae93cdafa6713888db0fd Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:29 +0800 Subject: net: pcs: xpcs: support to switch mode for Wangxun NICs According to chapter 6 of DesignWare Cores Ethernet PCS (version 3.20a) and custom design manual, add a configuration flow for switching interface mode. If the interface changes, the following setting is required: 1. wait VR_XS_PCS_DIG_STS bit(4, 2) [PSEQ_STATE] = 100b (Power-Good) 2. write SR_XS_PCS_CTRL2 to select various PCS type 3. write SR_PMA_CTRL1 and/or SR_XS_PCS_CTRL1 for link speed 4. program PMA registers 5. write VR_XS_PCS_DIG_CTRL1 bit(15) [VR_RST] = 1b (Vendor-Specific Soft Reset) 6. wait for VR_XS_PCS_DIG_CTRL1 bit(15) [VR_RST] to get cleared Only 10GBASE-R/SGMII/1000BASE-X modes are planned for the current Wangxun devices. And there is a quirk for Wangxun devices to switch mode although the interface in phylink state has not changed, since PCS will change to default 10GBASE-R when the ethernet driver(txgbe) do LAN reset. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/pcs/Makefile | 2 +- drivers/net/pcs/pcs-xpcs-wx.c | 208 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/pcs/pcs-xpcs.c | 13 ++- drivers/net/pcs/pcs-xpcs.h | 8 ++ 4 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 drivers/net/pcs/pcs-xpcs-wx.c (limited to 'drivers/net') diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile index ea662a7989b2..fb1694192ae6 100644 --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for Linux PCS drivers -pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-nxp.o +pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-nxp.o pcs-xpcs-wx.o obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o diff --git a/drivers/net/pcs/pcs-xpcs-wx.c b/drivers/net/pcs/pcs-xpcs-wx.c new file mode 100644 index 000000000000..1f228d5a1398 --- /dev/null +++ b/drivers/net/pcs/pcs-xpcs-wx.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#include +#include +#include "pcs-xpcs.h" + +/* VR_XS_PMA_MMD */ +#define TXGBE_PMA_MMD 0x8020 +#define TXGBE_TX_GENCTL1 0x11 +#define TXGBE_TX_GENCTL1_VBOOST_LVL GENMASK(10, 8) +#define TXGBE_TX_GENCTL1_VBOOST_EN0 BIT(4) +#define TXGBE_TX_GEN_CTL2 0x12 +#define TXGBE_TX_GEN_CTL2_TX0_WIDTH(v) FIELD_PREP(GENMASK(9, 8), v) +#define TXGBE_TX_RATE_CTL 0x14 +#define TXGBE_TX_RATE_CTL_TX0_RATE(v) FIELD_PREP(GENMASK(2, 0), v) +#define TXGBE_RX_GEN_CTL2 0x32 +#define TXGBE_RX_GEN_CTL2_RX0_WIDTH(v) FIELD_PREP(GENMASK(9, 8), v) +#define TXGBE_RX_GEN_CTL3 0x33 +#define TXGBE_RX_GEN_CTL3_LOS_TRSHLD0 GENMASK(2, 0) +#define TXGBE_RX_RATE_CTL 0x34 +#define TXGBE_RX_RATE_CTL_RX0_RATE(v) FIELD_PREP(GENMASK(1, 0), v) +#define TXGBE_RX_EQ_ATTN_CTL 0x37 +#define TXGBE_RX_EQ_ATTN_LVL0 GENMASK(2, 0) +#define TXGBE_RX_EQ_CTL0 0x38 +#define TXGBE_RX_EQ_CTL0_VGA1_GAIN(v) FIELD_PREP(GENMASK(15, 12), v) +#define TXGBE_RX_EQ_CTL0_VGA2_GAIN(v) FIELD_PREP(GENMASK(11, 8), v) +#define TXGBE_RX_EQ_CTL0_CTLE_POLE(v) FIELD_PREP(GENMASK(7, 5), v) +#define TXGBE_RX_EQ_CTL0_CTLE_BOOST(v) FIELD_PREP(GENMASK(4, 0), v) +#define TXGBE_RX_EQ_CTL4 0x3C +#define TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0 BIT(4) +#define TXGBE_RX_EQ_CTL4_CONT_ADAPT0 BIT(0) +#define TXGBE_AFE_DFE_ENABLE 0x3D +#define TXGBE_DFE_EN_0 BIT(4) +#define TXGBE_AFE_EN_0 BIT(0) +#define TXGBE_DFE_TAP_CTL0 0x3E +#define TXGBE_MPLLA_CTL0 0x51 +#define TXGBE_MPLLA_CTL2 0x53 +#define TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN BIT(10) +#define TXGBE_MPLLA_CTL2_DIV10_CLK_EN BIT(9) +#define TXGBE_MPLLA_CTL3 0x57 +#define TXGBE_MISC_CTL0 0x70 +#define TXGBE_MISC_CTL0_PLL BIT(15) +#define TXGBE_MISC_CTL0_CR_PARA_SEL BIT(14) +#define TXGBE_MISC_CTL0_RX_VREF(v) FIELD_PREP(GENMASK(12, 8), v) +#define TXGBE_VCO_CAL_LD0 0x72 +#define TXGBE_VCO_CAL_REF0 0x76 + +static int txgbe_read_pma(struct dw_xpcs *xpcs, int reg) +{ + return xpcs_read(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg); +} + +static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val) +{ + return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val); +} + +static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs) +{ + int val; + + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21); + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0); + val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1); + val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL); + txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val); + txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL | + TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF)); + txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549); + txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x29); + txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, 0); + txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, 0); + txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(3)); + txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(3)); + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN | + TXGBE_MPLLA_CTL2_DIV10_CLK_EN); + + txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) | + TXGBE_RX_EQ_CTL0_CTLE_BOOST(5)); + val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL); + val &= ~TXGBE_RX_EQ_ATTN_LVL0; + txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val); + txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE); + val = txgbe_read_pma(xpcs, TXGBE_AFE_DFE_ENABLE); + val &= ~(TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0); + txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, val); + val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_CTL4); + val &= ~TXGBE_RX_EQ_CTL4_CONT_ADAPT0; + txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, val); +} + +static void txgbe_pma_config_1g(struct dw_xpcs *xpcs) +{ + int val; + + val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1); + val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL); + val &= ~TXGBE_TX_GENCTL1_VBOOST_EN0; + txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val); + txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL | + TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF)); + + txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) | + TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6)); + val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL); + val &= ~TXGBE_RX_EQ_ATTN_LVL0; + txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val); + txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0); + val = txgbe_read_pma(xpcs, TXGBE_RX_GEN_CTL3); + val = u16_replace_bits(val, 0x4, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0); + txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val); + + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20); + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46); + txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x540); + txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x2A); + txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, 0); + txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0); + txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, TXGBE_TX_RATE_CTL_TX0_RATE(3)); + txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, TXGBE_RX_RATE_CTL_RX0_RATE(3)); + txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(1)); + txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(1)); + txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV10_CLK_EN); +} + +static int txgbe_pcs_poll_power_up(struct dw_xpcs *xpcs) +{ + int val, ret; + + /* Wait xpcs power-up good */ + ret = read_poll_timeout(xpcs_read_vpcs, val, + (val & DW_PSEQ_ST) == DW_PSEQ_ST_GOOD, + 10000, 1000000, false, + xpcs, DW_VR_XS_PCS_DIG_STS); + if (ret < 0) + dev_err(&xpcs->mdiodev->dev, "xpcs power-up timeout\n"); + + return ret; +} + +static int txgbe_pma_init_done(struct dw_xpcs *xpcs) +{ + int val, ret; + + xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_VR_RST | DW_EN_VSMMD1); + + /* wait pma initialization done */ + ret = read_poll_timeout(xpcs_read_vpcs, val, !(val & DW_VR_RST), + 100000, 10000000, false, + xpcs, DW_VR_XS_PCS_DIG_CTRL1); + if (ret < 0) + dev_err(&xpcs->mdiodev->dev, "xpcs pma initialization timeout\n"); + + return ret; +} + +static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs) +{ + int ret; + + /* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */ + ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2); + ret &= MDIO_PCS_CTRL2_TYPE; + if (ret == MDIO_PCS_CTRL2_10GBR && + xpcs->interface != PHY_INTERFACE_MODE_10GBASER) + return true; + + return false; +} + +int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface) +{ + int val, ret; + + switch (interface) { + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + break; + default: + return 0; + } + + if (xpcs->interface == interface && !txgbe_xpcs_mode_quirk(xpcs)) + return 0; + + xpcs->interface = interface; + + ret = txgbe_pcs_poll_power_up(xpcs); + if (ret < 0) + return ret; + + if (interface == PHY_INTERFACE_MODE_10GBASER) { + xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR); + val = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1); + val |= MDIO_CTRL1_SPEED10G; + xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, val); + txgbe_pma_config_10gbaser(xpcs); + } else { + xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX); + xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, 0); + xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL1, 0); + txgbe_pma_config_1g(xpcs); + } + + return txgbe_pma_init_done(xpcs); +} diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 8b56b2f9f24d..4cd011405376 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -228,12 +228,12 @@ static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg, return xpcs_write(xpcs, dev, DW_VENDOR | reg, val); } -static int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg) +int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg) { return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg); } -static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val) +int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val) { return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val); } @@ -841,6 +841,12 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, if (!compat) return -ENODEV; + if (xpcs->dev_flag == DW_DEV_TXGBE) { + ret = txgbe_xpcs_switch_mode(xpcs, interface); + if (ret) + return ret; + } + switch (compat->an_mode) { case DW_10GBASER: break; @@ -1313,9 +1319,6 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, xpcs->pcs.ops = &xpcs_phylink_ops; xpcs->pcs.neg_mode = true; - if (compat->an_mode == DW_10GBASER) - return xpcs; - xpcs->pcs.poll = true; if (xpcs->dev_flag != DW_DEV_TXGBE) { diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 68c6b5a62088..da61ad36946c 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -15,8 +15,13 @@ /* VR_XS_PCS */ #define DW_USXGMII_RST BIT(10) #define DW_USXGMII_EN BIT(9) +#define DW_VR_XS_PCS_DIG_CTRL1 0x0000 +#define DW_VR_RST BIT(15) +#define DW_EN_VSMMD1 BIT(13) #define DW_VR_XS_PCS_DIG_STS 0x0010 #define DW_RXFIFO_ERR GENMASK(6, 5) +#define DW_PSEQ_ST GENMASK(4, 2) +#define DW_PSEQ_ST_GOOD FIELD_PREP(GENMASK(4, 2), 0x4) /* SR_MII */ #define DW_USXGMII_FULL BIT(8) @@ -106,6 +111,9 @@ int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg); int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val); +int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg); +int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val); int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs); int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs); int nxp_sja1110_2500basex_pma_config(struct dw_xpcs *xpcs); +int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface); -- cgit From 2deea43f386d5c02cd490108aa3c6d02724594f8 Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:30 +0800 Subject: net: pcs: xpcs: add 1000BASE-X AN interrupt support Enable CL37 AN complete interrupt for DW XPCS. It requires to clear the bit(0) [CL37_ANCMPLT_INTR] of VR_MII_AN_INTR_STS after AN completed. And there is a quirk for Wangxun devices to enable CL37 AN in backplane configurations because of the special hardware design. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/pcs/pcs-xpcs.c | 19 ++++++++++++++++++- drivers/net/pcs/pcs-xpcs.h | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 4cd011405376..b806a9beecde 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -755,6 +755,9 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, int ret, mdio_ctrl, adv; bool changed = 0; + if (xpcs->dev_flag == DW_DEV_TXGBE) + xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1); + /* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must * be disabled first:- * 1) VR_MII_MMD_CTRL Bit(12)[AN_ENABLE] = 0b @@ -776,6 +779,8 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, return ret; ret &= ~DW_VR_MII_PCS_MODE_MASK; + if (!xpcs->pcs.poll) + ret |= DW_VR_MII_AN_INTR_EN; ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret); if (ret < 0) return ret; @@ -1029,6 +1034,17 @@ static int xpcs_get_state_c37_1000basex(struct dw_xpcs *xpcs, if (bmsr < 0) return bmsr; + /* Clear AN complete interrupt */ + if (!xpcs->pcs.poll) { + int an_intr; + + an_intr = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS); + if (an_intr & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) { + an_intr &= ~DW_VR_MII_AN_STS_C37_ANCMPLT_INTR; + xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, an_intr); + } + } + phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); } @@ -1319,9 +1335,10 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, xpcs->pcs.ops = &xpcs_phylink_ops; xpcs->pcs.neg_mode = true; - xpcs->pcs.poll = true; if (xpcs->dev_flag != DW_DEV_TXGBE) { + xpcs->pcs.poll = true; + ret = xpcs_soft_reset(xpcs, compat); if (ret) goto out; diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index da61ad36946c..ff04f6bc00a1 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -18,6 +18,7 @@ #define DW_VR_XS_PCS_DIG_CTRL1 0x0000 #define DW_VR_RST BIT(15) #define DW_EN_VSMMD1 BIT(13) +#define DW_CL37_BP BIT(12) #define DW_VR_XS_PCS_DIG_STS 0x0010 #define DW_RXFIFO_ERR GENMASK(6, 5) #define DW_PSEQ_ST GENMASK(4, 2) @@ -80,8 +81,10 @@ #define DW_VR_MII_PCS_MODE_MASK GENMASK(2, 1) #define DW_VR_MII_PCS_MODE_C37_1000BASEX 0x0 #define DW_VR_MII_PCS_MODE_C37_SGMII 0x2 +#define DW_VR_MII_AN_INTR_EN BIT(0) /* VR_MII_AN_INTR_STS */ +#define DW_VR_MII_AN_STS_C37_ANCMPLT_INTR BIT(0) #define DW_VR_MII_AN_STS_C37_ANSGM_FD BIT(1) #define DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT 2 #define DW_VR_MII_AN_STS_C37_ANSGM_SP GENMASK(3, 2) -- cgit From 2a22b7ae2fa3b579d650c068c668fb252c49582b Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:31 +0800 Subject: net: pcs: xpcs: adapt Wangxun NICs for SGMII mode Wangxun NICs support the connection with SFP to RJ45 module. In this case, PCS need to be configured in SGMII mode. According to chapter 6.11.1 "SGMII Auto-Negitiation" of DesignWare Cores Ethernet PCS (version 3.20a) and custom design manual, do the following configuration when the interface mode is SGMII. 1. program VR_MII_AN_CTRL bit(3) [TX_CONFIG] = 1b (PHY side SGMII) 2. program VR_MII_AN_CTRL bit(8) [MII_CTRL] = 1b (8-bit MII) 3. program VR_MII_DIG_CTRL1 bit(0) [PHY_MODE_CTRL] = 1b Also CL37 AN in backplane configurations need to be enabled because of the special hardware design. Another thing to note is that PMA needs to be reconfigured before each CL37 AN configuration for SGMII, otherwise AN will fail, although we don't know why. On this device, CL37_ANSGM_STS (bit[4:1] of VR_MII_AN_INTR_STS) indicates the status received from remote link during the auto-negotiation, and self-clear after the auto-negotiation is complete. Meanwhile, CL37_ANCMPLT_INTR will be set to 1, to indicate CL37 AN is complete. So add another way to get the state for CL37 SGMII. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/pcs/pcs-xpcs-wx.c | 5 +++-- drivers/net/pcs/pcs-xpcs.c | 47 +++++++++++++++++++++++++++++++++++++++---- drivers/net/pcs/pcs-xpcs.h | 6 ++++++ 3 files changed, 52 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcs/pcs-xpcs-wx.c b/drivers/net/pcs/pcs-xpcs-wx.c index 1f228d5a1398..19c75886f070 100644 --- a/drivers/net/pcs/pcs-xpcs-wx.c +++ b/drivers/net/pcs/pcs-xpcs-wx.c @@ -162,8 +162,9 @@ static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs) /* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */ ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2); ret &= MDIO_PCS_CTRL2_TYPE; - if (ret == MDIO_PCS_CTRL2_10GBR && - xpcs->interface != PHY_INTERFACE_MODE_10GBASER) + if ((ret == MDIO_PCS_CTRL2_10GBR && + xpcs->interface != PHY_INTERFACE_MODE_10GBASER) || + xpcs->interface == PHY_INTERFACE_MODE_SGMII) return true; return false; diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index b806a9beecde..4dbc21f604f2 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -683,7 +683,10 @@ EXPORT_SYMBOL_GPL(xpcs_config_eee); static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode) { - int ret, mdio_ctrl; + int ret, mdio_ctrl, tx_conf; + + if (xpcs->dev_flag == DW_DEV_TXGBE) + xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1); /* For AN for C37 SGMII mode, the settings are :- * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case @@ -720,9 +723,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, ret |= (DW_VR_MII_PCS_MODE_C37_SGMII << DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT & DW_VR_MII_PCS_MODE_MASK); - ret |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII << - DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT & - DW_VR_MII_TX_CONFIG_MASK); + if (xpcs->dev_flag == DW_DEV_TXGBE) { + ret |= DW_VR_MII_AN_CTRL_8BIT; + /* Hardware requires it to be PHY side SGMII */ + tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII; + } else { + tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII; + } + ret |= tx_conf << DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT & + DW_VR_MII_TX_CONFIG_MASK; ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret); if (ret < 0) return ret; @@ -736,6 +745,9 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, else ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; + if (xpcs->dev_flag == DW_DEV_TXGBE) + ret |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL; + ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret); if (ret < 0) return ret; @@ -1011,6 +1023,33 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs, state->duplex = DUPLEX_FULL; else state->duplex = DUPLEX_HALF; + } else if (ret == DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) { + int speed, duplex; + + state->link = true; + + speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1); + if (speed < 0) + return speed; + + speed &= SGMII_SPEED_SS13 | SGMII_SPEED_SS6; + if (speed == SGMII_SPEED_SS6) + state->speed = SPEED_1000; + else if (speed == SGMII_SPEED_SS13) + state->speed = SPEED_100; + else if (speed == 0) + state->speed = SPEED_10; + + duplex = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_ADVERTISE); + if (duplex < 0) + return duplex; + + if (duplex & DW_FULL_DUPLEX) + state->duplex = DUPLEX_FULL; + else if (duplex & DW_HALF_DUPLEX) + state->duplex = DUPLEX_HALF; + + xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0); } return 0; diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index ff04f6bc00a1..39a90417e535 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -67,12 +67,14 @@ /* VR_MII_DIG_CTRL1 */ #define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9) +#define DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL BIT(0) /* VR_MII_DIG_CTRL2 */ #define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4) #define DW_VR_MII_DIG_CTRL2_RX_POL_INV BIT(0) /* VR_MII_AN_CTRL */ +#define DW_VR_MII_AN_CTRL_8BIT BIT(8) #define DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT 3 #define DW_VR_MII_TX_CONFIG_MASK BIT(3) #define DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII 0x1 @@ -98,6 +100,10 @@ #define SGMII_SPEED_SS13 BIT(13) /* SGMII speed along with SS6 */ #define SGMII_SPEED_SS6 BIT(6) /* SGMII speed along with SS13 */ +/* SR MII MMD AN Advertisement defines */ +#define DW_HALF_DUPLEX BIT(6) +#define DW_FULL_DUPLEX BIT(5) + /* VR MII EEE Control 0 defines */ #define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */ #define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */ -- cgit From ab928c24e6cd9473a2f9ec04df8849cdad1ba2ca Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:32 +0800 Subject: net: txgbe: add FW version warning Since XPCS device identifier is implemented in the firmware version 0x20010 and above, so add a warning to prompt the users to upgrade the firmware to make sure the driver works. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 46eba6d6188b..641b8188da4e 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -663,6 +663,9 @@ static int txgbe_probe(struct pci_dev *pdev, "0x%08x", etrack_id); } + if (etrack_id < 0x20010) + dev_warn(&pdev->dev, "Please upgrade the firmware to 0x20010 or above.\n"); + txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL); if (!txgbe) { err = -ENOMEM; -- cgit From a4414dd13f21d4e40a29a6ba068d17e4d3090021 Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:33 +0800 Subject: net: txgbe: support switching mode to 1000BASE-X and SGMII Disable data path before PCS VR reset while switching PCS mode, to prevent the blocking of data path. Enable AN interrupt for CL37 auto-negotiation. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/libwx/wx_type.h | 2 ++ drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c | 28 ++++++++++++++++++++++++ drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h | 2 ++ drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 30 +++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 1de88a33a698..50b92cfb46a0 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -205,6 +205,8 @@ #define WX_TSC_CTL 0x1D000 #define WX_TSC_CTL_TX_DIS BIT(1) #define WX_TSC_CTL_TSEC_DIS BIT(0) +#define WX_TSC_ST 0x1D004 +#define WX_TSC_ST_SECTX_RDY BIT(0) #define WX_TSC_BUF_AE 0x1D00C #define WX_TSC_BUF_AE_THR GENMASK(9, 0) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c index 6e130d1f7a7b..90168aab11ae 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c @@ -13,6 +13,34 @@ #include "txgbe_type.h" #include "txgbe_hw.h" +/** + * txgbe_disable_sec_tx_path - Stops the transmit data path + * @wx: pointer to hardware structure + * + * Stops the transmit data path and waits for the HW to internally empty + * the tx security block + **/ +int txgbe_disable_sec_tx_path(struct wx *wx) +{ + int val; + + wr32m(wx, WX_TSC_CTL, WX_TSC_CTL_TX_DIS, WX_TSC_CTL_TX_DIS); + return read_poll_timeout(rd32, val, val & WX_TSC_ST_SECTX_RDY, + 1000, 20000, false, wx, WX_TSC_ST); +} + +/** + * txgbe_enable_sec_tx_path - Enables the transmit data path + * @wx: pointer to hardware structure + * + * Enables the transmit data path. + **/ +void txgbe_enable_sec_tx_path(struct wx *wx) +{ + wr32m(wx, WX_TSC_CTL, WX_TSC_CTL_TX_DIS, 0); + WX_WRITE_FLUSH(wx); +} + /** * txgbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds * @wx: pointer to hardware structure diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h index e82f65dff8a6..abc729eb187a 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.h @@ -4,6 +4,8 @@ #ifndef _TXGBE_HW_H_ #define _TXGBE_HW_H_ +int txgbe_disable_sec_tx_path(struct wx *wx); +void txgbe_enable_sec_tx_path(struct wx *wx); int txgbe_read_pba_string(struct wx *wx, u8 *pba_num, u32 pba_num_size); int txgbe_validate_eeprom_checksum(struct wx *wx, u16 *checksum_val); int txgbe_reset_hw(struct wx *wx); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 819d1db34643..d2124547394d 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -18,6 +18,7 @@ #include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_phy.h" +#include "txgbe_hw.h" static int txgbe_swnodes_register(struct txgbe *txgbe) { @@ -210,8 +211,32 @@ static void txgbe_mac_link_up(struct phylink_config *config, wr32(wx, WX_MAC_WDG_TIMEOUT, wdg); } +static int txgbe_mac_prepare(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + + wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); + wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0); + + return txgbe_disable_sec_tx_path(wx); +} + +static int txgbe_mac_finish(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + + txgbe_enable_sec_tx_path(wx); + wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); + + return 0; +} + static const struct phylink_mac_ops txgbe_mac_ops = { .mac_select_pcs = txgbe_phylink_mac_select, + .mac_prepare = txgbe_mac_prepare, + .mac_finish = txgbe_mac_finish, .mac_config = txgbe_mac_config, .mac_link_down = txgbe_mac_link_down, .mac_link_up = txgbe_mac_link_up, @@ -234,6 +259,8 @@ static int txgbe_phylink_init(struct txgbe *txgbe) config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; phy_mode = PHY_INTERFACE_MODE_10GBASER; __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces); fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); if (IS_ERR(phylink)) @@ -431,7 +458,8 @@ static void txgbe_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); - if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) { + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN | + TXGBE_PX_MISC_ETH_AN)) { u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); -- cgit From 02b2a6f91b9042552bc3aa728622bda97e3916fa Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:34 +0800 Subject: net: txgbe: support copper NIC with external PHY Wangxun SP chip supports to connect with external PHY (marvell 88x3310), which links to 10GBASE-T/1000BASE-T/100BASE-T. Add the identification of media types from subsystem device IDs. For sp_media_copper, register mdio bus for the external PHY. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/Kconfig | 1 + drivers/net/ethernet/wangxun/libwx/wx_type.h | 26 ++++ drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c | 13 +- drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 53 +++++++-- drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 150 ++++++++++++++++++++++-- 5 files changed, 221 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 39596cd13539..23cd610bd376 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -41,6 +41,7 @@ config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI depends on COMMON_CLK + select MARVELL_10G_PHY select REGMAP select I2C select I2C_DESIGNWARE_PLATFORM diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 50b92cfb46a0..c5cbd177ef62 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -233,6 +233,24 @@ #define WX_MAC_WDG_TIMEOUT 0x1100C #define WX_MAC_RX_FLOW_CTRL 0x11090 #define WX_MAC_RX_FLOW_CTRL_RFE BIT(0) /* receive fc enable */ +/* MDIO Registers */ +#define WX_MSCA 0x11200 +#define WX_MSCA_RA(v) FIELD_PREP(U16_MAX, v) +#define WX_MSCA_PA(v) FIELD_PREP(GENMASK(20, 16), v) +#define WX_MSCA_DA(v) FIELD_PREP(GENMASK(25, 21), v) +#define WX_MSCC 0x11204 +#define WX_MSCC_CMD(v) FIELD_PREP(GENMASK(17, 16), v) + +enum WX_MSCA_CMD_value { + WX_MSCA_CMD_RSV = 0, + WX_MSCA_CMD_WRITE, + WX_MSCA_CMD_POST_READ, + WX_MSCA_CMD_READ, +}; + +#define WX_MSCC_SADDR BIT(18) +#define WX_MSCC_BUSY BIT(22) +#define WX_MDIO_CLK(v) FIELD_PREP(GENMASK(21, 19), v) #define WX_MMC_CONTROL 0x11800 #define WX_MMC_CONTROL_RSTONRD BIT(2) /* reset on read */ @@ -582,6 +600,13 @@ enum wx_mac_type { wx_mac_em }; +enum sp_media_type { + sp_media_unknown = 0, + sp_media_fiber, + sp_media_copper, + sp_media_backplane +}; + enum em_mac_type { em_mac_type_unknown = 0, em_mac_type_mdi, @@ -829,6 +854,7 @@ struct wx { struct wx_bus_info bus; struct wx_mac_info mac; enum em_mac_type mac_type; + enum sp_media_type media_type; struct wx_eeprom_info eeprom; struct wx_addr_filter_info addr_ctrl; struct wx_mac_addr *mac_table; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c index 90168aab11ae..372745250270 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c @@ -285,17 +285,20 @@ static void txgbe_reset_misc(struct wx *wx) int txgbe_reset_hw(struct wx *wx) { int status; - u32 val; /* Call adapter stop to disable tx/rx and clear interrupts */ status = wx_stop_adapter(wx); if (status != 0) return status; - val = WX_MIS_RST_LAN_RST(wx->bus.func); - wr32(wx, WX_MIS_RST, val | rd32(wx, WX_MIS_RST)); - WX_WRITE_FLUSH(wx); - usleep_range(10, 100); + if (wx->media_type != sp_media_copper) { + u32 val; + + val = WX_MIS_RST_LAN_RST(wx->bus.func); + wr32(wx, WX_MIS_RST, val | rd32(wx, WX_MIS_RST)); + WX_WRITE_FLUSH(wx); + usleep_range(10, 100); + } status = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_LAN_SW_RST(wx->bus.func)); if (status != 0) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 641b8188da4e..5c3aed516ac2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -300,6 +300,49 @@ static void txgbe_down(struct wx *wx) wx_clean_all_rx_rings(wx); } +/** + * txgbe_init_type_code - Initialize the shared code + * @wx: pointer to hardware structure + **/ +static void txgbe_init_type_code(struct wx *wx) +{ + u8 device_type = wx->subsystem_device_id & 0xF0; + + switch (wx->device_id) { + case TXGBE_DEV_ID_SP1000: + case TXGBE_DEV_ID_WX1820: + wx->mac.type = wx_mac_sp; + break; + default: + wx->mac.type = wx_mac_unknown; + break; + } + + switch (device_type) { + case TXGBE_ID_SFP: + wx->media_type = sp_media_fiber; + break; + case TXGBE_ID_XAUI: + case TXGBE_ID_SGMII: + wx->media_type = sp_media_copper; + break; + case TXGBE_ID_KR_KX_KX4: + case TXGBE_ID_MAC_XAUI: + case TXGBE_ID_MAC_SGMII: + wx->media_type = sp_media_backplane; + break; + case TXGBE_ID_SFI_XAUI: + if (wx->bus.func == 0) + wx->media_type = sp_media_fiber; + else + wx->media_type = sp_media_copper; + break; + default: + wx->media_type = sp_media_unknown; + break; + } +} + /** * txgbe_sw_init - Initialize general software structures (struct wx) * @wx: board private structure to initialize @@ -324,15 +367,7 @@ static int txgbe_sw_init(struct wx *wx) return err; } - switch (wx->device_id) { - case TXGBE_DEV_ID_SP1000: - case TXGBE_DEV_ID_WX1820: - wx->mac.type = wx_mac_sp; - break; - default: - wx->mac.type = wx_mac_unknown; - break; - } + txgbe_init_type_code(wx); /* Set common capability flags and settings */ wx->max_q_vectors = TXGBE_MAX_MSIX_VECTORS; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index d2124547394d..4159c84035fd 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -161,7 +161,10 @@ static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *confi { struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev)); - return &txgbe->xpcs->pcs; + if (interface == PHY_INTERFACE_MODE_10GBASER) + return &txgbe->xpcs->pcs; + + return NULL; } static void txgbe_mac_config(struct phylink_config *config, unsigned int mode, @@ -244,8 +247,8 @@ static const struct phylink_mac_ops txgbe_mac_ops = { static int txgbe_phylink_init(struct txgbe *txgbe) { + struct fwnode_handle *fwnode = NULL; struct phylink_config *config; - struct fwnode_handle *fwnode; struct wx *wx = txgbe->wx; phy_interface_t phy_mode; struct phylink *phylink; @@ -256,16 +259,34 @@ static int txgbe_phylink_init(struct txgbe *txgbe) config->dev = &wx->netdev->dev; config->type = PHYLINK_NETDEV; - config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; - phy_mode = PHY_INTERFACE_MODE_10GBASER; - __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces); - fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); + config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_100FD | + MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + + if (wx->media_type == sp_media_copper) { + phy_mode = PHY_INTERFACE_MODE_XAUI; + __set_bit(PHY_INTERFACE_MODE_XAUI, config->supported_interfaces); + } else { + phy_mode = PHY_INTERFACE_MODE_10GBASER; + fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); + __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces); + } + phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); if (IS_ERR(phylink)) return PTR_ERR(phylink); + if (wx->phydev) { + int ret; + + ret = phylink_connect_phy(phylink, wx->phydev); + if (ret) { + phylink_destroy(phylink); + return ret; + } + } + txgbe->phylink = phylink; return 0; @@ -626,10 +647,117 @@ static int txgbe_sfp_register(struct txgbe *txgbe) return 0; } +static int txgbe_phy_read(struct mii_bus *bus, int phy_addr, + int devnum, int regnum) +{ + struct wx *wx = bus->priv; + u32 val, command; + int ret; + + /* setup and write the address cycle command */ + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); + + command = WX_MSCC_CMD(WX_MSCA_CMD_READ) | WX_MSCC_BUSY; + wr32(wx, WX_MSCC, command); + + /* wait to complete */ + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); + if (ret) { + wx_err(wx, "Mdio read c45 command did not complete.\n"); + return ret; + } + + return (u16)rd32(wx, WX_MSCC); +} + +static int txgbe_phy_write(struct mii_bus *bus, int phy_addr, + int devnum, int regnum, u16 value) +{ + struct wx *wx = bus->priv; + int ret, command; + u16 val; + + /* setup and write the address cycle command */ + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); + + command = value | WX_MSCC_CMD(WX_MSCA_CMD_WRITE) | WX_MSCC_BUSY; + wr32(wx, WX_MSCC, command); + + /* wait to complete */ + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); + if (ret) + wx_err(wx, "Mdio write c45 command did not complete.\n"); + + return ret; +} + +static int txgbe_ext_phy_init(struct txgbe *txgbe) +{ + struct phy_device *phydev; + struct mii_bus *mii_bus; + struct pci_dev *pdev; + struct wx *wx; + int ret = 0; + + wx = txgbe->wx; + pdev = wx->pdev; + + mii_bus = devm_mdiobus_alloc(&pdev->dev); + if (!mii_bus) + return -ENOMEM; + + mii_bus->name = "txgbe_mii_bus"; + mii_bus->read_c45 = &txgbe_phy_read; + mii_bus->write_c45 = &txgbe_phy_write; + mii_bus->parent = &pdev->dev; + mii_bus->phy_mask = GENMASK(31, 1); + mii_bus->priv = wx; + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe-%x", + (pdev->bus->number << 8) | pdev->devfn); + + ret = devm_mdiobus_register(&pdev->dev, mii_bus); + if (ret) { + wx_err(wx, "failed to register MDIO bus: %d\n", ret); + return ret; + } + + phydev = phy_find_first(mii_bus); + if (!phydev) { + wx_err(wx, "no PHY found\n"); + return -ENODEV; + } + + phy_attached_info(phydev); + + wx->link = 0; + wx->speed = 0; + wx->duplex = 0; + wx->phydev = phydev; + + ret = txgbe_phylink_init(txgbe); + if (ret) { + wx_err(wx, "failed to init phylink: %d\n", ret); + return ret; + } + + return 0; +} + int txgbe_init_phy(struct txgbe *txgbe) { int ret; + if (txgbe->wx->media_type == sp_media_copper) + return txgbe_ext_phy_init(txgbe); + ret = txgbe_swnodes_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to register software nodes\n"); @@ -691,6 +819,12 @@ err_unregister_swnode: void txgbe_remove_phy(struct txgbe *txgbe) { + if (txgbe->wx->media_type == sp_media_copper) { + phylink_disconnect_phy(txgbe->phylink); + phylink_destroy(txgbe->phylink); + return; + } + platform_device_unregister(txgbe->sfp_dev); platform_device_unregister(txgbe->i2c_dev); clkdev_drop(txgbe->clock); -- cgit From ad63f7aa585ee58ebf5e83af09653134a21cd082 Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Wed, 23 Aug 2023 14:19:35 +0800 Subject: net: ngbe: move mdio access registers to libwx Registers of mdio accessing are common defined in libwx, remove the redundant macro definitions in ngbe driver. Signed-off-by: Jiawen Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c | 84 +++++++++++++-------------- drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 19 ------ 2 files changed, 42 insertions(+), 61 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c index fe20f02ecb3a..591f5b7b6da6 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c @@ -37,24 +37,24 @@ static int ngbe_phy_read_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regn wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(device_type); - wr32(wx, NGBE_MSCA, command); - command = NGBE_MSCC_CMD(NGBE_MSCA_CMD_READ) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(device_type); + wr32(wx, WX_MSCA, command); + command = WX_MSCC_CMD(WX_MSCA_CMD_READ) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) { wx_err(wx, "Mdio read c22 command did not complete.\n"); return ret; } - return (u16)rd32(wx, NGBE_MSCC); + return (u16)rd32(wx, WX_MSCC); } static int ngbe_phy_write_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regnum, u16 value) @@ -65,19 +65,19 @@ static int ngbe_phy_write_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int reg wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(device_type); - wr32(wx, NGBE_MSCA, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(device_type); + wr32(wx, WX_MSCA, command); command = value | - NGBE_MSCC_CMD(NGBE_MSCA_CMD_WRITE) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + WX_MSCC_CMD(WX_MSCA_CMD_WRITE) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) wx_err(wx, "Mdio write c22 command did not complete.\n"); @@ -92,24 +92,24 @@ static int ngbe_phy_read_reg_mdi_c45(struct mii_bus *bus, int phy_addr, int devn wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(devnum); - wr32(wx, NGBE_MSCA, command); - command = NGBE_MSCC_CMD(NGBE_MSCA_CMD_READ) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); + command = WX_MSCC_CMD(WX_MSCA_CMD_READ) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) { wx_err(wx, "Mdio read c45 command did not complete.\n"); return ret; } - return (u16)rd32(wx, NGBE_MSCC); + return (u16)rd32(wx, WX_MSCC); } static int ngbe_phy_write_reg_mdi_c45(struct mii_bus *bus, int phy_addr, @@ -121,19 +121,19 @@ static int ngbe_phy_write_reg_mdi_c45(struct mii_bus *bus, int phy_addr, wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(devnum); - wr32(wx, NGBE_MSCA, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); command = value | - NGBE_MSCC_CMD(NGBE_MSCA_CMD_WRITE) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + WX_MSCC_CMD(WX_MSCA_CMD_WRITE) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) wx_err(wx, "Mdio write c45 command did not complete.\n"); diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h index b70eca397b67..72c8cd2d5575 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h @@ -59,25 +59,6 @@ #define NGBE_EEPROM_VERSION_L 0x1D #define NGBE_EEPROM_VERSION_H 0x1E -/* mdio access */ -#define NGBE_MSCA 0x11200 -#define NGBE_MSCA_RA(v) FIELD_PREP(U16_MAX, v) -#define NGBE_MSCA_PA(v) FIELD_PREP(GENMASK(20, 16), v) -#define NGBE_MSCA_DA(v) FIELD_PREP(GENMASK(25, 21), v) -#define NGBE_MSCC 0x11204 -#define NGBE_MSCC_CMD(v) FIELD_PREP(GENMASK(17, 16), v) - -enum NGBE_MSCA_CMD_value { - NGBE_MSCA_CMD_RSV = 0, - NGBE_MSCA_CMD_WRITE, - NGBE_MSCA_CMD_POST_READ, - NGBE_MSCA_CMD_READ, -}; - -#define NGBE_MSCC_SADDR BIT(18) -#define NGBE_MSCC_BUSY BIT(22) -#define NGBE_MDIO_CLK(v) FIELD_PREP(GENMASK(21, 19), v) - /* Media-dependent registers. */ #define NGBE_MDIO_CLAUSE_SELECT 0x11220 -- cgit From 1e4134610d93271535ecf900a676e1f094e9944c Mon Sep 17 00:00:00 2001 From: Wang Ming Date: Thu, 13 Jul 2023 11:03:44 +0800 Subject: wifi: ath9k: use IS_ERR() with debugfs_create_dir() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The debugfs_create_dir() function returns error pointers, it never returns NULL. Most incorrect error checks were fixed, but the one in ath9k_htc_init_debug() was forgotten. Fix the remaining error check. Fixes: e5facc75fa91 ("ath9k_htc: Cleanup HTC debugfs") Signed-off-by: Wang Ming Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230713030358.12379-1-machel@vivo.com --- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 1ed2b1216bce..c549ff3abcdc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -486,7 +486,7 @@ int ath9k_htc_init_debug(struct ath_hw *ah) priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, priv->hw->wiphy->debugfsdir); - if (!priv->debug.debugfs_phy) + if (IS_ERR(priv->debug.debugfs_phy)) return -ENOMEM; ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy); -- cgit From 2f5124e86ae74b7ba24c9ae2644107b750cbf38f Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 9 Aug 2023 04:16:57 -0400 Subject: wifi: ath12k: add check max message length while scanning with extraie Currently the extraie length is directly used to allocate skb buffer. When the length of skb is greater than the max message length which firmware supports, error will happen in firmware side. Hence add check for the skb length and drop extraie when overflow and print a message. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Wen Gong Reviewed-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230809081657.13858-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index cc9a377c06fd..ef0f3cf35cfd 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -2239,12 +2239,6 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar, if (arg->num_bssid) len += sizeof(*bssid) * arg->num_bssid; - len += TLV_HDR_SIZE; - if (arg->extraie.len) - extraie_len_with_pad = - roundup(arg->extraie.len, sizeof(u32)); - len += extraie_len_with_pad; - if (arg->num_hint_bssid) len += TLV_HDR_SIZE + arg->num_hint_bssid * sizeof(*hint_bssid); @@ -2253,6 +2247,18 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar, len += TLV_HDR_SIZE + arg->num_hint_s_ssid * sizeof(*s_ssid); + len += TLV_HDR_SIZE; + if (arg->extraie.len) + extraie_len_with_pad = + roundup(arg->extraie.len, sizeof(u32)); + if (extraie_len_with_pad <= (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len)) { + len += extraie_len_with_pad; + } else { + ath12k_warn(ar->ab, "discard large size %d bytes extraie for scan start\n", + arg->extraie.len); + extraie_len_with_pad = 0; + } + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) return -ENOMEM; @@ -2342,7 +2348,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar, tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len); ptr += TLV_HDR_SIZE; - if (arg->extraie.len) + if (extraie_len_with_pad) memcpy(ptr, arg->extraie.ptr, arg->extraie.len); -- cgit From 0e5b1b46925b005bd4f701a116d06a561c7262e8 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Wed, 16 Aug 2023 21:05:50 +0800 Subject: wifi: ath12k: Remove unused declarations Commit d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") declared but never implemented these, remove it. Signed-off-by: Yue Haibing Acked-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816130550.50896-1-yuehaibing@huawei.com --- drivers/net/wireless/ath/ath12k/ce.h | 3 --- drivers/net/wireless/ath/ath12k/core.h | 1 - drivers/net/wireless/ath/ath12k/qmi.h | 2 -- drivers/net/wireless/ath/ath12k/wmi.h | 2 -- 4 files changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h index 17cf16235e0b..79af3b6159f1 100644 --- a/drivers/net/wireless/ath/ath12k/ce.h +++ b/drivers/net/wireless/ath/ath12k/ce.h @@ -176,9 +176,6 @@ int ath12k_ce_alloc_pipes(struct ath12k_base *ab); void ath12k_ce_free_pipes(struct ath12k_base *ab); int ath12k_ce_get_attr_flags(struct ath12k_base *ab, int ce_id); void ath12k_ce_poll_send_completed(struct ath12k_base *ab, u8 pipe_id); -int ath12k_ce_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe); -int ath12k_ce_attr_attach(struct ath12k_base *ab); void ath12k_ce_get_shadow_config(struct ath12k_base *ab, u32 **shadow_cfg, u32 *shadow_cfg_len); #endif diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 4389ff40b49d..d873b573dac6 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -788,7 +788,6 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab, int ath12k_core_fetch_bdf(struct ath12k_base *ath12k, struct ath12k_board_data *bd); void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd); -int ath12k_core_check_dt(struct ath12k_base *ath12k); void ath12k_core_halt(struct ath12k *ar); int ath12k_core_resume(struct ath12k_base *ab); diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index df76149c49f5..15944f5f33ab 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -562,8 +562,6 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 { int ath12k_qmi_firmware_start(struct ath12k_base *ab, u32 mode); void ath12k_qmi_firmware_stop(struct ath12k_base *ab); -void ath12k_qmi_event_work(struct work_struct *work); -void ath12k_qmi_msg_recv_work(struct work_struct *work); void ath12k_qmi_deinit_service(struct ath12k_base *ab); int ath12k_qmi_init_service(struct ath12k_base *ab); diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 8c047a9623f9..c75a6fa1f7e0 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -4855,8 +4855,6 @@ int ath12k_wmi_vdev_install_key(struct ath12k *ar, struct wmi_vdev_install_key_arg *arg); int ath12k_wmi_pdev_bss_chan_info_request(struct ath12k *ar, enum wmi_bss_chan_info_req_type type); -int ath12k_wmi_send_stats_request_cmd(struct ath12k *ar, u32 stats_id, - u32 vdev_id, u32 pdev_id); int ath12k_wmi_send_pdev_temperature_cmd(struct ath12k *ar); int ath12k_wmi_send_peer_flush_tids_cmd(struct ath12k *ar, u8 peer_addr[ETH_ALEN], -- cgit From 4c2964ef553b9c7c4ae1803158386a8b169f8f4e Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 14 Aug 2023 20:42:11 +0800 Subject: wifi: ath: Use is_multicast_ether_addr() to check multicast Ether address Use is_multicast_ether_addr() to perform the Checking. Signed-off-by: Ruan Jinjie Reviewed-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230814124212.302738-2-ruanjinjie@huawei.com --- drivers/net/wireless/ath/key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index b7b61d4f02ba..21a93fec284d 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -104,7 +104,7 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) * Not setting this bit allows the hardware to use the key * for multicast frame decryption. */ - if (mac[0] & 0x01) + if (is_multicast_ether_addr(mac)) unicast_flag = 0; macLo = get_unaligned_le32(mac); -- cgit From 0aacec49c29e7c5b1487e859b0c0a42388c34092 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 23 Aug 2023 08:18:14 -0700 Subject: ice: avoid executing commands on other ports when driving sync The ice hardware has a synchronization mechanism used to drive the simultaneous application of commands on both PHY ports and the source timer in the MAC. When issuing a sync via ice_ptp_exec_tmr_cmd(), the hardware will simultaneously apply the commands programmed for the main timer and each PHY port. Neither the main timer command register, nor the PHY port command registers auto clear on command execution. During the execution of a timer command intended for a single port on E822 devices, such as those used to configure a PHY during link up, the driver is not correctly clearing the previous commands. This results in unintentionally executing the last programmed command on the main timer and other PHY ports whenever performing reconfiguration on E822 ports after link up. This results in unintended side effects on other timers, depending on what command was previously programmed. To fix this, the driver must ensure that the main timer and all other PHY ports are properly initialized to perform no action. The enumeration for timer commands does not include an enumeration value for doing nothing. Introduce ICE_PTP_NOP for this purpose. When writing a timer command to hardware, leave the command bits set to zero which indicates that no operation should be performed on that port. Modify ice_ptp_one_port_cmd() to always initialize all ports. For all ports other than the one being configured, write their timer command register to ICE_PTP_NOP. This ensures that no side effect happens on the timer command. To fix this for the PHY ports, modify ice_ptp_one_port_cmd() to always initialize all other ports to ICE_PTP_NOP. This ensures that no side effects happen on the other ports. Call ice_ptp_src_cmd() with a command value if ICE_PTP_NOP in ice_sync_phy_timer_e822() and ice_start_phy_timer_e822(). With both of these changes, the driver should no longer execute a stale command on the main timer or another PHY port when reconfiguring one of the PHY ports after link up. Fixes: 3a7496234d17 ("ice: implement basic E822 PTP support") Signed-off-by: Siddaraju DH Signed-off-by: Jacob Keller Tested-by: Sunitha Mekala (A Contingent worker at Intel) Signed-off-by: Tony Nguyen Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 55 ++++++++++++++++++++++++++--- drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 3 +- 2 files changed, 52 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index a38614d21ea8..de1d83300481 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -131,6 +131,8 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case READ_TIME: cmd_val |= GLTSYN_CMD_READ_TIME; break; + case ICE_PTP_NOP: + break; } wr32(hw, GLTSYN_CMD, cmd_val); @@ -1226,18 +1228,18 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) } /** - * ice_ptp_one_port_cmd - Prepare a single PHY port for a timer command + * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command * @hw: pointer to HW struct * @port: Port to which cmd has to be sent * @cmd: Command to be sent to the port * * Prepare the requested port for an upcoming timer sync command. * - * Note there is no equivalent of this operation on E810, as that device - * always handles all external PHYs internally. + * Do not use this function directly. If you want to configure exactly one + * port, use ice_ptp_one_port_cmd() instead. */ static int -ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) +ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) { u32 cmd_val, val; u8 tmr_idx; @@ -1261,6 +1263,8 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME; break; + case ICE_PTP_NOP: + break; } /* Tx case */ @@ -1306,6 +1310,39 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) return 0; } +/** + * ice_ptp_one_port_cmd - Prepare one port for a timer command + * @hw: pointer to the HW struct + * @configured_port: the port to configure with configured_cmd + * @configured_cmd: timer command to prepare on the configured_port + * + * Prepare the configured_port for the configured_cmd, and prepare all other + * ports for ICE_PTP_NOP. This causes the configured_port to execute the + * desired command while all other ports perform no operation. + */ +static int +ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + enum ice_ptp_tmr_cmd configured_cmd) +{ + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + enum ice_ptp_tmr_cmd cmd; + int err; + + if (port == configured_port) + cmd = configured_cmd; + else + cmd = ICE_PTP_NOP; + + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); + if (err) + return err; + } + + return 0; +} + /** * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command * @hw: pointer to the HW struct @@ -1322,7 +1359,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { int err; - err = ice_ptp_one_port_cmd(hw, port, cmd); + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); if (err) return err; } @@ -2252,6 +2289,9 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) goto err_unlock; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + /* Issue the sync to activate the time adjustment */ ice_ptp_exec_tmr_cmd(hw); @@ -2372,6 +2412,9 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) return err; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + ice_ptp_exec_tmr_cmd(hw); err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); @@ -2847,6 +2890,8 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val = GLTSYN_CMD_ADJ_INIT_TIME; break; + case ICE_PTP_NOP: + return 0; } /* Read, modify, write */ diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 3b68cb91bd81..096685237ca6 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -9,7 +9,8 @@ enum ice_ptp_tmr_cmd { INIT_INCVAL, ADJ_TIME, ADJ_TIME_AT_TIME, - READ_TIME + READ_TIME, + ICE_PTP_NOP, }; enum ice_ptp_serdes { -- cgit From 9540329452b737340960b4273600e61a6a236a78 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Thu, 24 Aug 2023 14:11:50 +0800 Subject: net: fec: add statistics for XDP_TX The FEC driver supports the statistics for XDP actions except for XDP_TX before, because the XDP_TX was not supported when adding the statistics for XDP. Now the FEC driver has supported XDP_TX since commit f601899e4321 ("net: fec: add XDP_TX feature support"). So it's reasonable and necessary to add statistics for XDP_TX. Signed-off-by: Wei Fang Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 8909899e9a31..77c8e9cfb445 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1590,9 +1590,12 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, break; case XDP_TX: + rxq->stats[RX_XDP_TX]++; err = fec_enet_xdp_tx_xmit(fep, cpu, xdp, sync); - if (unlikely(err)) + if (unlikely(err)) { + rxq->stats[RX_XDP_TX_ERRORS]++; goto xdp_err; + } ret = FEC_ENET_XDP_TX; break; -- cgit From 49fa4b0d06705a24a81bb8be6eb175059b77f0a7 Mon Sep 17 00:00:00 2001 From: Ratheesh Kannoth Date: Thu, 24 Aug 2023 08:33:01 +0530 Subject: octeontx2-pf: fix page_pool creation fail for rings > 32k octeontx2 driver calls page_pool_create() during driver probe() and fails if queue size > 32k. Page pool infra uses these buffers as shock absorbers for burst traffic. These pages are pinned down over time as working sets varies, due to the recycling nature of page pool, given page pool (currently) don't have a shrinker mechanism, the pages remain pinned down in ptr_ring. Instead of clamping page_pool size to 32k at most, limit it even more to 2k to avoid wasting memory. This have been tested on octeontx2 CN10KA hardware. TCP and UDP tests using iperf shows no performance regressions. Fixes: b2e3406a38f0 ("octeontx2-pf: Add support for page pool") Suggested-by: Alexander Lobakin Reviewed-by: Sunil Goutham Signed-off-by: Ratheesh Kannoth Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 2 +- drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 77c8f650f7ac..3e1c70c74622 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -1432,7 +1432,7 @@ int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, } pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; - pp_params.pool_size = numptrs; + pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); pp_params.nid = NUMA_NO_NODE; pp_params.dev = pfvf->dev; pp_params.dma_dir = DMA_FROM_DEVICE; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index b5d689eeff80..9e3bfbe5c480 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -23,6 +23,8 @@ #define OTX2_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN) #define OTX2_MIN_MTU 60 +#define OTX2_PAGE_POOL_SZ 2048 + #define OTX2_MAX_GSO_SEGS 255 #define OTX2_MAX_FRAGS_IN_SQE 9 -- cgit From 786c96e92fb9e854cb8b0cb7399bb2fb28e15c4b Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Thu, 24 Aug 2023 14:43:36 +0800 Subject: net: arcnet: Do not call kfree_skb() under local_irq_disable() It is not allowed to call kfree_skb() from hardware interrupt context or with hardware interrupts being disabled. So replace kfree_skb() with dev_kfree_skb_irq() under local_irq_disable(). Compile tested only. Fixes: 05fcd31cc472 ("arcnet: add err_skb package for package status feedback") Signed-off-by: Jinjie Ruan Signed-off-by: David S. Miller --- drivers/net/arcnet/arcnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 99265667538c..d9e052c49ba1 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -464,7 +464,7 @@ static void arcnet_reply_tasklet(struct tasklet_struct *t) ret = sock_queue_err_skb(sk, ackskb); if (ret) - kfree_skb(ackskb); + dev_kfree_skb_irq(ackskb); local_irq_enable(); }; -- cgit From 146c7c330507c0384bf29d567186632bfe975927 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 24 Aug 2023 15:43:08 +0200 Subject: mlxsw: i2c: Fix chunk size setting in output mailbox buffer The driver reads commands output from the output mailbox. If the size of the output mailbox is not a multiple of the transaction / block size, then the driver will not issue enough read transactions to read the entire output, which can result in driver initialization errors. Fix by determining the number of transactions using DIV_ROUND_UP(). Fixes: 3029a693beda ("mlxsw: i2c: Allow flexible setting of I2C transactions size") Signed-off-by: Vadim Pasternak Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 41298835a11e..47af7ef7e4ee 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -444,7 +444,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, } else { /* No input mailbox is case of initialization query command. */ reg_size = MLXSW_I2C_MAX_DATA_SIZE; - num = reg_size / mlxsw_i2c->block_size; + num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size); if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { dev_err(&client->dev, "Could not acquire lock"); -- cgit From d7248f1cc835bd80e936dc5b2d94b149bdd0077d Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 24 Aug 2023 15:43:09 +0200 Subject: mlxsw: i2c: Limit single transaction buffer size Maximum size of buffer is obtained from underlying I2C adapter and in case adapter allows I2C transaction buffer size greater than 100 bytes, transaction will fail due to firmware limitation. As a result driver will fail initialization. Limit the maximum size of transaction buffer by 100 bytes to fit to firmware. Remove unnecessary calculation: max_t(u16, MLXSW_I2C_BLK_DEF, quirk_size). This condition can not happened. Fixes: 3029a693beda ("mlxsw: i2c: Allow flexible setting of I2C transactions size") Signed-off-by: Vadim Pasternak Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 47af7ef7e4ee..d23f293e285c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -48,6 +48,7 @@ #define MLXSW_I2C_MBOX_SIZE_BITS 12 #define MLXSW_I2C_ADDR_BUF_SIZE 4 #define MLXSW_I2C_BLK_DEF 32 +#define MLXSW_I2C_BLK_MAX 100 #define MLXSW_I2C_RETRY 5 #define MLXSW_I2C_TIMEOUT_MSECS 5000 #define MLXSW_I2C_MAX_DATA_SIZE 256 @@ -653,7 +654,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client) return -EOPNOTSUPP; } - mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF, + mlxsw_i2c->block_size = min_t(u16, MLXSW_I2C_BLK_MAX, min_t(u16, quirks->max_read_len, quirks->max_write_len)); } else { -- cgit From 3fc134a07438055fc93ce1bbacf2702ddd09500c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 24 Aug 2023 15:43:10 +0200 Subject: mlxsw: core_hwmon: Adjust module label names based on MTCAP sensor counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Transceiver module temperature sensors are indexed after ASIC and platform sensors. The current label printing method does not take this into account and simply prints the index of the transceiver module sensor. On new systems that have platform sensors this results in incorrect (shifted) transceiver module labels being printed: $ sensors [...] front panel 002: +37.0°C (crit = +70.0°C, emerg = +75.0°C) front panel 003: +47.0°C (crit = +70.0°C, emerg = +75.0°C) [...] Fix by taking the sensor count into account. After the fix: $ sensors [...] front panel 001: +37.0°C (crit = +70.0°C, emerg = +75.0°C) front panel 002: +47.0°C (crit = +70.0°C, emerg = +75.0°C) [...] Fixes: a53779de6a0e ("mlxsw: core: Add QSFP module temperature label attribute to hwmon") Signed-off-by: Vadim Pasternak Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 70735068cf29..0fd290d776ff 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -405,7 +405,8 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, container_of(attr, struct mlxsw_hwmon_attr, dev_attr); return sprintf(buf, "front panel %03u\n", - mlxsw_hwmon_attr->type_index); + mlxsw_hwmon_attr->type_index + 1 - + mlxsw_hwmon_attr->mlxsw_hwmon_dev->sensor_count); } static ssize_t -- cgit From 5d7cf67f72ae34d38e090bdfa673da4aefe4048e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 8 Aug 2023 20:44:48 -0400 Subject: Fix nomenclature for USB and PCI wireless devices A mouse that uses a USB connection is called a "USB mouse" device (or "USB mouse" for short), not a "mouse USB" device. By analogy, a WiFi adapter that connects to the host computer via USB is a "USB wireless" device, not a "wireless USB" device. (The latter term more properly refers to a defunct Wireless USB specification, which described a technology for sending USB protocol messages over an ultra wideband radio link.) Similarly for a WiFi adapter card that plugs into a PCIe slot: It is a "PCIe wireless" device, not a "wireless PCIe" device. Rephrase the text in the kernel source where the word ordering is wrong. Signed-off-by: Alan Stern Reviewed-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/57da7c80-0e48-41b5-8427-884a02648f55@rowland.harvard.edu --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- drivers/net/wireless/ath/ath10k/usb.c | 2 +- drivers/net/wireless/ath/ath11k/pci.c | 2 +- drivers/net/wireless/ath/ath12k/pci.c | 2 +- drivers/net/wireless/atmel/at76c50x-usb.c | 8 ++++---- drivers/net/wireless/intersil/orinoco/orinoco_usb.c | 12 ++++++------ drivers/net/wireless/legacy/rndis_wlan.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/Kconfig | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/Kconfig | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7915/Kconfig | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +- drivers/net/wireless/mediatek/mt7601u/Kconfig | 2 +- drivers/net/wireless/purelifi/plfxlc/Kconfig | 2 +- drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +- drivers/net/wireless/realtek/rtw88/pci.c | 2 +- drivers/net/wireless/realtek/rtw88/usb.c | 2 +- drivers/net/wireless/realtek/rtw89/pci.c | 2 +- drivers/net/wireless/zydas/zd1201.c | 6 +++--- 20 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index a7f44f6335fb..3ef414b613bf 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3816,7 +3816,7 @@ static void __exit ath10k_pci_exit(void) module_exit(ath10k_pci_exit); MODULE_AUTHOR("Qualcomm Atheros"); -MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN PCIe/AHB devices"); +MODULE_DESCRIPTION("Driver support for Qualcomm Atheros PCIe/AHB 802.11ac WLAN devices"); MODULE_LICENSE("Dual BSD/GPL"); /* QCA988x 2.0 firmware files */ diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c index b0067af685b1..3c482baacec1 100644 --- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -1126,5 +1126,5 @@ static struct usb_driver ath10k_usb_driver = { module_usb_driver(ath10k_usb_driver); MODULE_AUTHOR("Atheros Communications, Inc."); -MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN USB devices"); +MODULE_DESCRIPTION("Driver support for Qualcomm Atheros USB 802.11ac WLAN devices"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 5fd08ffc2a9f..9573bd959cac 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -1036,7 +1036,7 @@ static void ath11k_pci_exit(void) module_exit(ath11k_pci_exit); -MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices"); +MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices"); MODULE_LICENSE("Dual BSD/GPL"); /* firmware files */ diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 5990a55801f0..bd689efa7daa 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1409,5 +1409,5 @@ static void ath12k_pci_exit(void) module_exit(ath12k_pci_exit); -MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe devices"); +MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11be WLAN devices"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index 009bca34ece3..447b51cff8f9 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c @@ -10,7 +10,7 @@ * Copyright (c) 2007 Kalle Valo * Copyright (c) 2010 Sebastian Smolorz * - * This file is part of the Berlios driver for WLAN USB devices based on the + * This file is part of the Berlios driver for USB WLAN devices based on the * Atmel AT76C503A/505/505A. * * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed @@ -143,7 +143,7 @@ static const struct usb_device_id dev_table[] = { { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, /* Dynalink/Askey WLL013 (intersil) */ { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */ + /* EZ connect 11Mpbs USB Wireless Adapter SMC2662W v1 */ { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, /* BenQ AWL300 */ { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) }, @@ -195,7 +195,7 @@ static const struct usb_device_id dev_table[] = { { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) }, /* 3Com 3CRSHEW696 */ { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) }, - /* Siemens Santis ADSL WLAN USB adapter WLL 013 */ + /* Siemens Santis ADSL USB WLAN adapter WLL 013 */ { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) }, /* Belkin F5D6050, version 2 */ { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) }, @@ -238,7 +238,7 @@ static const struct usb_device_id dev_table[] = { { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) }, /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */ { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Corega WLAN USB Stick 11 */ + /* Corega USB WLAN Stick 11 */ { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) }, /* Microstar MSI Box MS6978 */ { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) }, diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index dd31929261ab..866e0230df25 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -129,18 +129,18 @@ MODULE_FIRMWARE("orinoco_ezusb_fw"); #define USB_AVAYA8_VENDOR_ID 0x0D98 #define USB_AVAYAE_VENDOR_ID 0x0D9E -#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya Wireless USB Card */ +#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya USB Wireless Card */ #define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */ -#define USB_AGERE_MODEL0801_ID 0x1000 /* Wireless USB Card Model 0801 */ -#define USB_AGERE_MODEL0802_ID 0x1001 /* Wireless USB Card Model 0802 */ -#define USB_AGERE_REBRANDED_ID 0x047A /* WLAN USB Card */ +#define USB_AGERE_MODEL0801_ID 0x1000 /* USB Wireless Card Model 0801 */ +#define USB_AGERE_MODEL0802_ID 0x1001 /* USB Wireless Card Model 0802 */ +#define USB_AGERE_REBRANDED_ID 0x047A /* USB WLAN Card */ #define USB_ELSA_VENDOR_ID 0x05CC #define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */ #define USB_LEGEND_VENDOR_ID 0x0E7C -#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet WLAN USB Card */ +#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet USB WLAN Card */ #define USB_SAMSUNG_VENDOR_ID 0x04E8 #define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */ @@ -154,7 +154,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw"); #define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */ #define USB_2WIRE_VENDOR_ID 0x1630 -#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire Wireless USB adapter */ +#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire USB Wireless adapter */ #define EZUSB_REQUEST_FW_TRANS 0xA0 diff --git a/drivers/net/wireless/legacy/rndis_wlan.c b/drivers/net/wireless/legacy/rndis_wlan.c index 712038d46bdb..e7fea7ded6d5 100644 --- a/drivers/net/wireless/legacy/rndis_wlan.c +++ b/drivers/net/wireless/legacy/rndis_wlan.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Driver for RNDIS based wireless USB devices. + * Driver for RNDIS based USB wireless devices. * * Copyright (C) 2007 by Bjorge Dijkstra * Copyright (C) 2008-2009 by Jussi Kivilinna diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig index 6a0080f1d91c..dd16acfd9735 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig @@ -5,7 +5,7 @@ config MT7603E depends on MAC80211 depends on PCI help - This adds support for MT7603E wireless PCIe devices and the WLAN core + This adds support for MT7603E PCIe wireless devices and the WLAN core on MT7628/MT7688 SoC devices. This family supports IEEE 802.11n 2x2 to 300Mbps PHY rate diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig index 30fba36ff46b..1ab1439143f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig @@ -11,7 +11,7 @@ config MT7615E depends on MAC80211 depends on PCI help - This adds support for MT7615-based wireless PCIe devices, + This adds support for MT7615-based PCIe wireless devices, which support concurrent dual-band operation at both 5GHz and 2.4GHz, IEEE 802.11ac 4x4:4SS 1733Mbps PHY rate, wave2 MU-MIMO up to 4 users/group and 160MHz channels. diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig index 7c88ed8b8f1e..3ed888782a70 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig @@ -10,7 +10,7 @@ config MT76x0U depends on MAC80211 depends on USB help - This adds support for MT7610U-based wireless USB 2.0 dongles, + This adds support for MT7610U-based USB 2.0 wireless dongles, which comply with IEEE 802.11ac standards and support 1x1 433Mbps PHY rate. @@ -22,7 +22,7 @@ config MT76x0E depends on MAC80211 depends on PCI help - This adds support for MT7610/MT7630-based wireless PCIe devices, + This adds support for MT7610/MT7630-based PCIe wireless devices, which comply with IEEE 802.11ac standards and support 1x1 433Mbps PHY rate. diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig index 5fd4973e32df..482a32b70ddf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig @@ -9,7 +9,7 @@ config MT76x2E depends on MAC80211 depends on PCI help - This adds support for MT7612/MT7602/MT7662-based wireless PCIe + This adds support for MT7612/MT7602/MT7662-based PCIe wireless devices, which comply with IEEE 802.11ac standards and support 2SS to 866Mbit/s PHY rate. @@ -22,7 +22,7 @@ config MT76x2U depends on MAC80211 depends on USB help - This adds support for MT7612U-based wireless USB 3.0 dongles, + This adds support for MT7612U-based USB 3.0 wireless dongles, which comply with IEEE 802.11ac standards and support 2SS to 866Mbit/s PHY rate. diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig index 896ec38c23d9..193112c49bd1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig @@ -7,7 +7,7 @@ config MT7915E depends on PCI select RELAY help - This adds support for MT7915-based wireless PCIe devices, + This adds support for MT7915-based PCIe wireless devices, which support concurrent dual-band operation at both 5GHz and 2.4GHz IEEE 802.11ax 4x4:4SS 1024-QAM, 160MHz channels, OFDMA, spatial reuse and dual carrier modulation. diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig index 1afa2f662e47..bb44d4a5e2dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig @@ -7,7 +7,7 @@ config MT7996E depends on MAC80211 depends on PCI help - This adds support for MT7996-based wireless PCIe devices, + This adds support for MT7996-based PCIe wireless devices, which support concurrent tri-band operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels. diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig index 4a8b96280670..4880fc053d9d 100644 --- a/drivers/net/wireless/mediatek/mt7601u/Kconfig +++ b/drivers/net/wireless/mediatek/mt7601u/Kconfig @@ -4,4 +4,4 @@ config MT7601U depends on MAC80211 depends on USB help - This adds support for MT7601U-based wireless USB dongles. + This adds support for MT7601U-based USB wireless dongles. diff --git a/drivers/net/wireless/purelifi/plfxlc/Kconfig b/drivers/net/wireless/purelifi/plfxlc/Kconfig index 4e0be27a5e0e..dd5fca480d7e 100644 --- a/drivers/net/wireless/purelifi/plfxlc/Kconfig +++ b/drivers/net/wireless/purelifi/plfxlc/Kconfig @@ -3,7 +3,7 @@ config PLFXLC tristate "pureLiFi X, XL, XC device support" depends on CFG80211 && MAC80211 && USB help - This option adds support for pureLiFi LiFi wireless USB + This option adds support for pureLiFi LiFi USB wireless adapters. The pureLiFi X, XL, XC USB devices are based on 802.11 OFDM PHY but uses light as the transmission medium. The driver supports common 802.11 encryption/authentication diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig index dcccc290a7f5..d1fd66d44a7e 100644 --- a/drivers/net/wireless/ralink/rt2x00/Kconfig +++ b/drivers/net/wireless/ralink/rt2x00/Kconfig @@ -170,7 +170,7 @@ config RT2800USB_RT35XX config RT2800USB_RT3573 bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)" help - This enables support for RT3573 chipset based wireless USB devices + This enables support for RT3573 chipset based USB wireless devices in the rt2800usb driver. config RT2800USB_RT53XX diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 44a8fff34cdd..2bfc0e822b8d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1828,5 +1828,5 @@ void rtw_pci_shutdown(struct pci_dev *pdev) EXPORT_SYMBOL(rtw_pci_shutdown); MODULE_AUTHOR("Realtek Corporation"); -MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver"); +MODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 91ed6d10ba8a..95b9d933158f 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -909,5 +909,5 @@ void rtw_usb_disconnect(struct usb_interface *intf) EXPORT_SYMBOL(rtw_usb_disconnect); MODULE_AUTHOR("Realtek Corporation"); -MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver"); +MODULE_DESCRIPTION("Realtek USB 802.11ac wireless driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 9402f1a0caea..3a4bfc44142b 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -3939,5 +3939,5 @@ void rtw89_pci_remove(struct pci_dev *pdev) EXPORT_SYMBOL(rtw89_pci_remove); MODULE_AUTHOR("Realtek Corporation"); -MODULE_DESCRIPTION("Realtek 802.11ax wireless PCI driver"); +MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c index a85fe7e4c6d4..2814df1ecc78 100644 --- a/drivers/net/wireless/zydas/zd1201.c +++ b/drivers/net/wireless/zydas/zd1201.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Driver for ZyDAS zd1201 based wireless USB devices. + * Driver for ZyDAS zd1201 based USB wireless devices. * * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) * @@ -23,8 +23,8 @@ #include "zd1201.h" static const struct usb_device_id zd1201_table[] = { - {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ - {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ + {USB_DEVICE(0x0586, 0x3400)}, /* Peabird USB Wireless Adapter */ + {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 USB Wireless Adapter */ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ {USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */ -- cgit From 64a24cb63a4b6036e4af280767b305a5044ff303 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:28 +0800 Subject: wifi: rtw89: add function prototype for coex request duration The request duration comes from coex mechanism, indicating the length of time that should be reserved for BT in each time division. It is required to handle update notification when channel concurrency processes. Since it will involve in both coex and wifi code flow, this commit ahead adds the prototype for required function interfaces to split the implementation of coex and wifi in the following. The follow-up are expected be add afterwards. 1. coex mechanism call rtw89_core_ntfy_btc_event() once bt req len changes 2. channel concurrency flow updates related stuffs when notified Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/coex.h | 9 +++++++++ drivers/net/wireless/realtek/rtw89/core.c | 21 +++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/core.h | 12 ++++++++++++ 3 files changed, 42 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index f16421cb30ef..e76153709793 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -193,4 +193,13 @@ static inline u8 rtw89_btc_path_phymap(struct rtw89_dev *rtwdev, return rtw89_btc_phymap(rtwdev, phy_idx, BIT(path)); } +/* return bt req len in TU */ +static inline u16 rtw89_coex_query_bt_req_len(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + struct rtw89_btc *btc = &rtwdev->btc; + + return btc->bt_req_len; +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 71eb9cfd4896..a338b0a97910 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3464,6 +3464,27 @@ void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond, complete(&wait->completion); } +void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event) +{ + u16 bt_req_len; + + switch (event) { + case RTW89_BTC_HMSG_SET_BT_REQ_SLOT: + bt_req_len = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "coex updates BT req len to %d TU\n", bt_req_len); + break; + default: + if (event < NUM_OF_RTW89_BTC_HMSG) + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "unhandled BTC HMSG event: %d\n", event); + else + rtw89_warn(rtwdev, + "unrecognized BTC HMSG event: %d\n", event); + break; + } +} + int rtw89_core_start(struct rtw89_dev *rtwdev) { int ret; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index b5a08f90f5bd..5b60bc72b4a5 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -2656,6 +2656,17 @@ struct rtw89_btc { bool lps; }; +enum rtw89_btc_hmsg { + RTW89_BTC_HMSG_TMR_EN = 0x0, + RTW89_BTC_HMSG_BT_REG_READBACK = 0x1, + RTW89_BTC_HMSG_SET_BT_REQ_SLOT = 0x2, + RTW89_BTC_HMSG_FW_EV = 0x3, + RTW89_BTC_HMSG_BT_LINK_CHG = 0x4, + RTW89_BTC_HMSG_SET_BT_REQ_STBC = 0x5, + + NUM_OF_RTW89_BTC_HMSG, +}; + enum rtw89_ra_mode { RTW89_RA_MODE_CCK = BIT(0), RTW89_RA_MODE_OFDM = BIT(1), @@ -5325,5 +5336,6 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool hw_scan); void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool active); +void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event); #endif -- cgit From b05fdc46c5a64358f515c4db31991f609a572b53 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:29 +0800 Subject: wifi: rtw89: refine rtw89_correct_cck_chan() by rtw89_hw_to_nl80211_band() In rtw89_correct_cck_chan(), we turn to use rtw89_hw_to_nl80211_band(). The difference between rtw89_hw_to_nl80211_band() and the original raw judgement is the case on 6 GHz. Since rtw89_correct_cck_chan() is common code independent on chip, if runtime chip doesn't support 6 GHz, it is probably safe. Otherwise, it might not. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index a338b0a97910..aedabd262251 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1659,8 +1659,7 @@ static void rtw89_correct_cck_chan(struct rtw89_dev *rtwdev, const struct rtw89_chan_rcd *rcd = rtw89_chan_rcd_get(rtwdev, RTW89_SUB_ENTITY_0); u16 chan = rcd->prev_primary_channel; - u8 band = rcd->prev_band_type == RTW89_BAND_2G ? - NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + u8 band = rtw89_hw_to_nl80211_band(rcd->prev_band_type); if (status->band != NL80211_BAND_2GHZ && status->encoding == RX_ENC_LEGACY && -- cgit From bfbadacf37a204afbfb829d508412d501a22d62c Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:30 +0800 Subject: wifi: rtw89: sar: let caller decide the center frequency to query If multiple channels, SAR will be hard to determine the center frequency to query. Therefore, we move this decision out of SAR. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/debug.c | 10 ++++++---- drivers/net/wireless/realtek/rtw89/phy.c | 8 ++++++-- drivers/net/wireless/realtek/rtw89/sar.c | 24 ++++++++++++------------ drivers/net/wireless/realtek/rtw89/sar.h | 6 +++--- 4 files changed, 27 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index f6f1e90c3934..48635458c36a 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -572,9 +572,9 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev, seq_puts(m, #_regd "\n"); \ break -static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev) +static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); u8 band = chan->band_type; u8 regd = rtw89_regd_get(rtwdev, band); @@ -604,16 +604,18 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v) { struct rtw89_debugfs_priv *debugfs_priv = m->private; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; + const struct rtw89_chan *chan; int ret = 0; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); + chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); seq_puts(m, "[Regulatory] "); - __print_regd(m, rtwdev); + __print_regd(m, rtwdev, chan); seq_puts(m, "[SAR]\n"); - rtw89_print_sar(m, rtwdev); + rtw89_print_sar(m, rtwdev, chan->freq); seq_puts(m, "[TAS]\n"); rtw89_print_tas(m, rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index c40c4f8c1271..fcdc61597b9b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -1647,6 +1647,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); + u32 freq = ieee80211_channel_to_frequency(ch, nl_band); u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); u8 reg6 = regulatory->reg_6ghz_power; @@ -1682,7 +1684,7 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, } lmt = _phy_txpwr_rf_to_mac(rtwdev, lmt); - sar = rtw89_query_sar(rtwdev); + sar = rtw89_query_sar(rtwdev, freq); return min(lmt, sar); } @@ -1902,6 +1904,8 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); + u32 freq = ieee80211_channel_to_frequency(ch, nl_band); u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); u8 reg6 = regulatory->reg_6ghz_power; @@ -1937,7 +1941,7 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, } lmt_ru = _phy_txpwr_rf_to_mac(rtwdev, lmt_ru); - sar = rtw89_query_sar(rtwdev); + sar = rtw89_query_sar(rtwdev, freq); return min(lmt_ru, sar); } diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index fafc7a0cfe97..881322f85d79 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -85,17 +85,15 @@ static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = { RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8), }; -static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg) +static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, + u32 center_freq, s32 *cfg) { struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); - enum rtw89_band band = chan->band_type; - u32 center_freq = chan->freq; const struct rtw89_sar_span *span = NULL; enum rtw89_sar_subband subband_l, subband_h; int idx; - if (band == RTW89_BAND_6G) { + if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) { idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq); /* To decrease size of rtw89_sar_overlapping_6ghz[], * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs @@ -115,8 +113,8 @@ static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg) } rtw89_debug(rtwdev, RTW89_DBG_SAR, - "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n", - band, center_freq, subband_l, subband_h); + "center_freq %u: SAR subband {%u, %u}\n", + center_freq, subband_l, subband_h); if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h]) return -ENODATA; @@ -186,7 +184,7 @@ static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl, return cfg << (RTW89_TAS_FACTOR - fct); } -s8 rtw89_query_sar(struct rtw89_dev *rtwdev) +s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq) { const enum rtw89_sar_sources src = rtwdev->sar.src; /* its members are protected by rtw89_sar_set_src() */ @@ -202,7 +200,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev) if (src == RTW89_SAR_SOURCE_NONE) return RTW89_SAR_TXPWR_MAC_MAX; - ret = sar_hdl->query_sar_config(rtwdev, &cfg); + ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); if (ret) return RTW89_SAR_TXPWR_MAC_MAX; @@ -224,7 +222,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev) return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg); } -void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev) +void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq) { const enum rtw89_sar_sources src = rtwdev->sar.src; /* its members are protected by rtw89_sar_set_src() */ @@ -243,7 +241,7 @@ void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev) seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source); - ret = sar_hdl->query_sar_config(rtwdev, &cfg); + ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); if (ret) { seq_printf(m, "config: return code: %d\n", ret); seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n", @@ -359,6 +357,7 @@ static void rtw89_tas_state_update(struct rtw89_dev *rtwdev) s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT; s32 dpr_on_threshold, dpr_off_threshold, cfg; enum rtw89_tas_state state = tas->state; + const struct rtw89_chan *chan; int ret; lockdep_assert_held(&rtwdev->mutex); @@ -366,7 +365,8 @@ static void rtw89_tas_state_update(struct rtw89_dev *rtwdev) if (src == RTW89_SAR_SOURCE_NONE) return; - ret = sar_hdl->query_sar_config(rtwdev, &cfg); + chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg); if (ret) return; diff --git a/drivers/net/wireless/realtek/rtw89/sar.h b/drivers/net/wireless/realtek/rtw89/sar.h index 40ce5990ceaf..bd7a657188d9 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.h +++ b/drivers/net/wireless/realtek/rtw89/sar.h @@ -13,13 +13,13 @@ struct rtw89_sar_handler { const char *descr_sar_source; u8 txpwr_factor_sar; - int (*query_sar_config)(struct rtw89_dev *rtwdev, s32 *cfg); + int (*query_sar_config)(struct rtw89_dev *rtwdev, u32 center_freq, s32 *cfg); }; extern const struct cfg80211_sar_capa rtw89_sar_capa; -s8 rtw89_query_sar(struct rtw89_dev *rtwdev); -void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev); +s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq); +void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq); void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev); int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); -- cgit From ad3dc7220220ae2b86152c67882f9cf5bad4bc1f Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:31 +0800 Subject: wifi: rtw89: call rtw89_chan_get() by vif chanctx if aware of vif We adjust these processes which can work accodrding to vif but call rtw89_chan_get() with static RTW89_SUB_ENTITY_0. After multi-channel support, chanctx of vif won't always be on RTW89_SUB_ENTITY_0. So, we make them call rtw89_chan_get() with rtwvif->sub_entity_idx. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/coex.c | 3 ++- drivers/net/wireless/realtek/rtw89/core.c | 22 +++++++++++++--------- drivers/net/wireless/realtek/rtw89/core.h | 12 ++++++++++++ drivers/net/wireless/realtek/rtw89/fw.c | 6 ++++-- drivers/net/wireless/realtek/rtw89/mac80211.c | 3 ++- drivers/net/wireless/realtek/rtw89/phy.c | 21 ++++++++++++--------- 6 files changed, 45 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index bda0e1e99a8c..4ba8b3df70ae 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -5666,7 +5666,8 @@ enum btc_wl_mode { void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, struct rtw89_sta *rtwsta, enum btc_role_state state) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); struct rtw89_btc *btc = &rtwdev->btc; diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index aedabd262251..91f9a587220b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -523,12 +523,12 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev, } static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, - struct rtw89_core_tx_request *tx_req) + struct rtw89_core_tx_request *tx_req, + const struct rtw89_chan *chan) { struct sk_buff *skb = tx_req->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = tx_info->control.vif; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); u16 lowest_rate; if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE || @@ -567,7 +567,8 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif = tx_req->vif; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); u8 qsel, ch_dma; qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT; @@ -584,7 +585,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, desc_info->en_wd_info = true; desc_info->use_rate = true; desc_info->dis_data_fb = true; - desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req); + desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req, chan); rtw89_debug(rtwdev, RTW89_DBG_TXRX, "tx mgmt frame with rate 0x%x on channel %d (band %d, bw %d)\n", @@ -603,7 +604,8 @@ rtw89_core_tx_update_h2c_info(struct rtw89_dev *rtwdev, desc_info->ch_dma = RTW89_DMA_H2C; } -static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc) +static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc, + const struct rtw89_chan *chan) { static const u8 rtw89_bandwidth_to_om[] = { [RTW89_CHANNEL_WIDTH_20] = HTC_OM_CHANNEL_WIDTH_20, @@ -614,7 +616,6 @@ static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc }; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_hal *hal = &rtwdev->hal; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); u8 om_bandwidth; if (!chip->dis_2g_40m_ul_ofdma || @@ -1899,7 +1900,6 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, { const struct cfg80211_chan_def *chandef = rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0); - const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); u16 data_rate; u8 data_rate_mode; @@ -1909,6 +1909,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, if (rtwdev->scanning && RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { + const struct rtw89_chan *cur = rtw89_scan_chan_get(rtwdev); u8 chan = cur->primary_channel; u8 band = cur->band_type; enum nl80211_band nl_band; @@ -2970,6 +2971,8 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); int ret; if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { @@ -3023,7 +3026,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, BTC_ROLE_MSTS_STA_CONN_END); - rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template); + rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan); rtw89_phy_ul_tb_assoc(rtwdev, rtwvif); ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); @@ -3656,7 +3659,8 @@ EXPORT_SYMBOL(rtw89_core_deinit); void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, const u8 *mac_addr, bool hw_scan) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); rtwdev->scanning = true; rtw89_leave_lps(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 5b60bc72b4a5..257582fc39ea 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4929,6 +4929,18 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev, return &hal->sub[idx].rcd; } +static inline +const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev) +{ + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + + if (rtwvif) + return rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); + else + return rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); +} + static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index bcd9050f989f..4c044dbc90b6 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -1758,7 +1758,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); struct sk_buff *skb; u8 pads[RTW89_PPE_BW_NUM]; u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; @@ -1915,7 +1916,8 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); struct sk_buff *skb; struct sk_buff *skb_beacon; u16 tim_offset; diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index a66503eb35b8..7c3066c0a550 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -296,7 +296,8 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u8 aifsn) { struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); u8 slot_time; u8 sifs; diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index fcdc61597b9b..5ff2871b230b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -133,10 +133,10 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak) return ra_mask; } -static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) +static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + const struct rtw89_chan *chan) { struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); struct cfg80211_bitrate_mask *mask = &rtwsta->mask; enum nl80211_band band; u64 cfg_mask; @@ -197,9 +197,9 @@ rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES, static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + const struct rtw89_chan *chan, bool *fix_giltf_en, u8 *fix_giltf) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); struct cfg80211_bitrate_mask *mask = &rtwsta->mask; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); @@ -236,7 +236,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; struct rtw89_ra_info *ra = &rtwsta->ra; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); @@ -265,7 +266,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) ldpc_en = 1; - rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, &fix_giltf_en, &fix_giltf); + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf); } else if (sta->deflink.vht_cap.vht_supported) { u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); @@ -332,7 +333,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0); ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak); - ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta); + ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_160: @@ -362,7 +363,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->dcm_cap = 1; if (rate_pattern->enable && !vif->p2p) { - ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta); + ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); ra_mask &= rate_pattern->ra_mask; mode = rate_pattern->ra_mode; } @@ -457,7 +458,8 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct ieee80211_supported_band *sband; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_phy_rate_pattern next_pattern = {0}; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), @@ -2889,7 +2891,8 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val, void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { const struct rtw89_chip_info *chip = rtwdev->chip; - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif->sub_entity_idx); struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info; if (!chip->support_ul_tb_ctrl) -- cgit From 51383fd77791333868ef69bff223629a964beb8c Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:32 +0800 Subject: wifi: rtw89: provide functions to configure NoA for beacon update Callers call renew function when wanting to generate a new P2P NoA information element, and call append function to append NoA attribute one by one. Then, updating beacon work will fetch the P2P NoA information element configured by callers and add it to beacon. The use case of MCC (multi-channel concurrent) for example: * start MCC - GO part renew P2P NoA append period NoA after calculation * download beacon for GO fetch P2P NoA and add to beacon content * stop MCC - GO part renew P2P NoA (reset) Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 27 ++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.c | 10 +++++ drivers/net/wireless/realtek/rtw89/ps.c | 61 +++++++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/ps.h | 4 ++ 4 files changed, 102 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 257582fc39ea..431b0d3daa2a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -2896,6 +2896,32 @@ struct rtw89_roc { #define RTW89_P2P_MAX_NOA_NUM 2 +struct rtw89_p2p_ie_head { + u8 eid; + u8 ie_len; + u8 oui[3]; + u8 oui_type; +} __packed; + +struct rtw89_noa_attr_head { + u8 attr_type; + __le16 attr_len; + u8 index; + u8 oppps_ctwindow; +} __packed; + +struct rtw89_p2p_noa_ie { + struct rtw89_p2p_ie_head p2p_head; + struct rtw89_noa_attr_head noa_head; + struct ieee80211_p2p_noa_desc noa_desc[RTW89_P2P_MAX_NOA_NUM]; +} __packed; + +struct rtw89_p2p_noa_setter { + struct rtw89_p2p_noa_ie ie; + u8 noa_count; + u8 noa_index; +}; + struct rtw89_vif { struct list_head list; struct rtw89_dev *rtwdev; @@ -2938,6 +2964,7 @@ struct rtw89_vif { struct cfg80211_scan_request *scan_req; struct ieee80211_scan_ies *scan_ies; struct list_head general_pkt_list; + struct rtw89_p2p_noa_setter p2p_noa; }; enum rtw89_lv1_rcvy_step { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 4c044dbc90b6..772b0f107f40 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -9,6 +9,7 @@ #include "fw.h" #include "mac.h" #include "phy.h" +#include "ps.h" #include "reg.h" #include "util.h" @@ -1923,6 +1924,8 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, u16 tim_offset; int bcn_total_len; u16 beacon_rate; + void *noa_data; + u8 noa_len; int ret; if (vif->p2p) @@ -1939,6 +1942,13 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, return -ENOMEM; } + noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); + if (noa_len && + (noa_len <= skb_tailroom(skb_beacon) || + pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { + skb_put_data(skb_beacon, noa_data, noa_len); + } + bcn_total_len = H2C_BCN_BASE_LEN + skb_beacon->len; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, bcn_total_len); if (!skb) { diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index 84201ef19c17..b98ec178abe1 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -278,3 +278,64 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) rtwdev->lps_enabled = false; } } + +void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) +{ + struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; + struct rtw89_noa_attr_head *noa_head = &ie->noa_head; + + if (setter->noa_count) { + setter->noa_index++; + setter->noa_count = 0; + } + + memset(ie, 0, sizeof(*ie)); + + p2p_head->eid = WLAN_EID_VENDOR_SPECIFIC; + p2p_head->ie_len = 4 + sizeof(*noa_head); + p2p_head->oui[0] = (WLAN_OUI_WFA >> 16) & 0xff; + p2p_head->oui[1] = (WLAN_OUI_WFA >> 8) & 0xff; + p2p_head->oui[2] = (WLAN_OUI_WFA >> 0) & 0xff; + p2p_head->oui_type = WLAN_OUI_TYPE_WFA_P2P; + + noa_head->attr_type = IEEE80211_P2P_ATTR_ABSENCE_NOTICE; + noa_head->attr_len = cpu_to_le16(2); + noa_head->index = setter->noa_index; + noa_head->oppps_ctwindow = 0; +} + +void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, + const struct ieee80211_p2p_noa_desc *desc) +{ + struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; + struct rtw89_noa_attr_head *noa_head = &ie->noa_head; + + if (!desc->count || !desc->duration) + return; + + if (setter->noa_count >= RTW89_P2P_MAX_NOA_NUM) + return; + + p2p_head->ie_len += sizeof(*desc); + le16_add_cpu(&noa_head->attr_len, sizeof(*desc)); + + ie->noa_desc[setter->noa_count++] = *desc; +} + +u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data) +{ + struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + void *tail; + + if (!setter->noa_count) + return 0; + + *data = ie; + tail = ie->noa_desc + setter->noa_count; + return tail - *data; +} diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index 4c18f49204b2..aff0fba71cb0 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -16,6 +16,10 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev); void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); void rtw89_recalc_lps(struct rtw89_dev *rtwdev); +void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif); +void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, + const struct ieee80211_p2p_noa_desc *desc); +u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data); static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) { -- cgit From 4843aa3768e2c7f4dc61400c2db03671236d7c98 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Wed, 16 Aug 2023 16:21:33 +0800 Subject: wifi: rtw89: initialize multi-channel handling We prepare to deal with multiple channels via new entity modes. * MCC_PREPARE: Transitional mode before MCC * MCC: Multi-Channel Concurrent mode And, enum of sub-entity is extended for second channel context. We add the entry flow of multi-channel handling and the core stuffs for extended index of sub-entity. And, we now deal with the filling of entity channels' info in entity recalc where we know the number of active chanctx. However, the other detail coding of MCC start/stop will be implemented in the following. Besides, chanctx listener struct is pre-added in chip info. Each component can add callback type in chanctx listener and configure its callback function to react according to chanctx states. We know at least RFK (RF calibration) and BTC (BT coexistence) will require such callbacks. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230816082133.57474-7-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/chan.c | 124 ++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/chan.h | 5 ++ drivers/net/wireless/realtek/rtw89/core.c | 68 +++++++++----- drivers/net/wireless/realtek/rtw89/core.h | 27 ++++++ drivers/net/wireless/realtek/rtw89/mac80211.c | 4 + drivers/net/wireless/realtek/rtw89/ps.c | 14 ++- 6 files changed, 219 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 4663db4ce2f6..e1bc3606f9ae 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -4,6 +4,8 @@ #include "chan.h" #include "debug.h" +#include "fw.h" +#include "ps.h" #include "util.h" static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band, @@ -116,6 +118,7 @@ bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, rcd->prev_primary_channel = chan->primary_channel; rcd->prev_band_type = chan->band_type; band_changed = new->band_type != chan->band_type; + rcd->band_changed = band_changed; *chan = *new; return band_changed; @@ -193,8 +196,12 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; + const struct cfg80211_chan_def *chandef; enum rtw89_entity_mode mode; + struct rtw89_chan chan; u8 weight; + u8 last; + u8 idx; weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); switch (weight) { @@ -206,14 +213,121 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev) rtw89_config_default_chandef(rtwdev); fallthrough; case 1: + last = RTW89_SUB_ENTITY_0; mode = RTW89_ENTITY_MODE_SCC; break; + case 2: + last = RTW89_SUB_ENTITY_1; + mode = rtw89_get_entity_mode(rtwdev); + if (mode == RTW89_ENTITY_MODE_MCC) + break; + + mode = RTW89_ENTITY_MODE_MCC_PREPARE; + break; + } + + for (idx = 0; idx <= last; idx++) { + chandef = rtw89_chandef_get(rtwdev, idx); + rtw89_get_channel_params(chandef, &chan); + if (chan.channel == 0) { + WARN(1, "Invalid channel on chanctx %d\n", idx); + return RTW89_ENTITY_MODE_INVALID; + } + + rtw89_assign_entity_chan(rtwdev, idx, &chan); } rtw89_set_entity_mode(rtwdev, mode); return mode; } +static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_state state) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_chanctx_listener *listener = chip->chanctx_listener; + int i; + + if (!listener) + return; + + for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) { + if (!listener->callbacks[i]) + continue; + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "chanctx notify listener: cb %d, state %d\n", + i, state); + + listener->callbacks[i](rtwdev, state); + } +} + +static int rtw89_mcc_start(struct rtw89_dev *rtwdev) +{ + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + + rtw89_leave_lps(rtwdev); + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n"); + rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); + return 0; +} + +static void rtw89_mcc_stop(struct rtw89_dev *rtwdev) +{ + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop\n"); + rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); +} + +void rtw89_chanctx_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + chanctx_work.work); + enum rtw89_entity_mode mode; + int ret; + + mutex_lock(&rtwdev->mutex); + + mode = rtw89_get_entity_mode(rtwdev); + switch (mode) { + case RTW89_ENTITY_MODE_MCC_PREPARE: + rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC); + rtw89_set_channel(rtwdev); + + ret = rtw89_mcc_start(rtwdev); + if (ret) + rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret); + break; + default: + break; + } + + mutex_unlock(&rtwdev->mutex); +} + +void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) +{ + enum rtw89_entity_mode mode; + u32 delay; + + mode = rtw89_get_entity_mode(rtwdev); + switch (mode) { + default: + return; + case RTW89_ENTITY_MODE_MCC_PREPARE: + delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE); + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "queue chanctx work for mode %d with delay %d us\n", + mode, delay); + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->chanctx_work, + usecs_to_jiffies(delay)); +} + int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx) { @@ -238,6 +352,7 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, { struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; + enum rtw89_entity_mode mode; struct rtw89_vif *rtwvif; u8 drop, roll; @@ -267,6 +382,15 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, drop = roll; out: + mode = rtw89_get_entity_mode(rtwdev); + switch (mode) { + case RTW89_ENTITY_MODE_MCC: + rtw89_mcc_stop(rtwdev); + break; + default: + break; + } + clear_bit(drop, hal->entity_map); rtw89_set_channel(rtwdev); } diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index bdf369db5041..448e6c5df9f1 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -7,6 +7,9 @@ #include "core.h" +/* The dwell time in TU before doing rtw89_chanctx_work(). */ +#define RTW89_CHANCTX_TIME_MCC_PREPARE 100 + static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; @@ -50,6 +53,8 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev, const struct cfg80211_chan_def *chandef); void rtw89_entity_init(struct rtw89_dev *rtwdev); enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev); +void rtw89_chanctx_work(struct work_struct *work); +void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev); int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 91f9a587220b..92fbbcd5dd3f 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -256,8 +256,8 @@ void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef) NL80211_CHAN_NO_HT); } -static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, - struct rtw89_chan *chan) +void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, + struct rtw89_chan *chan) { struct ieee80211_channel *channel = chandef->chan; enum nl80211_chan_width width = chandef->width; @@ -318,9 +318,11 @@ static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) { + struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_chan *chan; enum rtw89_sub_entity_idx sub_entity_idx; + enum rtw89_sub_entity_idx roc_idx; enum rtw89_phy_idx phy_idx; enum rtw89_entity_mode mode; bool entity_active; @@ -330,10 +332,23 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) return; mode = rtw89_get_entity_mode(rtwdev); - if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode)) + switch (mode) { + case RTW89_ENTITY_MODE_SCC: + case RTW89_ENTITY_MODE_MCC: + sub_entity_idx = RTW89_SUB_ENTITY_0; + break; + case RTW89_ENTITY_MODE_MCC_PREPARE: + sub_entity_idx = RTW89_SUB_ENTITY_1; + break; + default: + WARN(1, "Invalid ent mode: %d\n", mode); return; + } + + roc_idx = atomic_read(&hal->roc_entity_idx); + if (roc_idx != RTW89_SUB_ENTITY_IDLE) + sub_entity_idx = roc_idx; - sub_entity_idx = RTW89_SUB_ENTITY_0; phy_idx = RTW89_PHY_0; chan = rtw89_chan_get(rtwdev, sub_entity_idx); chip->ops->set_txpwr(rtwdev, chan, phy_idx); @@ -341,43 +356,54 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) void rtw89_set_channel(struct rtw89_dev *rtwdev) { + struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chip_info *chip = rtwdev->chip; - const struct cfg80211_chan_def *chandef; + const struct rtw89_chan_rcd *chan_rcd; + const struct rtw89_chan *chan; enum rtw89_sub_entity_idx sub_entity_idx; + enum rtw89_sub_entity_idx roc_idx; enum rtw89_mac_idx mac_idx; enum rtw89_phy_idx phy_idx; - struct rtw89_chan chan; struct rtw89_channel_help_params bak; enum rtw89_entity_mode mode; - bool band_changed; bool entity_active; entity_active = rtw89_get_entity_state(rtwdev); mode = rtw89_entity_recalc(rtwdev); - if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode)) + switch (mode) { + case RTW89_ENTITY_MODE_SCC: + case RTW89_ENTITY_MODE_MCC: + sub_entity_idx = RTW89_SUB_ENTITY_0; + break; + case RTW89_ENTITY_MODE_MCC_PREPARE: + sub_entity_idx = RTW89_SUB_ENTITY_1; + break; + default: + WARN(1, "Invalid ent mode: %d\n", mode); return; + } + + roc_idx = atomic_read(&hal->roc_entity_idx); + if (roc_idx != RTW89_SUB_ENTITY_IDLE) + sub_entity_idx = roc_idx; - sub_entity_idx = RTW89_SUB_ENTITY_0; mac_idx = RTW89_MAC_0; phy_idx = RTW89_PHY_0; - chandef = rtw89_chandef_get(rtwdev, sub_entity_idx); - rtw89_get_channel_params(chandef, &chan); - if (WARN(chan.channel == 0, "Invalid channel\n")) - return; - band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan); + chan = rtw89_chan_get(rtwdev, sub_entity_idx); + chan_rcd = rtw89_chan_rcd_get(rtwdev, sub_entity_idx); - rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx); + rtw89_chip_set_channel_prepare(rtwdev, &bak, chan, mac_idx, phy_idx); - chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx); + chip->ops->set_channel(rtwdev, chan, mac_idx, phy_idx); - chip->ops->set_txpwr(rtwdev, &chan, phy_idx); + chip->ops->set_txpwr(rtwdev, chan, phy_idx); - rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx); + rtw89_chip_set_channel_done(rtwdev, &bak, chan, mac_idx, phy_idx); - if (!entity_active || band_changed) { - rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type); + if (!entity_active || chan_rcd->band_changed) { + rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan->band_type); rtw89_chip_rfk_band_changed(rtwdev, phy_idx); } @@ -3562,6 +3588,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) cancel_work_sync(&btc->icmp_notify_work); cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work); cancel_delayed_work_sync(&rtwdev->track_work); + cancel_delayed_work_sync(&rtwdev->chanctx_work); cancel_delayed_work_sync(&rtwdev->coex_act1_work); cancel_delayed_work_sync(&rtwdev->coex_bt_devinfo_work); cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work); @@ -3598,6 +3625,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); INIT_DELAYED_WORK(&rtwdev->track_work, rtw89_track_work); + INIT_DELAYED_WORK(&rtwdev->chanctx_work, rtw89_chanctx_work); INIT_DELAYED_WORK(&rtwdev->coex_act1_work, rtw89_coex_act1_work); INIT_DELAYED_WORK(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 431b0d3daa2a..284d8f7a7a0c 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -789,6 +789,7 @@ enum rtw89_phy_idx { enum rtw89_sub_entity_idx { RTW89_SUB_ENTITY_0 = 0, + RTW89_SUB_ENTITY_1 = 1, NUM_OF_RTW89_SUB_ENTITY, RTW89_SUB_ENTITY_IDLE = NUM_OF_RTW89_SUB_ENTITY, @@ -900,6 +901,7 @@ struct rtw89_chan { struct rtw89_chan_rcd { u8 prev_primary_channel; enum rtw89_band prev_band_type; + bool band_changed; }; struct rtw89_channel_help_params { @@ -3413,6 +3415,22 @@ struct rtw89_antdiv_info { bool get_stats; }; +enum rtw89_chanctx_state { + RTW89_CHANCTX_STATE_MCC_START, + RTW89_CHANCTX_STATE_MCC_STOP, +}; + +enum rtw89_chanctx_callbacks { + RTW89_CHANCTX_CALLBACK_PLACEHOLDER, + + NUM_OF_RTW89_CHANCTX_CALLBACKS, +}; + +struct rtw89_chanctx_listener { + void (*callbacks[NUM_OF_RTW89_CHANCTX_CALLBACKS]) + (struct rtw89_dev *rtwdev, enum rtw89_chanctx_state state); +}; + struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; enum rtw89_chip_gen chip_gen; @@ -3472,6 +3490,7 @@ struct rtw89_chip_info { /* NULL if no rfe-specific, or a null-terminated array by rfe_parms */ const struct rtw89_rfe_parms_conf *rfe_parms_conf; const struct rtw89_rfe_parms *dflt_parms; + const struct rtw89_chanctx_listener *chanctx_listener; u8 txpwr_factor_rf; u8 txpwr_factor_mac; @@ -3751,6 +3770,11 @@ struct rtw89_chanctx_cfg { enum rtw89_entity_mode { RTW89_ENTITY_MODE_SCC, + RTW89_ENTITY_MODE_MCC_PREPARE, + RTW89_ENTITY_MODE_MCC, + + NUM_OF_RTW89_ENTITY_MODE, + RTW89_ENTITY_MODE_INVALID = NUM_OF_RTW89_ENTITY_MODE, }; struct rtw89_sub_entity { @@ -4407,6 +4431,7 @@ struct rtw89_dev { struct rtw89_antdiv_info antdiv; struct delayed_work track_work; + struct delayed_work chanctx_work; struct delayed_work coex_act1_work; struct delayed_work coex_bt_devinfo_work; struct delayed_work coex_rfk_chk_work; @@ -5341,6 +5366,8 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); +void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, + struct rtw89_chan *chan); void rtw89_set_channel(struct rtw89_dev *rtwdev); void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, struct rtw89_chan *chan); diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 7c3066c0a550..c9ed369015fe 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -414,6 +414,8 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw, rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); rtw89_mac_port_update(rtwdev, rtwvif); rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif); + + rtw89_queue_chanctx_work(rtwdev); } else { /* Abort ongoing scan if cancel_scan isn't issued * when disconnected by peer @@ -477,6 +479,8 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); rtw89_chip_rfk_channel(rtwdev); + + rtw89_queue_chanctx_work(rtwdev); mutex_unlock(&rtwdev->mutex); return 0; diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index b98ec178abe1..917c01e5e9ed 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include "chan.h" #include "coex.h" #include "core.h" #include "debug.h" @@ -257,8 +258,13 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) { struct ieee80211_vif *vif, *found_vif = NULL; struct rtw89_vif *rtwvif; + enum rtw89_entity_mode mode; int count = 0; + mode = rtw89_get_entity_mode(rtwdev); + if (mode == RTW89_ENTITY_MODE_MCC) + goto disable_lps; + rtw89_for_each_rtwvif(rtwdev, rtwvif) { vif = rtwvif_to_vif(rtwvif); @@ -273,10 +279,12 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) if (count == 1 && found_vif->cfg.ps) { rtwdev->lps_enabled = true; - } else { - rtw89_leave_lps(rtwdev); - rtwdev->lps_enabled = false; + return; } + +disable_lps: + rtw89_leave_lps(rtwdev); + rtwdev->lps_enabled = false; } void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) -- cgit From 98fdd77d3df7ba269941f9a262d82a31537cf013 Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Mon, 21 Aug 2023 22:03:45 +0800 Subject: wifi: wlcore: sdio: Use module_sdio_driver macro to simplify the code Use the module_sdio_driver macro to simplify the code, which is the same as declaring with module_init() and module_exit(). Signed-off-by: Li Zetao Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230821140345.3140493-1-lizetao1@huawei.com --- drivers/net/wireless/ti/wlcore/sdio.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index cf8d909fa826..f0686635db46 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -442,18 +442,7 @@ static struct sdio_driver wl1271_sdio_driver = { #endif }; -static int __init wl1271_init(void) -{ - return sdio_register_driver(&wl1271_sdio_driver); -} - -static void __exit wl1271_exit(void) -{ - sdio_unregister_driver(&wl1271_sdio_driver); -} - -module_init(wl1271_init); -module_exit(wl1271_exit); +module_sdio_driver(wl1271_sdio_driver); module_param(dump, bool, 0600); MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); -- cgit From c220d08e1f981c8d381874a55c3c3c76ade43393 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 22 Aug 2023 20:58:17 +0800 Subject: wifi: rtw89: mac: add mac_gen_def::band1_offset to map MAC band1 register address There are two copies of MAC hardware called band0 and band1. Basically, the only difference between them is base address, so we can share functions with a 'band' (or 'mac_idx') argument. The offset of base address of WiFi 6 and 7 are 0x2000 and 0x4000 respectively, so add band1_offset field to new introduced struct mac_gen_def to possibly reuse functions. Using below spatch script to convert callers: @@ expression reg, band; @@ - rtw89_mac_reg_by_idx(reg, band) + rtw89_mac_reg_by_idx(rtwdev, reg, band) @@ expression reg, port, band; @@ - rtw89_mac_reg_by_port(reg, port, band) + rtw89_mac_reg_by_port(rtwdev, reg, port, band) Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-2-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 4 +- drivers/net/wireless/realtek/rtw89/core.h | 2 + drivers/net/wireless/realtek/rtw89/fw.c | 4 +- drivers/net/wireless/realtek/rtw89/mac.c | 171 ++++++++++++++------------ drivers/net/wireless/realtek/rtw89/mac.h | 36 ++++-- drivers/net/wireless/realtek/rtw89/mac80211.c | 6 +- drivers/net/wireless/realtek/rtw89/mac_be.c | 10 ++ drivers/net/wireless/realtek/rtw89/phy.c | 6 +- drivers/net/wireless/realtek/rtw89/rtw8851b.c | 13 +- drivers/net/wireless/realtek/rtw89/rtw8852a.c | 14 +-- drivers/net/wireless/realtek/rtw89/rtw8852b.c | 13 +- drivers/net/wireless/realtek/rtw89/rtw8852c.c | 19 ++- 12 files changed, 165 insertions(+), 133 deletions(-) create mode 100644 drivers/net/wireless/realtek/rtw89/mac_be.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 92fbbcd5dd3f..eca973b95fbb 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2504,7 +2504,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, &roc_chan); rtw89_set_channel(rtwdev); rtw89_write32_clr(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); ieee80211_ready_on_channel(hw); @@ -2525,7 +2525,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_leave_lps(rtwdev); rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 284d8f7a7a0c..2806d1cf2c0d 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -14,6 +14,7 @@ struct rtw89_dev; struct rtw89_pci_info; +struct rtw89_mac_gen_def; extern const struct ieee80211_ops rtw89_ops; @@ -3435,6 +3436,7 @@ struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; enum rtw89_chip_gen chip_gen; const struct rtw89_chip_ops *ops; + const struct rtw89_mac_gen_def *mac_def; const char *fw_basename; u8 fw_format_max; bool try_ce_fw; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 772b0f107f40..ba873a5d1a8d 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -3885,7 +3885,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rx_fltr); } @@ -3903,7 +3903,7 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, return; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index cebefa3b1db3..edfa1a2e677a 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -2082,7 +2082,7 @@ static int addr_cam_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_ADDR_CAM_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_ADDR_CAM_CTRL, mac_idx); val = rtw89_read32(rtwdev, reg); val |= u32_encode_bits(0x7f, B_AX_ADDR_CAM_RANGE_MASK) | @@ -2109,7 +2109,7 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_1, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PREBKF_CFG_1, mac_idx); if (rtwdev->chip->chip_id == RTL8852C) rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK, SIFS_MACTXEN_T1_V1); @@ -2118,14 +2118,14 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx) SIFS_MACTXEN_T1); if (rtwdev->chip->chip_id == RTL8852B || rtwdev->chip->chip_id == RTL8851B) { - reg = rtw89_mac_reg_by_idx(R_AX_SCH_EXT_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SCH_EXT_CTRL, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_PORT_RST_TSF_ADV); } - reg = rtw89_mac_reg_by_idx(R_AX_CCA_CFG_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CCA_CFG_0, mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_BTCCA_EN); - reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PREBKF_CFG_0, mac_idx); if (rtwdev->chip->chip_id == RTL8852C) { val = rtw89_read32_mask(rtwdev, R_AX_SEC_ENG_CTRL, B_AX_TX_PARTIAL_MODE); @@ -2165,13 +2165,13 @@ int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev, switch (type) { case RTW89_MGNT: - reg = rtw89_mac_reg_by_idx(R_AX_MGNT_FLTR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MGNT_FLTR, mac_idx); break; case RTW89_CTRL: - reg = rtw89_mac_reg_by_idx(R_AX_CTRL_FLTR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTRL_FLTR, mac_idx); break; case RTW89_DATA: - reg = rtw89_mac_reg_by_idx(R_AX_DATA_FLTR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_DATA_FLTR, mac_idx); break; default: rtw89_err(rtwdev, "[ERR]set rx filter type err\n"); @@ -2202,9 +2202,9 @@ static int rx_fltr_init(struct rtw89_dev *rtwdev, u8 mac_idx) B_AX_LSIG_PARITY_CHK_EN | B_AX_SIGA_CRC_CHK | B_AX_VHT_SU_SIGB_CRC_CHK | B_AX_VHT_MU_SIGB_CRC_CHK | B_AX_HE_SIGB_CRC_CHK; - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, mac_idx), mac_ftlr); - rtw89_write16(rtwdev, rtw89_mac_reg_by_idx(R_AX_PLCP_HDR_FLTR, mac_idx), + rtw89_write16(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx), plcp_ftlr); return 0; @@ -2224,20 +2224,20 @@ static void _patch_dis_resp_chk(struct rtw89_dev *rtwdev, u8 mac_idx) switch (rtwdev->chip->chip_id) { case RTL8852A: case RTL8852B: - reg = rtw89_mac_reg_by_idx(R_AX_RSP_CHK_SIG, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RSP_CHK_SIG, mac_idx); val32 = rtw89_read32(rtwdev, reg) & ~b_rsp_chk_nav; rtw89_write32(rtwdev, reg, val32); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx); val32 = rtw89_read32(rtwdev, reg) & ~b_rsp_chk_cca; rtw89_write32(rtwdev, reg, val32); break; default: - reg = rtw89_mac_reg_by_idx(R_AX_RSP_CHK_SIG, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RSP_CHK_SIG, mac_idx); val32 = rtw89_read32(rtwdev, reg) | b_rsp_chk_nav; rtw89_write32(rtwdev, reg, val32); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx); val32 = rtw89_read32(rtwdev, reg) | b_rsp_chk_cca; rtw89_write32(rtwdev, reg, val32); break; @@ -2253,7 +2253,7 @@ static int cca_ctrl_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_CCA_CONTROL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CCA_CONTROL, mac_idx); val = rtw89_read32(rtwdev, reg); val |= (B_AX_TB_CHK_BASIC_NAV | B_AX_TB_CHK_BTCCA | B_AX_TB_CHK_EDCCA | B_AX_TB_CHK_CCA_P20 | @@ -2294,7 +2294,7 @@ static int spatial_reuse_init(struct rtw89_dev *rtwdev, u8 mac_idx) ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_RX_SR_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_SR_CTRL, mac_idx); rtw89_write8_clr(rtwdev, reg, B_AX_SR_EN); return 0; @@ -2309,13 +2309,13 @@ static int tmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_MAC_LOOPBACK, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MAC_LOOPBACK, mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_MACLBK_EN); - reg = rtw89_mac_reg_by_idx(R_AX_TCR0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TCR0, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_TCR_UDF_THSD_MASK, TCR_UDF_THSD); - reg = rtw89_mac_reg_by_idx(R_AX_TXD_FIFO_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXD_FIFO_CTRL, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_HIGH_MCS_THRE_MASK, TXDFIFO_HIGH_MCS_THRE); rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_LOW_MCS_THRE_MASK, TXDFIFO_LOW_MCS_THRE); @@ -2333,7 +2333,7 @@ static int trxptcl_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx); val = rtw89_read32(rtwdev, reg); val &= ~B_AX_WMAC_SPEC_SIFS_CCK_MASK; val |= FIELD_PREP(B_AX_WMAC_SPEC_SIFS_CCK_MASK, WMAC_SPEC_SIFS_CCK); @@ -2353,12 +2353,12 @@ static int trxptcl_init(struct rtw89_dev *rtwdev, u8 mac_idx) val |= FIELD_PREP(B_AX_WMAC_SPEC_SIFS_OFDM_MASK, sifs); rtw89_write32(rtwdev, reg, val); - reg = rtw89_mac_reg_by_idx(R_AX_RXTRIG_TEST_USER_2, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RXTRIG_TEST_USER_2, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_RXTRIG_FCSCHK_EN); - reg = rtw89_mac_reg_by_idx(rrsr->ref_rate.addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, rrsr->ref_rate.addr, mac_idx); rtw89_write32_mask(rtwdev, reg, rrsr->ref_rate.mask, rrsr->ref_rate.data); - reg = rtw89_mac_reg_by_idx(rrsr->rsc.addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, rrsr->rsc.addr, mac_idx); rtw89_write32_mask(rtwdev, reg, rrsr->rsc.mask, rrsr->rsc.data); return 0; @@ -2397,10 +2397,10 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (mac_idx == RTW89_MAC_0) rst_bacam(rtwdev); - reg = rtw89_mac_reg_by_idx(R_AX_RESPBA_CAM_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RESPBA_CAM_CTRL, mac_idx); rtw89_write8_set(rtwdev, reg, B_AX_SSN_SEL); - reg = rtw89_mac_reg_by_idx(R_AX_DLK_PROTECT_CTL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_DLK_PROTECT_CTL, mac_idx); val = rtw89_read16(rtwdev, reg); val = u16_replace_bits(val, TRXCFG_RMAC_DATA_TO, B_AX_RX_DLK_DATA_TIME_MASK); @@ -2408,10 +2408,10 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) B_AX_RX_DLK_CCA_TIME_MASK); rtw89_write16(rtwdev, reg, val); - reg = rtw89_mac_reg_by_idx(R_AX_RCR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RCR, mac_idx); rtw89_write8_mask(rtwdev, reg, B_AX_CH_EN_MASK, 0x1); - reg = rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, mac_idx); if (mac_idx == RTW89_MAC_0) rx_qta = rtwdev->mac.dle_info.c0_rx_qta; else @@ -2425,13 +2425,13 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV) { rtw89_write16_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_DLK_PROTECT_CTL, mac_idx), + rtw89_mac_reg_by_idx(rtwdev, R_AX_DLK_PROTECT_CTL, mac_idx), B_AX_RX_DLK_CCA_TIME_MASK, 0); - rtw89_write16_set(rtwdev, rtw89_mac_reg_by_idx(R_AX_RCR, mac_idx), + rtw89_write16_set(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_RCR, mac_idx), BIT(12)); } - reg = rtw89_mac_reg_by_idx(R_AX_PLCP_HDR_FLTR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx); rtw89_write8_clr(rtwdev, reg, B_AX_VHT_SU_SIGB_CRC_CHK); return ret; @@ -2447,7 +2447,7 @@ static int cmac_com_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); val = rtw89_read32(rtwdev, reg); val = u32_replace_bits(val, 0, B_AX_TXSC_20M_MASK); val = u32_replace_bits(val, 0, B_AX_TXSC_40M_MASK); @@ -2455,7 +2455,7 @@ static int cmac_com_init(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write32(rtwdev, reg, val); if (chip_id == RTL8852A || chip_id == RTL8852B) { - reg = rtw89_mac_reg_by_idx(R_AX_PTCL_RRSR1, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_RRSR1, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_RRSR_RATE_EN_MASK, RRSR_OFDM_CCK_EN); } @@ -2485,7 +2485,7 @@ static int ptcl_init(struct rtw89_dev *rtwdev, u8 mac_idx) return ret; if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { - reg = rtw89_mac_reg_by_idx(R_AX_SIFS_SETTING, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SIFS_SETTING, mac_idx); val = rtw89_read32(rtwdev, reg); val = u32_replace_bits(val, S_AX_CTS2S_TH_1K, B_AX_HW_CTS2SELF_PKT_LEN_TH_MASK); @@ -2494,7 +2494,7 @@ static int ptcl_init(struct rtw89_dev *rtwdev, u8 mac_idx) val |= B_AX_HW_CTS2SELF_EN; rtw89_write32(rtwdev, reg, val); - reg = rtw89_mac_reg_by_idx(R_AX_PTCL_FSM_MON, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_FSM_MON, mac_idx); val = rtw89_read32(rtwdev, reg); val = u32_replace_bits(val, S_AX_PTCL_TO_2MS, B_AX_PTCL_TX_ARB_TO_THR_MASK); val &= ~B_AX_PTCL_TX_ARB_TO_MODE; @@ -2531,7 +2531,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_RXDMA_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RXDMA_CTRL_0, mac_idx); rtw89_write8_clr(rtwdev, reg, RX_FULL_MODE); return 0; @@ -2725,7 +2725,7 @@ static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band, static int rtw89_set_hw_sch_tx_en(struct rtw89_dev *rtwdev, u8 mac_idx, u16 tx_en, u16 tx_en_mask) { - u32 reg = rtw89_mac_reg_by_idx(R_AX_CTN_TXEN, mac_idx); + u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_TXEN, mac_idx); u16 val; int ret; @@ -2747,7 +2747,7 @@ static int rtw89_set_hw_sch_tx_en(struct rtw89_dev *rtwdev, u8 mac_idx, static int rtw89_set_hw_sch_tx_en_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en, u32 tx_en_mask) { - u32 reg = rtw89_mac_reg_by_idx(R_AX_CTN_DRV_TXEN, mac_idx); + u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_DRV_TXEN, mac_idx); u32 val; int ret; @@ -2768,7 +2768,7 @@ int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, int ret; *tx_en = rtw89_read16(rtwdev, - rtw89_mac_reg_by_idx(R_AX_CTN_TXEN, mac_idx)); + rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_TXEN, mac_idx)); switch (sel) { case RTW89_SCH_TX_SEL_ALL: @@ -2809,7 +2809,7 @@ int rtw89_mac_stop_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, int ret; *tx_en = rtw89_read32(rtwdev, - rtw89_mac_reg_by_idx(R_AX_CTN_DRV_TXEN, mac_idx)); + rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_DRV_TXEN, mac_idx)); switch (sel) { case RTW89_SCH_TX_SEL_ALL: @@ -3016,7 +3016,7 @@ static int band_idle_ck_b(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_PTCL_TX_CTN_SEL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_TX_CTN_SEL, mac_idx); ret = read_poll_timeout(rtw89_read8, val, (val & B_AX_PTCL_TX_ON_STAT) == 0, @@ -3224,7 +3224,7 @@ static void rtw89_scheduler_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) { u32 reg; - reg = rtw89_mac_reg_by_idx(R_AX_SCHEDULE_ERR_IMR, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SCHEDULE_ERR_IMR, mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_SORT_NON_IDLE_ERR_INT_EN | B_AX_FSM_TIMEOUT_ERR_INT_EN); rtw89_write32_set(rtwdev, reg, B_AX_FSM_TIMEOUT_ERR_INT_EN); @@ -3235,7 +3235,7 @@ static void rtw89_ptcl_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) const struct rtw89_imr_info *imr = rtwdev->chip->imr_info; u32 reg; - reg = rtw89_mac_reg_by_idx(R_AX_PTCL_IMR0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_IMR0, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->ptcl_imr_clr); rtw89_write32_set(rtwdev, reg, imr->ptcl_imr_set); } @@ -3246,12 +3246,12 @@ static void rtw89_cdma_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; u32 reg; - reg = rtw89_mac_reg_by_idx(imr->cdma_imr_0_reg, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, imr->cdma_imr_0_reg, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->cdma_imr_0_clr); rtw89_write32_set(rtwdev, reg, imr->cdma_imr_0_set); if (chip_id == RTL8852C) { - reg = rtw89_mac_reg_by_idx(imr->cdma_imr_1_reg, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, imr->cdma_imr_1_reg, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->cdma_imr_1_clr); rtw89_write32_set(rtwdev, reg, imr->cdma_imr_1_set); } @@ -3262,7 +3262,7 @@ static void rtw89_phy_intf_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) const struct rtw89_imr_info *imr = rtwdev->chip->imr_info; u32 reg; - reg = rtw89_mac_reg_by_idx(imr->phy_intf_imr_reg, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, imr->phy_intf_imr_reg, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->phy_intf_imr_clr); rtw89_write32_set(rtwdev, reg, imr->phy_intf_imr_set); } @@ -3272,7 +3272,7 @@ static void rtw89_rmac_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) const struct rtw89_imr_info *imr = rtwdev->chip->imr_info; u32 reg; - reg = rtw89_mac_reg_by_idx(imr->rmac_imr_reg, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, imr->rmac_imr_reg, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->rmac_imr_clr); rtw89_write32_set(rtwdev, reg, imr->rmac_imr_set); } @@ -3282,7 +3282,7 @@ static void rtw89_tmac_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx) const struct rtw89_imr_info *imr = rtwdev->chip->imr_info; u32 reg; - reg = rtw89_mac_reg_by_idx(imr->tmac_imr_reg, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, imr->tmac_imr_reg, mac_idx); rtw89_write32_clr(rtwdev, reg, imr->tmac_imr_clr); rtw89_write32_set(rtwdev, reg, imr->tmac_imr_set); } @@ -3860,7 +3860,7 @@ static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev, u8 port = rtwvif->port; u32 reg; - reg = rtw89_mac_reg_by_idx(hiq_win_addr[port], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, hiq_win_addr[port], rtwvif->mac_idx); rtw89_write8(rtwdev, reg, win); } @@ -3871,7 +3871,7 @@ static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev, const struct rtw89_port_reg *p = &rtw_port_base; u32 addr; - addr = rtw89_mac_reg_by_idx(R_AX_MD_TSFT_STMP_CTL, rtwvif->mac_idx); + addr = rtw89_mac_reg_by_idx(rtwdev, R_AX_MD_TSFT_STMP_CTL, rtwvif->mac_idx); rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE); rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, @@ -3930,7 +3930,7 @@ static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, bss_color = vif->bss_conf.he_bss_color.color; reg_base = port >= 4 ? R_AX_PTCL_BSS_COLOR_1 : R_AX_PTCL_BSS_COLOR_0; - reg = rtw89_mac_reg_by_idx(reg_base, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx); rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); } @@ -3944,7 +3944,7 @@ static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev, return; if (port == 0) { - reg = rtw89_mac_reg_by_idx(R_AX_MBSSID_CTRL, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MBSSID_CTRL, rtwvif->mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK); } } @@ -3956,7 +3956,7 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, u32 reg; u32 val; - reg = rtw89_mac_reg_by_idx(R_AX_MBSSID_DROP_0, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MBSSID_DROP_0, rtwvif->mac_idx); val = rtw89_read32(rtwdev, reg); val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port)); if (port == 0) @@ -4014,7 +4014,7 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, u32 val, reg; val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu); - reg = rtw89_mac_reg_by_idx(R_AX_PORT0_TSF_SYNC + rtwvif->port * 4, + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PORT0_TSF_SYNC + rtwvif->port * 4, rtwvif->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port); @@ -4204,7 +4204,7 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, rtw89_mac_check_he_obss_narrow_bw_ru_iter, &tolerated); - reg = rtw89_mac_reg_by_idx(R_AX_RXTRIG_TEST_USER_2, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RXTRIG_TEST_USER_2, rtwvif->mac_idx); if (tolerated) rtw89_write32_clr(rtwdev, reg, B_AX_RXTRIG_RU26_DIS); else @@ -4731,7 +4731,7 @@ bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev, { const struct rtw89_dle_mem *dle_mem = rtwdev->chip->dle_mem; enum rtw89_qta_mode mode = dle_mem->mode; - u32 addr = rtw89_mac_reg_by_idx(reg_base, phy_idx); + u32 addr = rtw89_mac_reg_by_idx(rtwdev, reg_base, phy_idx); if (addr < R_AX_PWR_RATE_CTRL || addr > CMAC1_END_ADDR) { rtw89_err(rtwdev, "[TXPWR] addr=0x%x exceed txpwr cr\n", @@ -4760,7 +4760,7 @@ EXPORT_SYMBOL(rtw89_mac_get_txpwr_cr); int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) { - u32 reg = rtw89_mac_reg_by_idx(R_AX_PPDU_STAT, mac_idx); + u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PPDU_STAT, mac_idx); int ret; ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); @@ -4807,7 +4807,7 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) time_th = min_t(u32, time_th >> MAC_AX_TIME_TH_SH, MAC_AX_TIME_TH_MAX); len_th = min_t(u32, len_th >> MAC_AX_LEN_TH_SH, MAC_AX_LEN_TH_MAX); - reg = rtw89_mac_reg_by_idx(R_AX_AGG_LEN_HT_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AGG_LEN_HT_0, mac_idx); rtw89_write16_mask(rtwdev, reg, B_AX_RTS_TXTIME_TH_MASK, time_th); rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th); } @@ -5043,7 +5043,7 @@ int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt) if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_BT_PLT, plt->band); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BT_PLT, plt->band); val = (plt->tx & RTW89_MAC_AX_PLT_LTE_RX ? B_AX_TX_PLT_GNT_LTE_RX : 0) | (plt->tx & RTW89_MAC_AX_PLT_GNT_BT_TX ? B_AX_TX_PLT_GNT_BT_TX : 0) | (plt->tx & RTW89_MAC_AX_PLT_GNT_BT_RX ? B_AX_TX_PLT_GNT_BT_RX : 0) | @@ -5133,7 +5133,7 @@ u16 rtw89_mac_get_plt_cnt(struct rtw89_dev *rtwdev, u8 band) u32 reg; u16 cnt; - reg = rtw89_mac_reg_by_idx(R_AX_BT_PLT, band); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BT_PLT, band); cnt = rtw89_read32_mask(rtwdev, reg, B_AX_BT_PLT_PKT_CNT_MASK); rtw89_write16_set(rtwdev, reg, B_AX_BT_PLT_RST); @@ -5146,7 +5146,7 @@ static void rtw89_mac_bfee_standby_timer(struct rtw89_dev *rtwdev, u8 mac_idx, u32 reg; rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee standby_timer to %d\n", keep); - reg = rtw89_mac_reg_by_idx(R_AX_BFMEE_RESP_OPTION, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx); if (keep) { set_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags); rtw89_write32_mask(rtwdev, reg, B_AX_BFMEE_BFRP_RX_STANDBY_TIMER_MASK, @@ -5165,7 +5165,7 @@ static void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) B_AX_BFMEE_HE_NDPA_EN; rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee ndpa_en to %d\n", en); - reg = rtw89_mac_reg_by_idx(R_AX_BFMEE_RESP_OPTION, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx); if (en) { set_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); rtw89_write32_set(rtwdev, reg, mask); @@ -5187,30 +5187,30 @@ static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx) /* AP mode set tx gid to 63 */ /* STA mode set tx gid to 0(default) */ - reg = rtw89_mac_reg_by_idx(R_AX_BFMER_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMER_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMER_NDP_BFEN); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx); rtw89_write32(rtwdev, reg, CSI_RRSC_BMAP); - reg = rtw89_mac_reg_by_idx(R_AX_BFMEE_RESP_OPTION, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx); val32 = FIELD_PREP(B_AX_BFMEE_NDP_RX_STANDBY_TIMER_MASK, NDP_RX_STANDBY_TIMER); rtw89_write32(rtwdev, reg, val32); rtw89_mac_bfee_standby_timer(rtwdev, mac_idx, true); rtw89_mac_bfee_ctrl(rtwdev, mac_idx, true); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL | B_AX_BFMEE_USE_NSTS | B_AX_BFMEE_CSI_GID_SEL | B_AX_BFMEE_CSI_FORCE_RETE_EN); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_RATE, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RATE, mac_idx); rtw89_write32(rtwdev, reg, u32_encode_bits(CSI_INIT_RATE_HT, B_AX_BFMEE_HT_CSI_RATE_MASK) | u32_encode_bits(CSI_INIT_RATE_VHT, B_AX_BFMEE_VHT_CSI_RATE_MASK) | u32_encode_bits(CSI_INIT_RATE_HE, B_AX_BFMEE_HE_CSI_RATE_MASK)); - reg = rtw89_mac_reg_by_idx(R_AX_CSIRPT_OPTION, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CSIRPT_OPTION, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_CSIPRT_VHTSU_AID_EN | B_AX_CSIPRT_HESU_AID_EN); @@ -5254,7 +5254,7 @@ static int rtw89_mac_set_csi_para_reg(struct rtw89_dev *rtwdev, nc = min(nc, sound_dim); nr = min(nr, sound_dim); - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); val = FIELD_PREP(B_AX_BFMEE_CSIINFO0_NC_MASK, nc) | @@ -5266,9 +5266,9 @@ static int rtw89_mac_set_csi_para_reg(struct rtw89_dev *rtwdev, FIELD_PREP(B_AX_BFMEE_CSIINFO0_STBC_EN, stbc_en); if (port_sel == 0) - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); else - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_CTRL_1, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_1, mac_idx); rtw89_write16(rtwdev, reg, val); @@ -5304,11 +5304,11 @@ static int rtw89_mac_csi_rrsc(struct rtw89_dev *rtwdev, BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); } - reg = rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN); rtw89_write32(rtwdev, - rtw89_mac_reg_by_idx(R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx), + rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx), rrsc); return 0; @@ -5346,19 +5346,21 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n"); p = (__le32 *)conf->mu_group.membership; - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION_EN0, mac_idx), + rtw89_write32(rtwdev, + rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN0, mac_idx), le32_to_cpu(p[0])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION_EN1, mac_idx), + rtw89_write32(rtwdev, + rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN1, mac_idx), le32_to_cpu(p[1])); p = (__le32 *)conf->mu_group.position; - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION0, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION0, mac_idx), le32_to_cpu(p[0])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION1, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION1, mac_idx), le32_to_cpu(p[1])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION2, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION2, mac_idx), le32_to_cpu(p[2])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(R_AX_GID_POSITION3, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION3, mac_idx), le32_to_cpu(p[3])); } @@ -5449,7 +5451,7 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return ret; } - reg = rtw89_mac_reg_by_idx(R_AX_AMPDU_AGG_LIMIT, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK, max_tx_time >> 5); } @@ -5489,7 +5491,7 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return ret; } - reg = rtw89_mac_reg_by_idx(R_AX_AMPDU_AGG_LIMIT, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx); *tx_time = rtw89_read32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK) << 5; } @@ -5531,7 +5533,7 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, return ret; } - reg = rtw89_mac_reg_by_idx(R_AX_TXCNT, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXCNT, mac_idx); *tx_retry = rtw89_read32_mask(rtwdev, reg, B_AX_L_TXCNT_LMT_MASK); } @@ -5550,7 +5552,7 @@ int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, if (ret) return ret; - reg = rtw89_mac_reg_by_idx(R_AX_MUEDCA_EN, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MUEDCA_EN, mac_idx); if (en) rtw89_write16_set(rtwdev, reg, set); else @@ -5673,3 +5675,8 @@ int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, } return ret; } + +const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { + .band1_offset = RTW89_MAC_AX_BAND_REG_OFFSET, +}; +EXPORT_SYMBOL(rtw89_mac_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 0e1570451c2c..26a89130fa48 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -478,6 +478,7 @@ enum rtw89_mac_bf_rrsc_rate { ({typeof(_addr) __addr = (_addr); \ __addr >= R_AX_CMAC_REG_START && __addr <= R_AX_CMAC_REG_END; }) #define RTW89_MAC_AX_BAND_REG_OFFSET 0x2000 +#define RTW89_MAC_BE_BAND_REG_OFFSET 0x4000 #define PTCL_IDLE_POLL_CNT 10000 #define SW_CVR_DUR_US 8 @@ -826,14 +827,25 @@ struct rtw89_mac_size_set { extern const struct rtw89_mac_size_set rtw89_mac_size; -static inline u32 rtw89_mac_reg_by_idx(u32 reg_base, u8 band) +struct rtw89_mac_gen_def { + u32 band1_offset; +}; + +extern const struct rtw89_mac_gen_def rtw89_mac_gen_ax; +extern const struct rtw89_mac_gen_def rtw89_mac_gen_be; + +static inline +u32 rtw89_mac_reg_by_idx(struct rtw89_dev *rtwdev, u32 reg_base, u8 band) { - return band == 0 ? reg_base : (reg_base + 0x2000); + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + return band == 0 ? reg_base : (reg_base + mac->band1_offset); } -static inline u32 rtw89_mac_reg_by_port(u32 base, u8 port, u8 mac_idx) +static inline +u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_idx) { - return rtw89_mac_reg_by_idx(base + port * 0x40, mac_idx); + return rtw89_mac_reg_by_idx(rtwdev, base + port * 0x40, mac_idx); } static inline u32 @@ -841,7 +853,7 @@ rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base) { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); return rtw89_read32(rtwdev, reg); } @@ -851,7 +863,7 @@ rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); return rtw89_read32_mask(rtwdev, reg, mask); } @@ -861,7 +873,7 @@ rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write32(rtwdev, reg, data); } @@ -871,7 +883,7 @@ rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write32_mask(rtwdev, reg, mask, data); } @@ -881,7 +893,7 @@ rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write16_mask(rtwdev, reg, mask, data); } @@ -891,7 +903,7 @@ rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write32_clr(rtwdev, reg, bit); } @@ -901,7 +913,7 @@ rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write16_clr(rtwdev, reg, bit); } @@ -911,7 +923,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, { u32 reg; - reg = rtw89_mac_reg_by_port(base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); rtw89_write32_set(rtwdev, reg, bit); } diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index c9ed369015fe..1f4f126f4667 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -271,13 +271,13 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, } rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); if (!rtwdev->dbcc_en) goto out; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_1), + rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_1), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); @@ -354,7 +354,7 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs); - reg = rtw89_mac_reg_by_idx(ac_to_mu_edca_param[ac], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac], rtwvif->mac_idx); rtw89_write32(rtwdev, reg, val); rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true); diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c new file mode 100644 index 000000000000..05bb8efaad23 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2019-2020 Realtek Corporation + */ + +#include "mac.h" + +const struct rtw89_mac_gen_def rtw89_mac_gen_be = { + .band1_offset = RTW89_MAC_BE_BAND_REG_OFFSET, +}; +EXPORT_SYMBOL(rtw89_mac_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 5ff2871b230b..7c72d92d5c91 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -4568,7 +4568,7 @@ void rtw89_phy_tssi_ctrl_set_fast_mode_cfg(struct rtw89_dev *rtwdev, regs = rtw89_tssi_fastmode_regs_level; for (i = 0; i < RTW89_TSSI_FAST_MODE_NUM; i++) { - reg = rtw89_mac_reg_by_idx(regs[i].addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx); rtw89_write32_mask(rtwdev, reg, regs[i].mask, val); } } @@ -4630,11 +4630,11 @@ void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, data = chip->tssi_dbw_table->data[bandedge_cfg]; for (i = 0; i < RTW89_TSSI_SBW_NUM; i++) { - reg = rtw89_mac_reg_by_idx(regs[i].addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx); rtw89_write32_mask(rtwdev, reg, regs[i].mask, data[i]); } - reg = rtw89_mac_reg_by_idx(R_AX_BANDEDGE_CFG, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BANDEDGE_CFG, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_BANDEDGE_CFG_IDX_MASK, bandedge_cfg); rtw89_phy_tssi_ctrl_set_fast_mode_cfg(rtwdev, mac_idx, bandedge_cfg, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index b5740639e267..ccf96c963bb4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -756,9 +756,9 @@ static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, u8 mac_idx) { - u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx); - u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); - u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); + u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx); u8 txsc20 = 0, txsc40 = 0; switch (chan->band_width) { @@ -1740,14 +1740,14 @@ void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, return; } - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_CTRL, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); pw_ofst = max_t(s8, pw_ofst - 3, -16); - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst); } @@ -2336,6 +2336,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .chip_id = RTL8851B, .chip_gen = RTW89_CHIP_AX, .ops = &rtw8851b_chip_ops, + .mac_def = &rtw89_mac_gen_ax, .fw_basename = RTW8851B_FW_BASENAME, .fw_format_max = RTW8851B_FW_FORMAT_MAX, .try_ce_fw = true, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 41f05276406d..aefc72f24cf2 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -704,10 +704,9 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, u8 mac_idx) { - u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); - u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, - mac_idx); - u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx); + u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx); u8 txsc20 = 0, txsc40 = 0; switch (chan->band_width) { @@ -1380,13 +1379,13 @@ void rtw8852a_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, pw_ofst); return; } - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_CTRL, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); val_1t = pw_ofst; - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, val_1t); val_2t = max(val_1t - 3, -16); - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, val_2t); rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[ULTB] Set TB pwr_offset=(%d, %d)\n", val_1t, val_2t); @@ -2073,6 +2072,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .chip_id = RTL8852A, .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852a_chip_ops, + .mac_def = &rtw89_mac_gen_ax, .fw_basename = RTW8852A_FW_BASENAME, .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index eb2210cb7e09..cd1863e7e6d4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -843,9 +843,9 @@ static void rtw8852b_set_channel_mac(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, u8 mac_idx) { - u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); - u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx); - u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx); + u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx); u8 txsc20 = 0, txsc40 = 0; switch (chan->band_width) { @@ -1725,14 +1725,14 @@ void rtw8852b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, return; } - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_CTRL, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); pw_ofst = max_t(s8, pw_ofst - 3, -16); - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst); } @@ -2505,6 +2505,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .chip_id = RTL8852B, .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852b_chip_ops, + .mac_def = &rtw89_mac_gen_ax, .fw_basename = RTW8852B_FW_BASENAME, .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index b1af72fbf085..4e936e0ba407 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -606,10 +606,9 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, u8 mac_idx) { - u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); - u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, - mac_idx); - u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx); + u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx); u8 txsc20 = 0, txsc40 = 0, txsc80 = 0; u8 rf_mod_val = 0, chk_rate_mask = 0; u32 txsc; @@ -1654,8 +1653,7 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev, rtwdev->hal.cv != CHIP_CAV) { rtw89_phy_write32_idx(rtwdev, R_P80_AT_HIGH_FREQ, B_P80_AT_HIGH_FREQ, 0x0, phy_idx); - reg = rtw89_mac_reg_by_idx(R_P80_AT_HIGH_FREQ_BB_WRP, - phy_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_P80_AT_HIGH_FREQ_BB_WRP, phy_idx); if (chan->primary_channel > chan->channel) { rtw89_phy_write32_mask(rtwdev, R_P80_AT_HIGH_FREQ_RU_ALLOC, @@ -1859,12 +1857,12 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, for (i = 0; i < 4; i++) { /* 1TX */ - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_V1_MASK << (8 * i), val_1t); /* 2TX */ - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_V1_MASK << (8 * i), val_2t); @@ -2181,7 +2179,7 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, for (addr = R_AX_MACID_ANT_TABLE; addr <= R_AX_MACID_ANT_TABLE_LAST; addr += 4) { - reg = rtw89_mac_reg_by_idx(addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx); rtw89_write32(rtwdev, reg, 0); } @@ -2211,7 +2209,7 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, for (i = 0; i < cr_size; i++) { rtw89_debug(rtwdev, RTW89_DBG_TSSI, "0x%x = 0x%x\n", path_com[i].addr, path_com[i].data); - reg = rtw89_mac_reg_by_idx(path_com[i].addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, path_com[i].addr, mac_idx); rtw89_write32(rtwdev, reg, path_com[i].data); } } @@ -2804,6 +2802,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852c_chip_ops, + .mac_def = &rtw89_mac_gen_ax, .fw_basename = RTW8852C_FW_BASENAME, .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, -- cgit From 60168f6c50edd6b972c538aae11cb8861a892c7c Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 22 Aug 2023 20:58:18 +0800 Subject: wifi: rtw89: mac: generalize code to indirectly access WiFi internal memory To diagnose abnormal behavior, we need to dump certain internal memory. For example, dump security CAM when debugging encryption/decryption problems, or dump BA CAM when debugging abnormal BlockAck. Since the indirect address and internal memory base address are different between WiFi 6 and 7 chips, add fields to reuse codes. Also, only WiFi 6 chips initialize DMAC and CMAC tables via this indirect interface, so no need to change the constant register address, and new firmware will help to initialize these tables. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/debug.c | 13 ++++++++----- drivers/net/wireless/realtek/rtw89/mac.c | 25 ++++++++++++++++++------- drivers/net/wireless/realtek/rtw89/mac.h | 5 +++-- drivers/net/wireless/realtek/rtw89/ser.c | 20 +++++++++++++------- 4 files changed, 42 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 48635458c36a..d162e64f6064 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -795,6 +795,9 @@ static void rtw89_debug_dump_mac_mem(struct seq_file *m, struct rtw89_dev *rtwdev, u8 sel, u32 start_addr, u32 len) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 filter_model_addr = mac->filter_model_addr; + u32 indir_access_addr = mac->indir_access_addr; u32 base_addr, start_page, residue; u32 i, j, p, pages; u32 dump_len, remain; @@ -804,17 +807,17 @@ static void rtw89_debug_dump_mac_mem(struct seq_file *m, pages = len / MAC_MEM_DUMP_PAGE_SIZE + 1; start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE; residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE; - base_addr = rtw89_mac_mem_base_addrs[sel]; + base_addr = mac->mem_base_addrs[sel]; base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE; for (p = 0; p < pages; p++) { dump_len = min_t(u32, remain, MAC_MEM_DUMP_PAGE_SIZE); - rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, base_addr); - for (i = R_AX_INDIR_ACCESS_ENTRY + residue; - i < R_AX_INDIR_ACCESS_ENTRY + dump_len;) { + rtw89_write32(rtwdev, filter_model_addr, base_addr); + for (i = indir_access_addr + residue; + i < indir_access_addr + dump_len;) { seq_printf(m, "%08xh:", i); for (j = 0; - j < 4 && i < R_AX_INDIR_ACCESS_ENTRY + dump_len; + j < 4 && i < indir_access_addr + dump_len; j++, i += 4) { val = rtw89_read32(rtwdev, i); seq_printf(m, " %08x", val); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index edfa1a2e677a..e0925a21a096 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -12,7 +12,7 @@ #include "reg.h" #include "util.h" -const u32 rtw89_mac_mem_base_addrs[RTW89_MAC_MEM_NUM] = { +static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = { [RTW89_MAC_MEM_AXIDMA] = AXIDMA_BASE_ADDR, [RTW89_MAC_MEM_SHARED_BUF] = SHARED_BUF_BASE_ADDR, [RTW89_MAC_MEM_DMAC_TBL] = DMAC_TBL_BASE_ADDR, @@ -39,19 +39,21 @@ const u32 rtw89_mac_mem_base_addrs[RTW89_MAC_MEM_NUM] = { static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset, u32 val, enum rtw89_mac_mem_sel sel) { - u32 addr = rtw89_mac_mem_base_addrs[sel] + offset; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 addr = mac->mem_base_addrs[sel] + offset; - rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, addr); - rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY, val); + rtw89_write32(rtwdev, mac->filter_model_addr, addr); + rtw89_write32(rtwdev, mac->indir_access_addr, val); } static u32 rtw89_mac_mem_read(struct rtw89_dev *rtwdev, u32 offset, enum rtw89_mac_mem_sel sel) { - u32 addr = rtw89_mac_mem_base_addrs[sel] + offset; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 addr = mac->mem_base_addrs[sel] + offset; - rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, addr); - return rtw89_read32(rtwdev, R_AX_INDIR_ACCESS_ENTRY); + rtw89_write32(rtwdev, mac->filter_model_addr, addr); + return rtw89_read32(rtwdev, mac->indir_access_addr); } int rtw89_mac_check_mac_en(struct rtw89_dev *rtwdev, u8 mac_idx, @@ -3661,6 +3663,9 @@ static void rtw89_mac_dmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid) { u8 i; + if (rtwdev->chip->chip_gen != RTW89_CHIP_AX) + return; + for (i = 0; i < 4; i++) { rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, DMAC_TBL_BASE_ADDR + (macid << 4) + (i << 2)); @@ -3670,6 +3675,9 @@ static void rtw89_mac_dmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid) static void rtw89_mac_cmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid) { + if (rtwdev->chip->chip_gen != RTW89_CHIP_AX) + return; + rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, CMAC_TBL_BASE_ADDR + macid * CCTL_INFO_SIZE); rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY, 0x4); @@ -5678,5 +5686,8 @@ int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .band1_offset = RTW89_MAC_AX_BAND_REG_OFFSET, + .filter_model_addr = R_AX_FILTER_MODEL_ADDR, + .indir_access_addr = R_AX_INDIR_ACCESS_ENTRY, + .mem_base_addrs = rtw89_mac_mem_base_addrs_ax, }; EXPORT_SYMBOL(rtw89_mac_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 26a89130fa48..b31c78ca27da 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -327,8 +327,6 @@ enum rtw89_mac_mem_sel { RTW89_MAC_MEM_NUM, }; -extern const u32 rtw89_mac_mem_base_addrs[]; - enum rtw89_rpwm_req_pwr_state { RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE = 0, RTW89_MAC_RPWM_REQ_PWR_STATE_BAND0_RFON = 1, @@ -829,6 +827,9 @@ extern const struct rtw89_mac_size_set rtw89_mac_size; struct rtw89_mac_gen_def { u32 band1_offset; + u32 filter_model_addr; + u32 indir_access_addr; + const u32 *mem_base_addrs; }; extern const struct rtw89_mac_gen_def rtw89_mac_gen_ax; diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 0462ba693f6f..c1644353053f 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -529,6 +529,9 @@ static void ser_do_hci_st_hdl(struct rtw89_ser *ser, u8 evt) static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf, u8 sel, u32 start_addr, u32 len) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 filter_model_addr = mac->filter_model_addr; + u32 indir_access_addr = mac->indir_access_addr; u32 *ptr = (u32 *)buf; u32 base_addr, start_page, residue; u32 cnt = 0; @@ -536,14 +539,14 @@ static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf, start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE; residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE; - base_addr = rtw89_mac_mem_base_addrs[sel]; + base_addr = mac->mem_base_addrs[sel]; base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE; while (cnt < len) { - rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, base_addr); + rtw89_write32(rtwdev, filter_model_addr, base_addr); - for (i = R_AX_INDIR_ACCESS_ENTRY + residue; - i < R_AX_INDIR_ACCESS_ENTRY + MAC_MEM_DUMP_PAGE_SIZE; + for (i = indir_access_addr + residue; + i < indir_access_addr + MAC_MEM_DUMP_PAGE_SIZE; i += 4, ptr++) { *ptr = rtw89_read32(rtwdev, i); cnt += 4; @@ -585,6 +588,9 @@ static int rtw89_ser_fw_backtrace_dump(struct rtw89_dev *rtwdev, u8 *buf, const struct __fw_backtrace_entry *ent) { struct __fw_backtrace_info *ptr = (struct __fw_backtrace_info *)buf; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 filter_model_addr = mac->filter_model_addr; + u32 indir_access_addr = mac->indir_access_addr; u32 fwbt_addr = ent->wcpu_addr & RTW89_WCPU_BASE_MASK; u32 fwbt_size = ent->size; u32 fwbt_key = ent->key; @@ -610,10 +616,10 @@ static int rtw89_ser_fw_backtrace_dump(struct rtw89_dev *rtwdev, u8 *buf, } rtw89_debug(rtwdev, RTW89_DBG_SER, "dump fw backtrace start\n"); - rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR, fwbt_addr); + rtw89_write32(rtwdev, filter_model_addr, fwbt_addr); - for (i = R_AX_INDIR_ACCESS_ENTRY; - i < R_AX_INDIR_ACCESS_ENTRY + fwbt_size; + for (i = indir_access_addr; + i < indir_access_addr + fwbt_size; i += RTW89_FW_BACKTRACE_INFO_SIZE, ptr++) { *ptr = (struct __fw_backtrace_info){ .ra = rtw89_read32(rtwdev, i), -- cgit From 3a7e4f56eb184da66b7f60d4b001ce0248a7b519 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 22 Aug 2023 20:58:19 +0800 Subject: wifi: rtw89: mac: define internal memory address for WiFi 7 chip Define base address of WiFi 7 internal memory according to design to provide the same functions as existing WiFi 6 chips. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-4-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/mac.h | 27 +++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/mac_be.c | 27 +++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/reg.h | 2 ++ 3 files changed, 56 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index b31c78ca27da..7c7940093480 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -275,6 +275,7 @@ enum rtw89_mac_dbg_port_sel { /* SRAM mem dump */ #define R_AX_INDIR_ACCESS_ENTRY 0x40000 +#define R_BE_INDIR_ACCESS_ENTRY 0x80000 #define AXIDMA_BASE_ADDR 0x18006000 #define STA_SCHED_BASE_ADDR 0x18808000 @@ -298,6 +299,31 @@ enum rtw89_mac_dbg_port_sel { #define TXDATA_FIFO_1_BASE_ADDR 0x188A1000 #define CPU_LOCAL_BASE_ADDR 0x18003000 +#define WD_PAGE_BASE_ADDR_BE 0x0 +#define CPU_LOCAL_BASE_ADDR_BE 0x18003000 +#define AXIDMA_BASE_ADDR_BE 0x18006000 +#define SHARED_BUF_BASE_ADDR_BE 0x18700000 +#define DMAC_TBL_BASE_ADDR_BE 0x18800000 +#define SHCUT_MACHDR_BASE_ADDR_BE 0x18800800 +#define STA_SCHED_BASE_ADDR_BE 0x18818000 +#define NAT25_CAM_BASE_ADDR_BE 0x18820000 +#define RXPLD_FLTR_CAM_BASE_ADDR_BE 0x18823000 +#define SEC_CAM_BASE_ADDR_BE 0x18824000 +#define WOW_CAM_BASE_ADDR_BE 0x18828000 +#define MLD_TBL_BASE_ADDR_BE 0x18829000 +#define RX_CLSF_CAM_BASE_ADDR_BE 0x1882A000 +#define CMAC_TBL_BASE_ADDR_BE 0x18840000 +#define ADDR_CAM_BASE_ADDR_BE 0x18850000 +#define BSSID_CAM_BASE_ADDR_BE 0x18858000 +#define BA_CAM_BASE_ADDR_BE 0x18859000 +#define BCN_IE_CAM0_BASE_ADDR_BE 0x18860000 +#define TXDATA_FIFO_0_BASE_ADDR_BE 0x18861000 +#define TXD_FIFO_0_BASE_ADDR_BE 0x18862000 +#define BCN_IE_CAM1_BASE_ADDR_BE 0x18880000 +#define TXDATA_FIFO_1_BASE_ADDR_BE 0x18881000 +#define TXD_FIFO_1_BASE_ADDR_BE 0x18881800 +#define DCPU_LOCAL_BASE_ADDR_BE 0x19C02000 + #define CCTL_INFO_SIZE 32 enum rtw89_mac_mem_sel { @@ -322,6 +348,7 @@ enum rtw89_mac_mem_sel { RTW89_MAC_MEM_BSSID_CAM, RTW89_MAC_MEM_TXD_FIFO_0_V1, RTW89_MAC_MEM_TXD_FIFO_1_V1, + RTW89_MAC_MEM_WD_PAGE, /* keep last */ RTW89_MAC_MEM_NUM, diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 05bb8efaad23..ec920978195e 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -3,8 +3,35 @@ */ #include "mac.h" +#include "reg.h" + +static const u32 rtw89_mac_mem_base_addrs_be[RTW89_MAC_MEM_NUM] = { + [RTW89_MAC_MEM_AXIDMA] = AXIDMA_BASE_ADDR_BE, + [RTW89_MAC_MEM_SHARED_BUF] = SHARED_BUF_BASE_ADDR_BE, + [RTW89_MAC_MEM_DMAC_TBL] = DMAC_TBL_BASE_ADDR_BE, + [RTW89_MAC_MEM_SHCUT_MACHDR] = SHCUT_MACHDR_BASE_ADDR_BE, + [RTW89_MAC_MEM_STA_SCHED] = STA_SCHED_BASE_ADDR_BE, + [RTW89_MAC_MEM_RXPLD_FLTR_CAM] = RXPLD_FLTR_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_SECURITY_CAM] = SEC_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_WOW_CAM] = WOW_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_CMAC_TBL] = CMAC_TBL_BASE_ADDR_BE, + [RTW89_MAC_MEM_ADDR_CAM] = ADDR_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_BA_CAM] = BA_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_BCN_IE_CAM0] = BCN_IE_CAM0_BASE_ADDR_BE, + [RTW89_MAC_MEM_BCN_IE_CAM1] = BCN_IE_CAM1_BASE_ADDR_BE, + [RTW89_MAC_MEM_TXD_FIFO_0] = TXD_FIFO_0_BASE_ADDR_BE, + [RTW89_MAC_MEM_TXD_FIFO_1] = TXD_FIFO_1_BASE_ADDR_BE, + [RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR_BE, + [RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR_BE, + [RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR_BE, + [RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR_BE, + [RTW89_MAC_MEM_WD_PAGE] = WD_PAGE_BASE_ADDR_BE, +}; const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .band1_offset = RTW89_MAC_BE_BAND_REG_OFFSET, + .filter_model_addr = R_BE_FILTER_MODEL_ADDR, + .indir_access_addr = R_BE_INDIR_ACCESS_ENTRY, + .mem_base_addrs = rtw89_mac_mem_base_addrs_be, }; EXPORT_SYMBOL(rtw89_mac_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 2d34b43cda3a..cab07cc993f0 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -3625,6 +3625,8 @@ #define B_AX_GNT_BT_TX_SW_VAL BIT(1) #define B_AX_GNT_BT_TX_SW_CTRL BIT(0) +#define R_BE_FILTER_MODEL_ADDR 0x0C04 + #define RR_MOD 0x00 #define RR_MOD_V1 0x10000 #define RR_MOD_IQK GENMASK(19, 4) -- cgit From 9d87e7dc930e149def617c152f03ed97e3d7d899 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 22 Aug 2023 20:58:20 +0800 Subject: wifi: rtw89: mac: define register address of rx_filter to generalize code rx_filter is used to decide which kind of packets are received to driver, or just dropped by MAC layer to reduce bus traffic. The bit definitions of old and new chips are the sames, but only address is changed, so define a field to generalize usage. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.c | 6 ++++-- drivers/net/wireless/realtek/rtw89/fw.c | 6 ++++-- drivers/net/wireless/realtek/rtw89/mac.c | 1 + drivers/net/wireless/realtek/rtw89/mac.h | 1 + drivers/net/wireless/realtek/rtw89/mac80211.c | 5 +++-- drivers/net/wireless/realtek/rtw89/mac_be.c | 1 + drivers/net/wireless/realtek/rtw89/reg.h | 19 +++++++++++++++++++ drivers/net/wireless/realtek/rtw89/wow.c | 3 ++- 8 files changed, 35 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index eca973b95fbb..133bf289bacb 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2477,6 +2477,7 @@ out: void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; struct cfg80211_chan_def roc_chan; @@ -2504,7 +2505,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, &roc_chan); rtw89_set_channel(rtwdev); rtw89_write32_clr(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); ieee80211_ready_on_channel(hw); @@ -2512,6 +2513,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; struct rtw89_vif *tmp; @@ -2525,7 +2527,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_leave_lps(rtwdev); rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index ba873a5d1a8d..df1dc2f43c86 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -3863,6 +3863,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_scan_request *scan_req) { struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct cfg80211_scan_request *req = &scan_req->req; u32 rx_fltr = rtwdev->hal.rx_fltr; u8 mac_addr[ETH_ALEN]; @@ -3885,7 +3886,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rx_fltr); } @@ -3893,6 +3894,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool aborted) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct cfg80211_scan_info info = { .aborted = aborted, @@ -3903,7 +3905,7 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, return; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index e0925a21a096..fab9f5004a75 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -5689,5 +5689,6 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .filter_model_addr = R_AX_FILTER_MODEL_ADDR, .indir_access_addr = R_AX_INDIR_ACCESS_ENTRY, .mem_base_addrs = rtw89_mac_mem_base_addrs_ax, + .rx_fltr = R_AX_RX_FLTR_OPT, }; EXPORT_SYMBOL(rtw89_mac_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 7c7940093480..7cf34137c0bc 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -857,6 +857,7 @@ struct rtw89_mac_gen_def { u32 filter_model_addr; u32 indir_access_addr; const u32 *mem_base_addrs; + u32 rx_fltr; }; extern const struct rtw89_mac_gen_def rtw89_mac_gen_ax; diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 1f4f126f4667..5e48618706d9 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -224,6 +224,7 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct rtw89_dev *rtwdev = hw->priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); @@ -271,13 +272,13 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, } rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_0), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); if (!rtwdev->dbcc_en) goto out; rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, RTW89_MAC_1), + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_1), B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index ec920978195e..9a63fb35e867 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -33,5 +33,6 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .filter_model_addr = R_BE_FILTER_MODEL_ADDR, .indir_access_addr = R_BE_INDIR_ACCESS_ENTRY, .mem_base_addrs = rtw89_mac_mem_base_addrs_be, + .rx_fltr = R_BE_RX_FLTR_OPT, }; EXPORT_SYMBOL(rtw89_mac_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index cab07cc993f0..eab26039242a 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -3627,6 +3627,25 @@ #define R_BE_FILTER_MODEL_ADDR 0x0C04 +#define R_BE_RX_FLTR_OPT 0x11420 +#define R_BE_RX_FLTR_OPT_C1 0x15420 +#define B_BE_UID_FILTER_MASK GENMASK(31, 24) +#define B_BE_UNSPT_TYPE BIT(22) +#define B_BE_RX_MPDU_MAX_LEN_MASK GENMASK(21, 16) +#define B_BE_A_FTM_REQ BIT(14) +#define B_BE_A_ERR_PKT BIT(13) +#define B_BE_A_UNSUP_PKT BIT(12) +#define B_BE_A_CRC32_ERR BIT(11) +#define B_BE_A_BCN_CHK_RULE_MASK GENMASK(9, 8) +#define B_BE_A_BCN_CHK_EN BIT(7) +#define B_BE_A_MC_LIST_CAM_MATCH BIT(6) +#define B_BE_A_BC_CAM_MATCH BIT(5) +#define B_BE_A_UC_CAM_MATCH BIT(4) +#define B_BE_A_MC BIT(3) +#define B_BE_A_BC BIT(2) +#define B_BE_A_A1_MATCH BIT(1) +#define B_BE_SNIFFER_MODE BIT(0) + #define RR_MOD 0x00 #define RR_MOD_V1 0x10000 #define RR_MOD_IQK GENMASK(19, 4) diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 364e54622150..aa9efca04025 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -40,6 +40,7 @@ static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev) static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; int ret; if (enable_wow) { @@ -49,7 +50,7 @@ static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow) return ret; } rtw89_write32_set(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP); - rtw89_write32_clr(rtwdev, R_AX_RX_FLTR_OPT, B_AX_SNIFFER_MODE); + rtw89_write32_clr(rtwdev, mac->rx_fltr, B_AX_SNIFFER_MODE); rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); rtw89_write32(rtwdev, R_AX_ACTION_FWD0, 0); rtw89_write32(rtwdev, R_AX_ACTION_FWD1, 0); -- cgit From 1165f5719229882442e67ad845a07491b0795ded Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Tue, 22 Aug 2023 20:58:21 +0800 Subject: wifi: rtw89: phy: add phy_gen_def::cr_base to support WiFi 7 chips cr_base is base address of PHY control register. The base of WiFi 6 and 7 chips are 0x1_0000 and 0x2_0000 respectively, so define them accordingly. For example, if PHY address is 0x1330, absolute address is 0x1_1330 for WiFi 6 chips, and 0x2_1330 for WiFi 7 chips. Meanwhile, there are two copies of PHY hardware named PHY0 and PHY1. The offset between them is 0x2_0000, so the base address of PHY0 and PHY1 are 0x2_0000 and 0x4_0000 respectively. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-6-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 2 ++ drivers/net/wireless/realtek/rtw89/phy.c | 8 +++++ drivers/net/wireless/realtek/rtw89/phy.h | 48 +++++++++++++++++++++------ drivers/net/wireless/realtek/rtw89/phy_be.c | 10 ++++++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + 8 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 drivers/net/wireless/realtek/rtw89/phy_be.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 2806d1cf2c0d..17f6418e4404 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -15,6 +15,7 @@ struct rtw89_dev; struct rtw89_pci_info; struct rtw89_mac_gen_def; +struct rtw89_phy_gen_def; extern const struct ieee80211_ops rtw89_ops; @@ -3437,6 +3438,7 @@ struct rtw89_chip_info { enum rtw89_chip_gen chip_gen; const struct rtw89_chip_ops *ops; const struct rtw89_mac_gen_def *mac_def; + const struct rtw89_phy_gen_def *phy_def; const char *fw_basename; u8 fw_format_max; bool try_ce_fw; diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 7c72d92d5c91..85d3205d6e68 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -1448,6 +1448,9 @@ static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr) u32 phy_page = addr >> 8; u32 ofst = 0; + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return addr < 0x10000 ? 0x20000 : 0; + switch (phy_page) { case 0x6: case 0x7: @@ -4732,3 +4735,8 @@ void rtw89_phy_config_edcca(struct rtw89_dev *rtwdev, bool scan) rtw89_phy_write32(rtwdev, reg, hal->edcca_bak); } } + +const struct rtw89_phy_gen_def rtw89_phy_gen_ax = { + .cr_base = 0x10000, +}; +EXPORT_SYMBOL(rtw89_phy_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index ab174a0ba488..36a24676b2fe 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -7,7 +7,6 @@ #include "core.h" -#define RTW89_PHY_ADDR_OFFSET 0x10000 #define RTW89_RF_ADDR_ADSEL_MASK BIT(16) #define get_phy_headline(addr) FIELD_GET(GENMASK(31, 28), addr) @@ -337,61 +336,88 @@ struct rtw89_nbi_reg_def { struct rtw89_reg_def notch2_en; }; +struct rtw89_phy_gen_def { + u32 cr_base; +}; + +extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax; +extern const struct rtw89_phy_gen_def rtw89_phy_gen_be; + static inline void rtw89_phy_write8(struct rtw89_dev *rtwdev, u32 addr, u8 data) { - rtw89_write8(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write8(rtwdev, addr + phy->cr_base, data); } static inline void rtw89_phy_write16(struct rtw89_dev *rtwdev, u32 addr, u16 data) { - rtw89_write16(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write16(rtwdev, addr + phy->cr_base, data); } static inline void rtw89_phy_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data) { - rtw89_write32(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, data); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write32(rtwdev, addr + phy->cr_base, data); } static inline void rtw89_phy_write32_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits) { - rtw89_write32_set(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, bits); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write32_set(rtwdev, addr + phy->cr_base, bits); } static inline void rtw89_phy_write32_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits) { - rtw89_write32_clr(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, bits); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write32_clr(rtwdev, addr + phy->cr_base, bits); } static inline void rtw89_phy_write32_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data) { - rtw89_write32_mask(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, mask, data); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + rtw89_write32_mask(rtwdev, addr + phy->cr_base, mask, data); } static inline u8 rtw89_phy_read8(struct rtw89_dev *rtwdev, u32 addr) { - return rtw89_read8(rtwdev, addr | RTW89_PHY_ADDR_OFFSET); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + return rtw89_read8(rtwdev, addr + phy->cr_base); } static inline u16 rtw89_phy_read16(struct rtw89_dev *rtwdev, u32 addr) { - return rtw89_read16(rtwdev, addr | RTW89_PHY_ADDR_OFFSET); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + return rtw89_read16(rtwdev, addr + phy->cr_base); } static inline u32 rtw89_phy_read32(struct rtw89_dev *rtwdev, u32 addr) { - return rtw89_read32(rtwdev, addr | RTW89_PHY_ADDR_OFFSET); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + return rtw89_read32(rtwdev, addr + phy->cr_base); } static inline u32 rtw89_phy_read32_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask) { - return rtw89_read32_mask(rtwdev, addr | RTW89_PHY_ADDR_OFFSET, mask); + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + + return rtw89_read32_mask(rtwdev, addr + phy->cr_base, mask); } static inline diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c new file mode 100644 index 000000000000..143f900d29a6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2023 Realtek Corporation + */ + +#include "phy.h" + +const struct rtw89_phy_gen_def rtw89_phy_gen_be = { + .cr_base = 0x20000, +}; +EXPORT_SYMBOL(rtw89_phy_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index ccf96c963bb4..52eb7030fd0b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2337,6 +2337,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .chip_gen = RTW89_CHIP_AX, .ops = &rtw8851b_chip_ops, .mac_def = &rtw89_mac_gen_ax, + .phy_def = &rtw89_phy_gen_ax, .fw_basename = RTW8851B_FW_BASENAME, .fw_format_max = RTW8851B_FW_FORMAT_MAX, .try_ce_fw = true, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index aefc72f24cf2..eb6aad3bbb85 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2073,6 +2073,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852a_chip_ops, .mac_def = &rtw89_mac_gen_ax, + .phy_def = &rtw89_phy_gen_ax, .fw_basename = RTW8852A_FW_BASENAME, .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index cd1863e7e6d4..49664cc44f36 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2506,6 +2506,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852b_chip_ops, .mac_def = &rtw89_mac_gen_ax, + .phy_def = &rtw89_phy_gen_ax, .fw_basename = RTW8852B_FW_BASENAME, .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 4e936e0ba407..abd01e808d83 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2803,6 +2803,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852c_chip_ops, .mac_def = &rtw89_mac_gen_ax, + .phy_def = &rtw89_phy_gen_ax, .fw_basename = RTW8852C_FW_BASENAME, .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, -- cgit From 058b207481977c4fab7f5d979aa783cf536e21f3 Mon Sep 17 00:00:00 2001 From: Cheng-Chieh Hsieh Date: Tue, 22 Aug 2023 20:58:22 +0800 Subject: wifi: rtw89: phy: modify register setting of ENV_MNTR, PHYSTS and DIG The ENV_MNTR(environment monitor) is the dynamic mechanism which based on the HW of CCX(Cisco Compatible Extensions) which provide the channel loading and noisy level indicator to debug or support the 802.11k. The PHYSTS provide the detail PHY information per packet we received for debugging. The DIG(dynamic initial gain) is the dynamic mechanism to adjust the packet detect power level by received signal strength to avoid false detection of the WiFi packet. The address of registers used for ENV_MNTR, PHYSTS and DIG of WiFi 7 IC are different with WiFi 6 series, so we modify the method to access the register address in order to compatible with all WiFi 7 and 6 ICs. Signed-off-by: Cheng-Chieh Hsieh Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822125822.23817-7-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 4 + drivers/net/wireless/realtek/rtw89/phy.c | 223 ++++++++++++++++++-------- drivers/net/wireless/realtek/rtw89/phy.h | 66 ++++++++ drivers/net/wireless/realtek/rtw89/phy_be.c | 67 ++++++++ drivers/net/wireless/realtek/rtw89/reg.h | 13 ++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 4 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 4 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 4 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 4 + 9 files changed, 325 insertions(+), 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 17f6418e4404..04ce221730f9 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3381,6 +3381,10 @@ struct rtw89_dig_regs { u32 seg0_pd_reg; u32 pd_lower_bound_mask; u32 pd_spatial_reuse_en; + u32 bmode_pd_reg; + u32 bmode_cca_rssi_limit_en; + u32 bmode_pd_lower_bound_reg; + u32 bmode_rssi_nocca_low_th_mask; struct rtw89_reg_def p0_lna_init; struct rtw89_reg_def p1_lna_init; struct rtw89_reg_def p0_tia_init; diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 85d3205d6e68..7139146cb3fa 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -3237,7 +3237,9 @@ static u32 rtw89_phy_ccx_idx_to_us(struct rtw89_dev *rtwdev, u16 idx) static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; env->ccx_manual_ctrl = false; env->ccx_ongoing = false; @@ -3245,10 +3247,10 @@ static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev) env->ccx_period = 0; env->ccx_unit_idx = RTW89_CCX_32_US; - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_EN_MSK, 1); - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_TRIG_OPT_MSK, 1); - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 1); - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_EDCCA_OPT_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->en_mask, 1); + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->trig_opt_mask, 1); + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1); + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->edcca_opt_mask, RTW89_CCX_EDCCA_BW20_0); } @@ -3363,25 +3365,27 @@ ifs_update_finished: static void rtw89_phy_ifs_clm_set_th_reg(struct rtw89_dev *rtwdev) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; u8 i = 0; - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T1, B_IFS_T1_TH_LOW_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_l_mask, env->ifs_clm_th_l[0]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T2, B_IFS_T2_TH_LOW_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_l_mask, env->ifs_clm_th_l[1]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T3, B_IFS_T3_TH_LOW_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_l_mask, env->ifs_clm_th_l[2]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T4, B_IFS_T4_TH_LOW_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_l_mask, env->ifs_clm_th_l[3]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T1, B_IFS_T1_TH_HIGH_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_h_mask, env->ifs_clm_th_h[0]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T2, B_IFS_T2_TH_HIGH_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_h_mask, env->ifs_clm_th_h[1]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T3, B_IFS_T3_TH_HIGH_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_h_mask, env->ifs_clm_th_h[2]); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T4, B_IFS_T4_TH_HIGH_MSK, + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_h_mask, env->ifs_clm_th_h[3]); for (i = 0; i < RTW89_IFS_CLM_NUM; i++) @@ -3392,7 +3396,9 @@ static void rtw89_phy_ifs_clm_set_th_reg(struct rtw89_dev *rtwdev) static void rtw89_phy_ifs_clm_setting_init(struct rtw89_dev *rtwdev) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; struct rtw89_ccx_para_info para = {0}; env->ifs_clm_app = RTW89_IFS_CLM_BACKGROUND; @@ -3402,12 +3408,11 @@ static void rtw89_phy_ifs_clm_setting_init(struct rtw89_dev *rtwdev) if (rtw89_phy_ifs_clm_th_update_check(rtwdev, ¶)) rtw89_phy_ifs_clm_set_th_reg(rtwdev); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COLLECT_EN, - true); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T1, B_IFS_T1_EN_MSK, true); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T2, B_IFS_T2_EN_MSK, true); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T3, B_IFS_T3_EN_MSK, true); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_T4, B_IFS_T4_EN_MSK, true); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_collect_en_mask, true); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_en_mask, true); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_en_mask, true); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_en_mask, true); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_en_mask, true); } static int rtw89_phy_ccx_racing_ctrl(struct rtw89_dev *rtwdev, @@ -3444,12 +3449,14 @@ static int rtw89_phy_ccx_racing_ctrl(struct rtw89_dev *rtwdev, static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; - rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COUNTER_CLR_MSK, 0); - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 0); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COUNTER_CLR_MSK, 1); - rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 1); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 0); + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 0); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 1); + rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1); env->ccx_ongoing = true; } @@ -3521,63 +3528,79 @@ static void rtw89_phy_ifs_clm_get_utility(struct rtw89_dev *rtwdev) static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; u8 i = 0; - if (rtw89_phy_read32_mask(rtwdev, R_IFSCNT, B_IFSCNT_DONE_MSK) == 0) { + if (rtw89_phy_read32_mask(rtwdev, ccx->ifs_total_addr, + ccx->ifs_cnt_done_mask) == 0) { rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Get IFS_CLM report Fail\n"); return false; } env->ifs_clm_tx = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_TX_CNT, - B_IFS_CLM_TX_CNT_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_tx_cnt_addr, + ccx->ifs_clm_tx_cnt_msk); env->ifs_clm_edcca_excl_cca = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_TX_CNT, - B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_tx_cnt_addr, + ccx->ifs_clm_edcca_excl_cca_fa_mask); env->ifs_clm_cckcca_excl_fa = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_CCA, - B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_cca_addr, + ccx->ifs_clm_cckcca_excl_fa_mask); env->ifs_clm_ofdmcca_excl_fa = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_CCA, - B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_cca_addr, + ccx->ifs_clm_ofdmcca_excl_fa_mask); env->ifs_clm_cckfa = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_FA, - B_IFS_CLM_CCK_FA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_fa_addr, + ccx->ifs_clm_cck_fa_mask); env->ifs_clm_ofdmfa = - rtw89_phy_read32_mask(rtwdev, R_IFS_CLM_FA, - B_IFS_CLM_OFDM_FA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_fa_addr, + ccx->ifs_clm_ofdm_fa_mask); env->ifs_clm_his[0] = - rtw89_phy_read32_mask(rtwdev, R_IFS_HIS, B_IFS_T1_HIS_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr, + ccx->ifs_t1_his_mask); env->ifs_clm_his[1] = - rtw89_phy_read32_mask(rtwdev, R_IFS_HIS, B_IFS_T2_HIS_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr, + ccx->ifs_t2_his_mask); env->ifs_clm_his[2] = - rtw89_phy_read32_mask(rtwdev, R_IFS_HIS, B_IFS_T3_HIS_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr, + ccx->ifs_t3_his_mask); env->ifs_clm_his[3] = - rtw89_phy_read32_mask(rtwdev, R_IFS_HIS, B_IFS_T4_HIS_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr, + ccx->ifs_t4_his_mask); env->ifs_clm_avg[0] = - rtw89_phy_read32_mask(rtwdev, R_IFS_AVG_L, B_IFS_T1_AVG_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_l_addr, + ccx->ifs_t1_avg_mask); env->ifs_clm_avg[1] = - rtw89_phy_read32_mask(rtwdev, R_IFS_AVG_L, B_IFS_T2_AVG_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_l_addr, + ccx->ifs_t2_avg_mask); env->ifs_clm_avg[2] = - rtw89_phy_read32_mask(rtwdev, R_IFS_AVG_H, B_IFS_T3_AVG_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_h_addr, + ccx->ifs_t3_avg_mask); env->ifs_clm_avg[3] = - rtw89_phy_read32_mask(rtwdev, R_IFS_AVG_H, B_IFS_T4_AVG_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_h_addr, + ccx->ifs_t4_avg_mask); env->ifs_clm_cca[0] = - rtw89_phy_read32_mask(rtwdev, R_IFS_CCA_L, B_IFS_T1_CCA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_l_addr, + ccx->ifs_t1_cca_mask); env->ifs_clm_cca[1] = - rtw89_phy_read32_mask(rtwdev, R_IFS_CCA_L, B_IFS_T2_CCA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_l_addr, + ccx->ifs_t2_cca_mask); env->ifs_clm_cca[2] = - rtw89_phy_read32_mask(rtwdev, R_IFS_CCA_H, B_IFS_T3_CCA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_h_addr, + ccx->ifs_t3_cca_mask); env->ifs_clm_cca[3] = - rtw89_phy_read32_mask(rtwdev, R_IFS_CCA_H, B_IFS_T4_CCA_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_h_addr, + ccx->ifs_t4_cca_mask); env->ifs_clm_total_ifs = - rtw89_phy_read32_mask(rtwdev, R_IFSCNT, B_IFSCNT_TOTAL_CNT_MSK); + rtw89_phy_read32_mask(rtwdev, ccx->ifs_total_addr, + ccx->ifs_total_mask); rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "IFS-CLM total_ifs = %d\n", env->ifs_clm_total_ifs); @@ -3605,7 +3628,9 @@ static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev) static int rtw89_phy_ifs_clm_set(struct rtw89_dev *rtwdev, struct rtw89_ccx_para_info *para) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; u32 period = 0; u32 unit_idx = 0; @@ -3621,10 +3646,11 @@ static int rtw89_phy_ifs_clm_set(struct rtw89_dev *rtwdev, if (para->mntr_time != env->ifs_clm_mntr_time) { rtw89_phy_ccx_ms_to_period_unit(rtwdev, para->mntr_time, &period, &unit_idx); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, - B_IFS_CLM_PERIOD_MSK, period); - rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, - B_IFS_CLM_COUNTER_UNIT_MSK, unit_idx); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, + ccx->ifs_clm_period_mask, period); + rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, + ccx->ifs_clm_cnt_unit_mask, + unit_idx); rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Update IFS-CLM time ((%d)) -> ((%d))\n", @@ -3742,16 +3768,19 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, bool enable, enum rtw89_phy_idx phy_idx) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + const struct rtw89_physts_regs *physts = phy->physts; + if (enable) { - rtw89_phy_write32_clr(rtwdev, R_PLCP_HISTOGRAM, - B_STS_DIS_TRIG_BY_FAIL); - rtw89_phy_write32_clr(rtwdev, R_PLCP_HISTOGRAM, - B_STS_DIS_TRIG_BY_BRK); + rtw89_phy_write32_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask); + rtw89_phy_write32_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask); } else { - rtw89_phy_write32_set(rtwdev, R_PLCP_HISTOGRAM, - B_STS_DIS_TRIG_BY_FAIL); - rtw89_phy_write32_set(rtwdev, R_PLCP_HISTOGRAM, - B_STS_DIS_TRIG_BY_BRK); + rtw89_phy_write32_set(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask); + rtw89_phy_write32_set(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask); } } @@ -4179,10 +4208,10 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, u8 rssi, "igi=%d, cck_ccaTH=%d, backoff=%d, cck_PD_low=((%d))dB\n", final_rssi, cck_cca_th, under_region, pd_val); - rtw89_phy_write32_mask(rtwdev, R_BMODE_PDTH_EN_V1, - B_BMODE_PDTH_LIMIT_EN_MSK_V1, enable); - rtw89_phy_write32_mask(rtwdev, R_BMODE_PDTH_V1, - B_BMODE_PDTH_LOWER_BOUND_MSK_V1, pd_val); + rtw89_phy_write32_mask(rtwdev, dig_regs->bmode_pd_reg, + dig_regs->bmode_cca_rssi_limit_en, enable); + rtw89_phy_write32_mask(rtwdev, dig_regs->bmode_pd_lower_bound_reg, + dig_regs->bmode_rssi_nocca_low_th_mask, pd_val); } void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev) @@ -4736,7 +4765,73 @@ void rtw89_phy_config_edcca(struct rtw89_dev *rtwdev, bool scan) } } +static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = { + .setting_addr = R_CCX, + .edcca_opt_mask = B_CCX_EDCCA_OPT_MSK, + .measurement_trig_mask = B_MEASUREMENT_TRIG_MSK, + .trig_opt_mask = B_CCX_TRIG_OPT_MSK, + .en_mask = B_CCX_EN_MSK, + .ifs_cnt_addr = R_IFS_COUNTER, + .ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK, + .ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK, + .ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK, + .ifs_collect_en_mask = B_IFS_COLLECT_EN, + .ifs_t1_addr = R_IFS_T1, + .ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK, + .ifs_t1_en_mask = B_IFS_T1_EN_MSK, + .ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK, + .ifs_t2_addr = R_IFS_T2, + .ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK, + .ifs_t2_en_mask = B_IFS_T2_EN_MSK, + .ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK, + .ifs_t3_addr = R_IFS_T3, + .ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK, + .ifs_t3_en_mask = B_IFS_T3_EN_MSK, + .ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK, + .ifs_t4_addr = R_IFS_T4, + .ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK, + .ifs_t4_en_mask = B_IFS_T4_EN_MSK, + .ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK, + .ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT, + .ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK, + .ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK, + .ifs_clm_cca_addr = R_IFS_CLM_CCA, + .ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK, + .ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK, + .ifs_clm_fa_addr = R_IFS_CLM_FA, + .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK, + .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK, + .ifs_his_addr = R_IFS_HIS, + .ifs_t4_his_mask = B_IFS_T4_HIS_MSK, + .ifs_t3_his_mask = B_IFS_T3_HIS_MSK, + .ifs_t2_his_mask = B_IFS_T2_HIS_MSK, + .ifs_t1_his_mask = B_IFS_T1_HIS_MSK, + .ifs_avg_l_addr = R_IFS_AVG_L, + .ifs_t2_avg_mask = B_IFS_T2_AVG_MSK, + .ifs_t1_avg_mask = B_IFS_T1_AVG_MSK, + .ifs_avg_h_addr = R_IFS_AVG_H, + .ifs_t4_avg_mask = B_IFS_T4_AVG_MSK, + .ifs_t3_avg_mask = B_IFS_T3_AVG_MSK, + .ifs_cca_l_addr = R_IFS_CCA_L, + .ifs_t2_cca_mask = B_IFS_T2_CCA_MSK, + .ifs_t1_cca_mask = B_IFS_T1_CCA_MSK, + .ifs_cca_h_addr = R_IFS_CCA_H, + .ifs_t4_cca_mask = B_IFS_T4_CCA_MSK, + .ifs_t3_cca_mask = B_IFS_T3_CCA_MSK, + .ifs_total_addr = R_IFSCNT, + .ifs_cnt_done_mask = B_IFSCNT_DONE_MSK, + .ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK, +}; + +static const struct rtw89_physts_regs rtw89_physts_regs_ax = { + .setting_addr = R_PLCP_HISTOGRAM, + .dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL, + .dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK, +}; + const struct rtw89_phy_gen_def rtw89_phy_gen_ax = { .cr_base = 0x10000, + .ccx = &rtw89_ccx_regs_ax, + .physts = &rtw89_physts_regs_ax, }; EXPORT_SYMBOL(rtw89_phy_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 36a24676b2fe..d6dc0cbbae43 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -336,8 +336,74 @@ struct rtw89_nbi_reg_def { struct rtw89_reg_def notch2_en; }; +struct rtw89_ccx_regs { + u32 setting_addr; + u32 edcca_opt_mask; + u32 measurement_trig_mask; + u32 trig_opt_mask; + u32 en_mask; + u32 ifs_cnt_addr; + u32 ifs_clm_period_mask; + u32 ifs_clm_cnt_unit_mask; + u32 ifs_clm_cnt_clear_mask; + u32 ifs_collect_en_mask; + u32 ifs_t1_addr; + u32 ifs_t1_th_h_mask; + u32 ifs_t1_en_mask; + u32 ifs_t1_th_l_mask; + u32 ifs_t2_addr; + u32 ifs_t2_th_h_mask; + u32 ifs_t2_en_mask; + u32 ifs_t2_th_l_mask; + u32 ifs_t3_addr; + u32 ifs_t3_th_h_mask; + u32 ifs_t3_en_mask; + u32 ifs_t3_th_l_mask; + u32 ifs_t4_addr; + u32 ifs_t4_th_h_mask; + u32 ifs_t4_en_mask; + u32 ifs_t4_th_l_mask; + u32 ifs_clm_tx_cnt_addr; + u32 ifs_clm_edcca_excl_cca_fa_mask; + u32 ifs_clm_tx_cnt_msk; + u32 ifs_clm_cca_addr; + u32 ifs_clm_ofdmcca_excl_fa_mask; + u32 ifs_clm_cckcca_excl_fa_mask; + u32 ifs_clm_fa_addr; + u32 ifs_clm_ofdm_fa_mask; + u32 ifs_clm_cck_fa_mask; + u32 ifs_his_addr; + u32 ifs_t4_his_mask; + u32 ifs_t3_his_mask; + u32 ifs_t2_his_mask; + u32 ifs_t1_his_mask; + u32 ifs_avg_l_addr; + u32 ifs_t2_avg_mask; + u32 ifs_t1_avg_mask; + u32 ifs_avg_h_addr; + u32 ifs_t4_avg_mask; + u32 ifs_t3_avg_mask; + u32 ifs_cca_l_addr; + u32 ifs_t2_cca_mask; + u32 ifs_t1_cca_mask; + u32 ifs_cca_h_addr; + u32 ifs_t4_cca_mask; + u32 ifs_t3_cca_mask; + u32 ifs_total_addr; + u32 ifs_cnt_done_mask; + u32 ifs_total_mask; +}; + +struct rtw89_physts_regs { + u32 setting_addr; + u32 dis_trigger_fail_mask; + u32 dis_trigger_brk_mask; +}; + struct rtw89_phy_gen_def { u32 cr_base; + const struct rtw89_ccx_regs *ccx; + const struct rtw89_physts_regs *physts; }; extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax; diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index 143f900d29a6..778e4b0c8e87 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -3,8 +3,75 @@ */ #include "phy.h" +#include "reg.h" + +static const struct rtw89_ccx_regs rtw89_ccx_regs_be = { + .setting_addr = R_CCX, + .edcca_opt_mask = B_CCX_EDCCA_OPT_MSK_V1, + .measurement_trig_mask = B_MEASUREMENT_TRIG_MSK, + .trig_opt_mask = B_CCX_TRIG_OPT_MSK, + .en_mask = B_CCX_EN_MSK, + .ifs_cnt_addr = R_IFS_COUNTER, + .ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK, + .ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK, + .ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK, + .ifs_collect_en_mask = B_IFS_COLLECT_EN, + .ifs_t1_addr = R_IFS_T1, + .ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK, + .ifs_t1_en_mask = B_IFS_T1_EN_MSK, + .ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK, + .ifs_t2_addr = R_IFS_T2, + .ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK, + .ifs_t2_en_mask = B_IFS_T2_EN_MSK, + .ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK, + .ifs_t3_addr = R_IFS_T3, + .ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK, + .ifs_t3_en_mask = B_IFS_T3_EN_MSK, + .ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK, + .ifs_t4_addr = R_IFS_T4, + .ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK, + .ifs_t4_en_mask = B_IFS_T4_EN_MSK, + .ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK, + .ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT_V1, + .ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK, + .ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK, + .ifs_clm_cca_addr = R_IFS_CLM_CCA_V1, + .ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK, + .ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK, + .ifs_clm_fa_addr = R_IFS_CLM_FA_V1, + .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK, + .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK, + .ifs_his_addr = R_IFS_HIS_V1, + .ifs_t4_his_mask = B_IFS_T4_HIS_MSK, + .ifs_t3_his_mask = B_IFS_T3_HIS_MSK, + .ifs_t2_his_mask = B_IFS_T2_HIS_MSK, + .ifs_t1_his_mask = B_IFS_T1_HIS_MSK, + .ifs_avg_l_addr = R_IFS_AVG_L_V1, + .ifs_t2_avg_mask = B_IFS_T2_AVG_MSK, + .ifs_t1_avg_mask = B_IFS_T1_AVG_MSK, + .ifs_avg_h_addr = R_IFS_AVG_H_V1, + .ifs_t4_avg_mask = B_IFS_T4_AVG_MSK, + .ifs_t3_avg_mask = B_IFS_T3_AVG_MSK, + .ifs_cca_l_addr = R_IFS_CCA_L_V1, + .ifs_t2_cca_mask = B_IFS_T2_CCA_MSK, + .ifs_t1_cca_mask = B_IFS_T1_CCA_MSK, + .ifs_cca_h_addr = R_IFS_CCA_H_V1, + .ifs_t4_cca_mask = B_IFS_T4_CCA_MSK, + .ifs_t3_cca_mask = B_IFS_T3_CCA_MSK, + .ifs_total_addr = R_IFSCNT_V1, + .ifs_cnt_done_mask = B_IFSCNT_DONE_MSK, + .ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK, +}; + +static const struct rtw89_physts_regs rtw89_physts_regs_be = { + .setting_addr = R_PLCP_HISTOGRAM, + .dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL, + .dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK, +}; const struct rtw89_phy_gen_def rtw89_phy_gen_be = { .cr_base = 0x20000, + .ccx = &rtw89_ccx_regs_be, + .physts = &rtw89_physts_regs_be, }; EXPORT_SYMBOL(rtw89_phy_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index eab26039242a..c0aac4d3678a 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -3998,6 +3998,7 @@ #define B_DBCC_80P80_SEL_EVM_RPT_EN BIT(0) #define R_CCX 0x0C00 #define B_CCX_EDCCA_OPT_MSK GENMASK(6, 4) +#define B_CCX_EDCCA_OPT_MSK_V1 GENMASK(7, 4) #define B_MEASUREMENT_TRIG_MSK BIT(2) #define B_CCX_TRIG_OPT_MSK BIT(1) #define B_CCX_EN_MSK BIT(0) @@ -4089,32 +4090,41 @@ #define B_SWSI_R_DATA_DONE_V1 BIT(26) #define R_TX_COUNTER 0x1A40 #define R_IFS_CLM_TX_CNT 0x1ACC +#define R_IFS_CLM_TX_CNT_V1 0x0ECC #define B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_TX_CNT_MSK GENMASK(15, 0) #define R_IFS_CLM_CCA 0x1AD0 +#define R_IFS_CLM_CCA_V1 0x0ED0 #define B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK GENMASK(15, 0) #define R_IFS_CLM_FA 0x1AD4 +#define R_IFS_CLM_FA_V1 0x0ED4 #define B_IFS_CLM_OFDM_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_CCK_FA_MSK GENMASK(15, 0) #define R_IFS_HIS 0x1AD8 +#define R_IFS_HIS_V1 0x0ED8 #define B_IFS_T4_HIS_MSK GENMASK(31, 24) #define B_IFS_T3_HIS_MSK GENMASK(23, 16) #define B_IFS_T2_HIS_MSK GENMASK(15, 8) #define B_IFS_T1_HIS_MSK GENMASK(7, 0) #define R_IFS_AVG_L 0x1ADC +#define R_IFS_AVG_L_V1 0x0EDC #define B_IFS_T2_AVG_MSK GENMASK(31, 16) #define B_IFS_T1_AVG_MSK GENMASK(15, 0) #define R_IFS_AVG_H 0x1AE0 +#define R_IFS_AVG_H_V1 0x0EE0 #define B_IFS_T4_AVG_MSK GENMASK(31, 16) #define B_IFS_T3_AVG_MSK GENMASK(15, 0) #define R_IFS_CCA_L 0x1AE4 +#define R_IFS_CCA_L_V1 0x0EE4 #define B_IFS_T2_CCA_MSK GENMASK(31, 16) #define B_IFS_T1_CCA_MSK GENMASK(15, 0) #define R_IFS_CCA_H 0x1AE8 +#define R_IFS_CCA_H_V1 0x0EE8 #define B_IFS_T4_CCA_MSK GENMASK(31, 16) #define B_IFS_T3_CCA_MSK GENMASK(15, 0) #define R_IFSCNT 0x1AEC +#define R_IFSCNT_V1 0x0EEC #define B_IFSCNT_DONE_MSK BIT(16) #define B_IFSCNT_TOTAL_CNT_MSK GENMASK(15, 0) #define R_TXAGC_TP 0x1C04 @@ -4385,6 +4395,7 @@ #define B_PKT_POP_EN BIT(8) #define R_SEG0R_PD 0x481C #define R_SEG0R_PD_V1 0x4860 +#define R_SEG0R_PD_V2 0x6A74 #define R_SEG0R_EDCCA_LVL 0x4840 #define R_SEG0R_EDCCA_LVL_V1 0x4884 #define B_SEG0R_PPDU_LVL_MSK GENMASK(31, 24) @@ -4503,8 +4514,10 @@ #define R_DCFO_COMP_S0_V1 0x4A40 #define B_DCFO_COMP_S0_V1_MSK GENMASK(13, 0) #define R_BMODE_PDTH_V1 0x4B64 +#define R_BMODE_PDTH_V2 0x6708 #define B_BMODE_PDTH_LOWER_BOUND_MSK_V1 GENMASK(31, 24) #define R_BMODE_PDTH_EN_V1 0x4B74 +#define R_BMODE_PDTH_EN_V2 0x6718 #define B_BMODE_PDTH_LIMIT_EN_MSK_V1 BIT(30) #define R_CFO_COMP_SEG1_L 0x5384 #define R_CFO_COMP_SEG1_H 0x5388 diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 52eb7030fd0b..103893f28b51 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -185,6 +185,10 @@ static const struct rtw89_dig_regs rtw8851b_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V1, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1, + .bmode_pd_reg = R_BMODE_PDTH_EN_V1, + .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1, + .bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1, + .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1, .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index eb6aad3bbb85..d068eae6a2f0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -478,6 +478,10 @@ static const struct rtw89_dig_regs rtw8852a_dig_regs = { .seg0_pd_reg = R_SEG0R_PD, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK, + .bmode_pd_reg = R_BMODE_PDTH_EN_V1, + .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1, + .bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1, + .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1, .p0_lna_init = {R_PATH0_LNA_INIT, B_PATH0_LNA_INIT_IDX_MSK}, .p1_lna_init = {R_PATH1_LNA_INIT, B_PATH1_LNA_INIT_IDX_MSK}, .p0_tia_init = {R_PATH0_TIA_INIT, B_PATH0_TIA_INIT_IDX_MSK}, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 49664cc44f36..0063301952b3 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -310,6 +310,10 @@ static const struct rtw89_dig_regs rtw8852b_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V1, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1, + .bmode_pd_reg = R_BMODE_PDTH_EN_V1, + .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1, + .bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1, + .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1, .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index abd01e808d83..1e16cc0a05dc 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -146,6 +146,10 @@ static const struct rtw89_dig_regs rtw8852c_dig_regs = { .seg0_pd_reg = R_SEG0R_PD, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK, + .bmode_pd_reg = R_BMODE_PDTH_EN_V1, + .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1, + .bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1, + .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1, .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, -- cgit From 78d84f35d2c3bf4434e9d785e4b4c33fa8e57878 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 22 Aug 2023 08:27:16 -0700 Subject: wifi: rtw89: Fix clang -Wimplicit-fallthrough in rtw89_query_sar() clang warns (or errors with CONFIG_WERROR=y): drivers/net/wireless/realtek/rtw89/sar.c:216:3: error: unannotated fall-through between switch labels [-Werror,-Wimplicit-fallthrough] 216 | case RTW89_TAS_STATE_DPR_FORBID: | ^ drivers/net/wireless/realtek/rtw89/sar.c:216:3: note: insert 'break;' to avoid fall-through 216 | case RTW89_TAS_STATE_DPR_FORBID: | ^ | break; 1 error generated. Clang is a little more pedantic than GCC, which does not warn when falling through to a case that is just break or return. Clang's version is more in line with the kernel's own stance in deprecated.rst, which states that all switch/case blocks must end in either break, fallthrough, continue, goto, or return. Add the missing break to silence the warning. Closes: https://github.com/ClangBuiltLinux/linux/issues/1921 Fixes: eb2624f55ad1 ("wifi: rtw89: Introduce Time Averaged SAR (TAS) feature") Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230822-rtw89-tas-clang-implicit-fallthrough-v1-1-5cb73f0fa976@kernel.org --- drivers/net/wireless/realtek/rtw89/sar.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index 881322f85d79..aed05b026c6c 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -211,6 +211,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq) case RTW89_TAS_STATE_DPR_ON: delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta); cfg -= delta; + break; case RTW89_TAS_STATE_DPR_FORBID: default: break; -- cgit From 290564367ab7fa7e2048bdc00d9c0ad016b41eea Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 23 Aug 2023 09:50:21 +0200 Subject: wifi: rtw88: usb: kill and free rx urbs on probe failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After rtw_usb_alloc_rx_bufs() has been called rx urbs have been allocated and must be freed in the error path. After rtw_usb_init_rx() has been called they are submitted, so they also must be killed. Add these forgotten steps to the probe error path. Besides the lost memory this also fixes a problem when the driver fails to download the firmware in rtw_chip_info_setup(). In this case it can happen that the completion of the rx urbs handler runs at a time when we already freed our data structures resulting in a kernel crash. Fixes: a82dfd33d123 ("wifi: rtw88: Add common USB chip support") Cc: stable@vger.kernel.org Reported-by: Ilgaz Öcal Signed-off-by: Sascha Hauer Acked-by: Larry Finger Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230823075021.588596-1-s.hauer@pengutronix.de --- drivers/net/wireless/realtek/rtw88/usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 95b9d933158f..d879d7e3dc81 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -826,7 +826,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ret = rtw_core_init(rtwdev); if (ret) - goto err_release_hw; + goto err_free_rx_bufs; ret = rtw_usb_intf_init(rtwdev, intf); if (ret) { @@ -872,6 +872,9 @@ err_destroy_usb: err_deinit_core: rtw_core_deinit(rtwdev); +err_free_rx_bufs: + rtw_usb_free_rx_bufs(rtwusb); + err_release_hw: ieee80211_free_hw(hw); -- cgit From e8afebbf434b7d7aede0122032ece40ae671bb44 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Thu, 24 Aug 2023 14:23:39 +0800 Subject: wifi: rtlwifi: rtl8723: Remove unused function rtl8723_cmd_send_packet() The function rtl8723_cmd_send_packet() is not used anywhere, so remove it. Signed-off-by: Jinjie Ruan Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230824062339.1885385-1-ruanjinjie@huawei.com --- .../realtek/rtlwifi/rtl8723com/fw_common.c | 28 ---------------------- .../realtek/rtlwifi/rtl8723com/fw_common.h | 2 -- 2 files changed, 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c index 36c00b89ccae..50b79cf8fb3c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c @@ -215,31 +215,3 @@ int rtl8723_download_fw(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rtl8723_download_fw); -bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - struct sk_buff *pskb = NULL; - unsigned long flags; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - pskb = __skb_dequeue(&ring->queue); - kfree_skb(pskb); - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - pdesc = &ring->desc[0]; - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} -EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h index b527fcbbdf08..c8e04f9722ae 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h @@ -66,7 +66,5 @@ void rtl8723_write_fw(struct ieee80211_hw *hw, u8 *buffer, u32 size, u8 max_page); int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, int count); int rtl8723_download_fw(struct ieee80211_hw *hw, bool is_8723be, int count); -bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb); #endif -- cgit From a9ac2e18779597f280d68a5b5f5bdd51a34080fa Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Thu, 24 Aug 2023 13:40:30 +0530 Subject: octeontx2-pf: Fix PFC TX scheduler free During PFC TX schedulers free, flag TXSCHQ_FREE_ALL was being set which caused free up all schedulers other than the PFC schedulers. This patch fixes that to free only the PFC Tx schedulers. Fixes: 99c969a83d82 ("octeontx2-pf: Add egress PFC support") Signed-off-by: Suman Ghosh Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824081032.436432-2-sumang@marvell.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 1 + drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c | 15 ++++----------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 3e1c70c74622..b9712040a0bc 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -804,6 +804,7 @@ void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq) mutex_unlock(&pfvf->mbox.lock); } +EXPORT_SYMBOL(otx2_txschq_free_one); void otx2_txschq_stop(struct otx2_nic *pfvf) { diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c index ccaf97bb1ce0..6492749dd7c8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c @@ -125,19 +125,12 @@ int otx2_pfc_txschq_alloc(struct otx2_nic *pfvf) static int otx2_pfc_txschq_stop_one(struct otx2_nic *pfvf, u8 prio) { - struct nix_txsch_free_req *free_req; + int lvl; - mutex_lock(&pfvf->mbox.lock); /* free PFC TLx nodes */ - free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox); - if (!free_req) { - mutex_unlock(&pfvf->mbox.lock); - return -ENOMEM; - } - - free_req->flags = TXSCHQ_FREE_ALL; - otx2_sync_mbox_msg(&pfvf->mbox); - mutex_unlock(&pfvf->mbox.lock); + for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) + otx2_txschq_free_one(pfvf, lvl, + pfvf->pfc_schq_list[lvl][prio]); pfvf->pfc_alloc_status[prio] = false; return 0; -- cgit From 47bcc9c1cf6aa60156c7532983090e86d9d171b6 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Thu, 24 Aug 2023 13:40:31 +0530 Subject: octeontx2-af: CN10KB: fix PFC configuration Suppose user has enabled pfc with prio 0,1 on a PF netdev(eth0) dcb pfc set dev eth0 prio-pfc o:on 1:on later user enabled pfc priorities 2 and 3 on the VF interface(eth1) dcb pfc set dev eth1 prio-pfc 2:on 3:on Instead of enabling pfc on all priorities (0..3), the driver only enables on priorities 2,3. This patch corrects the issue by using the proper CSR address. Fixes: b9d0fedc6234 ("octeontx2-af: cn10kb: Add RPM_USX MAC support") Signed-off-by: Hariprasad Kelam Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824081032.436432-3-sumang@marvell.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/rpm.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c index b4fcb20c3f4f..af21e2030cff 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c @@ -355,8 +355,8 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) { + u64 cfg, pfc_class_mask_cfg; rpm_t *rpm = rpmd; - u64 cfg; /* ALL pause frames received are completely ignored */ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); @@ -380,9 +380,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL); /* Disable all PFC classes */ - cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : + RPMX_CMRX_PRT_CBFC_CTL; + cfg = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg); - rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg); + rpm_write(rpm, lmac_id, pfc_class_mask_cfg, cfg); } int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat) @@ -605,8 +607,11 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p if (!is_lmac_valid(rpm, lmac_id)) return -ENODEV; + pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : + RPMX_CMRX_PRT_CBFC_CTL; + cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); - class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + class_en = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en); if (rx_pause) { @@ -635,10 +640,6 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE; rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); - - pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : - RPMX_CMRX_PRT_CBFC_CTL; - rpm_write(rpm, lmac_id, pfc_class_mask_cfg, class_en); return 0; -- cgit From 597d0ec0e4ca6a912affea4cc94df08959e9ec74 Mon Sep 17 00:00:00 2001 From: Suman Ghosh Date: Thu, 24 Aug 2023 13:40:32 +0530 Subject: cteonxt2-pf: Fix backpressure config for multiple PFC priorities to work simultaneously MAC (CGX or RPM) asserts backpressure at TL3 or TL2 node of the egress hierarchical scheduler tree depending on link level config done. If there are multiple PFC priorities enabled at a time and for all such flows to backoff, each priority will have to assert backpressure at different TL3/TL2 scheduler nodes and these flows will need to submit egress pkts to these nodes. Current PFC configuration has an issue where in only one backpressure scheduler node is being allocated which is resulting in only one PFC priority to work. This patch fixes this issue. Fixes: 99c969a83d82 ("octeontx2-pf: Add egress PFC support") Signed-off-by: Suman Ghosh Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824081032.436432-4-sumang@marvell.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c index 6492749dd7c8..bfddbff7bcdf 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c @@ -70,7 +70,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio) * link config level. These rest of the scheduler can be * same as hw.txschq_list. */ - for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) req->schq[lvl] = 1; rc = otx2_sync_mbox_msg(&pfvf->mbox); @@ -83,7 +83,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio) return PTR_ERR(rsp); /* Setup transmit scheduler list */ - for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) { + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) { if (!rsp->schq[lvl]) return -ENOSPC; @@ -128,7 +128,7 @@ static int otx2_pfc_txschq_stop_one(struct otx2_nic *pfvf, u8 prio) int lvl; /* free PFC TLx nodes */ - for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) otx2_txschq_free_one(pfvf, lvl, pfvf->pfc_schq_list[lvl][prio]); -- cgit From 215eb9f962091ebaab96be2c18cf5d0f5174a4d6 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 24 Aug 2023 20:31:31 +0800 Subject: veth: Avoid NAPI scheduling on failed SKB forwarding When an skb fails to be forwarded to the peer(e.g., skb data buffer length exceeds MTU), it will not be added to the peer's receive queue. Therefore, we should schedule the peer's NAPI poll function only when skb forwarding is successful to avoid unnecessary overhead. Signed-off-by: Liang Chen Link: https://lore.kernel.org/r/20230824123131.7673-1-liangchen.linux@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/veth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/veth.c b/drivers/net/veth.c index da44bb1331ff..d43e62ebc2fc 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -373,14 +373,13 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) { if (!use_napi) dev_lstats_add(dev, length); + else + __veth_xdp_flush(rq); } else { drop: atomic64_inc(&priv->dropped); } - if (use_napi) - __veth_xdp_flush(rq); - rcu_read_unlock(); return NETDEV_TX_OK; -- cgit From 70934c7c99ad01778eef83e898df4c624e52492f Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:37:53 +0100 Subject: net: phylink: add phylink_limit_mac_speed() Add a function which can be used to limit the phylink MAC capabilities to an upper speed limit. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAX3-005pTi-K1@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/phy/phylink.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 160bce608c34..0d7354955d62 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -426,6 +426,24 @@ static struct { { MAC_10HD, SPEED_10, DUPLEX_HALF }, }; +/** + * phylink_limit_mac_speed - limit the phylink_config to a maximum speed + * @config: pointer to a &struct phylink_config + * @max_speed: maximum speed + * + * Mask off MAC capabilities for speeds higher than the @max_speed parameter. + * Any further motifications of config.mac_capabilities will override this. + */ +void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(phylink_caps_params) && + phylink_caps_params[i].speed > max_speed; i++) + config->mac_capabilities &= ~phylink_caps_params[i].mask; +} +EXPORT_SYMBOL_GPL(phylink_limit_mac_speed); + /** * phylink_cap_from_speed_duplex - Get mac capability from speed/duplex * @speed: the speed to search for -- cgit From e80af2acdef73d90ce56d6849d96f2a5862cec2c Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:37:58 +0100 Subject: net: stmmac: convert plat->phylink_node to fwnode All users of plat->phylink_node first convert it to a fwnode. Rather than repeatedly convert to a fwnode, store it as a fwnode. To reflect this change, call it plat->port_node instead - it is used for more than just phylink. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAX8-005pTo-OT@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7a9bbcf03ea5..a2dfb624e10c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1153,7 +1153,7 @@ static int stmmac_init_phy(struct net_device *dev) if (!phylink_expects_phy(priv->phylink)) return 0; - fwnode = of_fwnode_handle(priv->plat->phylink_node); + fwnode = priv->plat->port_node; if (!fwnode) fwnode = dev_fwnode(priv->device); @@ -1200,7 +1200,7 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; - struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); + struct fwnode_handle *fwnode = priv->plat->port_node; int max_speed = priv->plat->max_speed; int mode = priv->plat->phy_interface; struct phylink *phylink; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index dd9e2fec5328..fa9e7e7040b9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -533,11 +533,11 @@ int stmmac_mdio_register(struct net_device *ndev) int err = 0; struct mii_bus *new_bus; struct stmmac_priv *priv = netdev_priv(ndev); - struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; struct device_node *mdio_node = priv->plat->mdio_node; struct device *dev = ndev->dev.parent; struct fwnode_handle *fixed_node; + struct fwnode_handle *fwnode; int addr, found, max_addr; if (!mdio_bus_data) @@ -601,6 +601,7 @@ int stmmac_mdio_register(struct net_device *ndev) stmmac_xgmac2_mdio_read_c45(new_bus, 0, 0, 0); /* If fixed-link is set, skip PHY scanning */ + fwnode = priv->plat->port_node; if (!fwnode) fwnode = dev_fwnode(priv->device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index be8e79c7aa34..ff330423ee66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -428,7 +428,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->phy_node = of_parse_phandle(np, "phy-handle", 0); /* PHYLINK automatically parses the phy-handle property */ - plat->phylink_node = np; + plat->port_node = of_fwnode_handle(np); /* Get max speed of operation from device tree */ of_property_read_u32(np, "max-speed", &plat->max_speed); -- cgit From 1a37c1c198320cce184b70772f78368aba0dec57 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:03 +0100 Subject: net: stmmac: clean up passing fwnode to phylink Move the initialisation of the fwnode variable closer to its use site, rather than scattered throughout stmmac_phy_setup(). Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXD-005pTv-TN@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a2dfb624e10c..7d97166194b5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1200,9 +1200,9 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; - struct fwnode_handle *fwnode = priv->plat->port_node; int max_speed = priv->plat->max_speed; int mode = priv->plat->phy_interface; + struct fwnode_handle *fwnode; struct phylink *phylink; priv->phylink_config.dev = &priv->dev->dev; @@ -1211,9 +1211,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband; - if (!fwnode) - fwnode = dev_fwnode(priv->device); - /* Set the platform/firmware specified interface mode */ __set_bit(mode, priv->phylink_config.supported_interfaces); @@ -1254,6 +1251,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) ~(MAC_10HD | MAC_100HD | MAC_1000HD); priv->phylink_config.mac_managed_pm = true; + fwnode = priv->plat->port_node; + if (!fwnode) + fwnode = dev_fwnode(priv->device); + phylink = phylink_create(&priv->phylink_config, fwnode, mode, &stmmac_phylink_mac_ops); if (IS_ERR(phylink)) -- cgit From 2b070cdd3afd53518e04d2813bb9df5ad93505f7 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:09 +0100 Subject: net: stmmac: use "mdio_bus_data" local variable We have a local variable for priv->plat->mdio_bus_data, which we use later in the conditional if() block, but we evaluate the above within the conditional expression. Use mdio_bus_data instead. Since these will be the only two users of this local variable, move its assignment just before the if(). Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXJ-005pU1-1z@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7d97166194b5..fe733a9f5fe4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1199,7 +1199,7 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { - struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; + struct stmmac_mdio_bus_data *mdio_bus_data; int max_speed = priv->plat->max_speed; int mode = priv->plat->phy_interface; struct fwnode_handle *fwnode; @@ -1207,7 +1207,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.dev = &priv->dev->dev; priv->phylink_config.type = PHYLINK_NETDEV; - if (priv->plat->mdio_bus_data) + + mdio_bus_data = priv->plat->mdio_bus_data; + if (mdio_bus_data) priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband; -- cgit From a4ac612bd345d676f2d70125a729df2861f91c1d Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:14 +0100 Subject: net: stmmac: use phylink_limit_mac_speed() Use phylink_limit_mac_speed() to limit the MAC capabilities rather than coding this for each speed. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXO-005pU7-61@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 35 +++++++++-------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fe733a9f5fe4..30a085f2b8fa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1200,10 +1200,10 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { struct stmmac_mdio_bus_data *mdio_bus_data; - int max_speed = priv->plat->max_speed; int mode = priv->plat->phy_interface; struct fwnode_handle *fwnode; struct phylink *phylink; + int max_speed; priv->phylink_config.dev = &priv->dev->dev; priv->phylink_config.type = PHYLINK_NETDEV; @@ -1222,29 +1222,18 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.supported_interfaces); priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100; - - if (!max_speed || max_speed >= 1000) - priv->phylink_config.mac_capabilities |= MAC_1000; + MAC_10 | MAC_100 | MAC_1000; if (priv->plat->has_gmac4) { - if (!max_speed || max_speed >= 2500) - priv->phylink_config.mac_capabilities |= MAC_2500FD; + priv->phylink_config.mac_capabilities |= MAC_2500FD; } else if (priv->plat->has_xgmac) { - if (!max_speed || max_speed >= 2500) - priv->phylink_config.mac_capabilities |= MAC_2500FD; - if (!max_speed || max_speed >= 5000) - priv->phylink_config.mac_capabilities |= MAC_5000FD; - if (!max_speed || max_speed >= 10000) - priv->phylink_config.mac_capabilities |= MAC_10000FD; - if (!max_speed || max_speed >= 25000) - priv->phylink_config.mac_capabilities |= MAC_25000FD; - if (!max_speed || max_speed >= 40000) - priv->phylink_config.mac_capabilities |= MAC_40000FD; - if (!max_speed || max_speed >= 50000) - priv->phylink_config.mac_capabilities |= MAC_50000FD; - if (!max_speed || max_speed >= 100000) - priv->phylink_config.mac_capabilities |= MAC_100000FD; + priv->phylink_config.mac_capabilities |= MAC_2500FD; + priv->phylink_config.mac_capabilities |= MAC_5000FD; + priv->phylink_config.mac_capabilities |= MAC_10000FD; + priv->phylink_config.mac_capabilities |= MAC_25000FD; + priv->phylink_config.mac_capabilities |= MAC_40000FD; + priv->phylink_config.mac_capabilities |= MAC_50000FD; + priv->phylink_config.mac_capabilities |= MAC_100000FD; } /* Half-Duplex can only work with single queue */ @@ -1253,6 +1242,10 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) ~(MAC_10HD | MAC_100HD | MAC_1000HD); priv->phylink_config.mac_managed_pm = true; + max_speed = priv->plat->max_speed; + if (max_speed) + phylink_limit_mac_speed(&priv->phylink_config, max_speed); + fwnode = priv->plat->port_node; if (!fwnode) fwnode = dev_fwnode(priv->device); -- cgit From d42ca04e044891c9cf2e5a8dbcef85dd57f94827 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:19 +0100 Subject: net: stmmac: provide stmmac_mac_phylink_get_caps() Allow MACs to provide their own capabilities via the MAC operations struct. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXT-005pUD-Aj@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++ 2 files changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 238f17c50a1e..b95d3e137813 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -300,6 +300,8 @@ struct stmmac_est; struct stmmac_ops { /* MAC core initialization */ void (*core_init)(struct mac_device_info *hw, struct net_device *dev); + /* Get phylink capabilities */ + void (*phylink_get_caps)(struct stmmac_priv *priv); /* Enable the MAC RX/TX */ void (*set_mac)(void __iomem *ioaddr, bool enable); /* Enable and verify that the IPC module is supported */ @@ -419,6 +421,8 @@ struct stmmac_ops { #define stmmac_core_init(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, core_init, __args) +#define stmmac_mac_phylink_get_caps(__priv) \ + stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv) #define stmmac_mac_set(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, set_mac, __args) #define stmmac_rx_ipc(__priv, __args...) \ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 30a085f2b8fa..a9cf6aecdddf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1224,6 +1224,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000; + /* Get the MAC specific capabilities */ + stmmac_mac_phylink_get_caps(priv); + if (priv->plat->has_gmac4) { priv->phylink_config.mac_capabilities |= MAC_2500FD; } else if (priv->plat->has_xgmac) { -- cgit From f1dae3d222c63b605d75d338a34e975c8a018640 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:24 +0100 Subject: net: stmmac: move gmac4 specific phylink capabilities to gmac4 Move the setup of gmac4 speicifc phylink capabilities into gmac4 code. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXY-005pUJ-Ez@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 8 ++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 03b1c5a97826..c6ff1fa0e04d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -68,6 +68,11 @@ static void dwmac4_core_init(struct mac_device_info *hw, init_waitqueue_head(&priv->tstamp_busy_wait); } +static void dwmac4_phylink_get_caps(struct stmmac_priv *priv) +{ + priv->phylink_config.mac_capabilities |= MAC_2500FD; +} + static void dwmac4_rx_queue_enable(struct mac_device_info *hw, u8 mode, u32 queue) { @@ -1131,6 +1136,7 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, const struct stmmac_ops dwmac4_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, @@ -1173,6 +1179,7 @@ const struct stmmac_ops dwmac4_ops = { const struct stmmac_ops dwmac410_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_dwmac4_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, @@ -1221,6 +1228,7 @@ const struct stmmac_ops dwmac410_ops = { const struct stmmac_ops dwmac510_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_dwmac4_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a9cf6aecdddf..0b02845e7e9d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1227,9 +1227,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) /* Get the MAC specific capabilities */ stmmac_mac_phylink_get_caps(priv); - if (priv->plat->has_gmac4) { - priv->phylink_config.mac_capabilities |= MAC_2500FD; - } else if (priv->plat->has_xgmac) { + if (priv->plat->has_xgmac) { priv->phylink_config.mac_capabilities |= MAC_2500FD; priv->phylink_config.mac_capabilities |= MAC_5000FD; priv->phylink_config.mac_capabilities |= MAC_10000FD; -- cgit From bedf9b81233dc3c7f70c65cd5370de883199e3f6 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:29 +0100 Subject: net: stmmac: move xgmac specific phylink caps to dwxgmac2 core Move the xgmac specific phylink capabilities to the dwxgmac2 support core. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXd-005pUP-JL@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 10 ++++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 34e1b0c3f346..f352be269deb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -47,6 +47,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); } +static void xgmac_phylink_get_caps(struct stmmac_priv *priv) +{ + priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD | + MAC_10000FD | MAC_25000FD | + MAC_40000FD | MAC_50000FD | + MAC_100000FD; +} + static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) { u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); @@ -1490,6 +1498,7 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq, const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, + .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxgmac2_rx_queue_enable, @@ -1551,6 +1560,7 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode, const struct stmmac_ops dwxlgmac2_ops = { .core_init = dwxgmac2_core_init, + .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxlgmac2_rx_queue_enable, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 0b02845e7e9d..5cf8304564c6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1227,16 +1227,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) /* Get the MAC specific capabilities */ stmmac_mac_phylink_get_caps(priv); - if (priv->plat->has_xgmac) { - priv->phylink_config.mac_capabilities |= MAC_2500FD; - priv->phylink_config.mac_capabilities |= MAC_5000FD; - priv->phylink_config.mac_capabilities |= MAC_10000FD; - priv->phylink_config.mac_capabilities |= MAC_25000FD; - priv->phylink_config.mac_capabilities |= MAC_40000FD; - priv->phylink_config.mac_capabilities |= MAC_50000FD; - priv->phylink_config.mac_capabilities |= MAC_100000FD; - } - /* Half-Duplex can only work with single queue */ if (priv->plat->tx_queues_to_use > 1) priv->phylink_config.mac_capabilities &= -- cgit From 64961f1b8ca1c6f515478887db70cd0e88f47af4 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:34 +0100 Subject: net: stmmac: move priv->phylink_config.mac_managed_pm Move priv->phylink_config.mac_managed_pm to be along side the other phylink initialisations. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXi-005pUV-Nq@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 5cf8304564c6..7cfc2918c913 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1207,6 +1207,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.dev = &priv->dev->dev; priv->phylink_config.type = PHYLINK_NETDEV; + priv->phylink_config.mac_managed_pm = true; mdio_bus_data = priv->plat->mdio_bus_data; if (mdio_bus_data) @@ -1231,7 +1232,6 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) if (priv->plat->tx_queues_to_use > 1) priv->phylink_config.mac_capabilities &= ~(MAC_10HD | MAC_100HD | MAC_1000HD); - priv->phylink_config.mac_managed_pm = true; max_speed = priv->plat->max_speed; if (max_speed) -- cgit From 76649fc93f097785e9b173950d0fbb1d7a9c4a76 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 24 Aug 2023 14:38:39 +0100 Subject: net: stmmac: convert half-duplex support to positive logic Rather than detecting when half-duplex is not supported, and clearing the MAC capabilities, reverse the if() condition and use it to set the capabilities instead. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZAXn-005pUb-SP@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7cfc2918c913..33ca5c50bdcd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1223,16 +1223,17 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.supported_interfaces); priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000; + MAC_10FD | MAC_100FD | + MAC_1000FD; + + /* Half-Duplex can only work with single queue */ + if (priv->plat->tx_queues_to_use <= 1) + priv->phylink_config.mac_capabilities |= MAC_10HD | MAC_100HD | + MAC_1000HD; /* Get the MAC specific capabilities */ stmmac_mac_phylink_get_caps(priv); - /* Half-Duplex can only work with single queue */ - if (priv->plat->tx_queues_to_use > 1) - priv->phylink_config.mac_capabilities &= - ~(MAC_10HD | MAC_100HD | MAC_1000HD); - max_speed = priv->plat->max_speed; if (max_speed) phylink_limit_mac_speed(&priv->phylink_config, max_speed); -- cgit From c4413a20fa6d7c4888009fb7dd391685f196cd36 Mon Sep 17 00:00:00 2001 From: Alex Austin Date: Thu, 24 Aug 2023 17:46:57 +0100 Subject: sfc: Check firmware supports Ethernet PTP filter Not all firmware variants support RSS filters. Do not fail all PTP functionality when raw ethernet PTP filters fail to insert. Fixes: e4616f64726b ("sfc: support PTP over Ethernet") Signed-off-by: Alex Austin Acked-by: Edward Cree Reviewed-by: Pieter Jansen van Vuuren Link: https://lore.kernel.org/r/20230824164657.42379-1-alex.austin@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sfc/ptp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 0c40571133cb..00cf6de3bb2b 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1485,7 +1485,9 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx) goto fail; rc = efx_ptp_insert_eth_multicast_filter(efx); - if (rc < 0) + + /* Not all firmware variants support this filter */ + if (rc < 0 && rc != -EPROTONOSUPPORT) goto fail; } -- cgit From 91202ce78fcd070982a115f0bf6f328af619aa00 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 24 Aug 2023 09:17:50 -0700 Subject: pds_core: protect devlink callbacks from fw_down state Don't access structs that have been cleared when in the fw_down state and the various structs have been cleaned and are waiting to recover. This caused a panic on rmmod when already in fw_down and devlink_param_unregister() tried to check the parameters. Fixes: 40ced8944536 ("pds_core: devlink params for enabling VIF support") Signed-off-by: Shannon Nelson Reviewed-by: Brett Creeley Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824161754.34264-2-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/devlink.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c index 9c6b3653c1c7..d9607033bbf2 100644 --- a/drivers/net/ethernet/amd/pds_core/devlink.c +++ b/drivers/net/ethernet/amd/pds_core/devlink.c @@ -10,6 +10,9 @@ pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc, { int vt; + if (!pdsc->viftype_status) + return NULL; + for (vt = 0; vt < PDS_DEV_TYPE_MAX; vt++) { if (pdsc->viftype_status[vt].dl_id == dl_id) return &pdsc->viftype_status[vt]; -- cgit From e48b894a1db7f6ce66bff0402ab21ff9f0e56034 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 24 Aug 2023 09:17:51 -0700 Subject: pds_core: no health reporter in VF Make sure the health reporter is set up before we use it in our devlink health updates, especially since the VF doesn't set up the health reporter. Fixes: 25b450c05a49 ("pds_core: add devlink health facilities") Signed-off-by: Shannon Nelson Reviewed-by: Brett Creeley Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824161754.34264-3-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index f2c79456d745..383e3311a52c 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -524,7 +524,8 @@ static void pdsc_fw_down(struct pdsc *pdsc) } /* Notify clients of fw_down */ - devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); + if (pdsc->fw_reporter) + devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); pdsc_notify(PDS_EVENT_RESET, &reset_event); pdsc_stop(pdsc); @@ -554,8 +555,9 @@ static void pdsc_fw_up(struct pdsc *pdsc) /* Notify clients of fw_up */ pdsc->fw_recoveries++; - devlink_health_reporter_state_update(pdsc->fw_reporter, - DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); + if (pdsc->fw_reporter) + devlink_health_reporter_state_update(pdsc->fw_reporter, + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); pdsc_notify(PDS_EVENT_RESET, &reset_event); return; -- cgit From 95e383226d6fcda6c217912f11edf8d74de9cc85 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 24 Aug 2023 09:17:52 -0700 Subject: pds_core: no reset command for VF The VF doesn't need to send a reset command, and in a PCI reset scenario it might not have a valid IO space to write to anyway. Fixes: 523847df1b37 ("pds_core: add devcmd device interfaces") Signed-off-by: Shannon Nelson Reviewed-by: Brett Creeley Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824161754.34264-4-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index 383e3311a52c..36f9b932b9e2 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -464,7 +464,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) { int i; - pdsc_devcmd_reset(pdsc); + if (!pdsc->pdev->is_virtfn) + pdsc_devcmd_reset(pdsc); pdsc_qcq_free(pdsc, &pdsc->notifyqcq); pdsc_qcq_free(pdsc, &pdsc->adminqcq); -- cgit From 969cfd4c8ca50c32901342cdd3d677c3ffe61371 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 24 Aug 2023 09:17:53 -0700 Subject: pds_core: check for work queue before use Add a check that the wq exists before queuing up work for a failed devcmd, as the PF is responsible for health and the VF doesn't have a wq. Fixes: c2dbb0904310 ("pds_core: health timer and workqueue") Signed-off-by: Shannon Nelson Reviewed-by: Brett Creeley Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824161754.34264-5-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c index debe5216fe29..524f422ee7ac 100644 --- a/drivers/net/ethernet/amd/pds_core/dev.c +++ b/drivers/net/ethernet/amd/pds_core/dev.c @@ -183,7 +183,7 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd, err = pdsc_devcmd_wait(pdsc, max_seconds); memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp)); - if (err == -ENXIO || err == -ETIMEDOUT) + if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq) queue_work(pdsc->wq, &pdsc->health_work); return err; -- cgit From 0ea064e74bc8f915aba3f2d0fb3418247a09b73d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 24 Aug 2023 09:17:54 -0700 Subject: pds_core: pass opcode to devcmd_wait Don't rely on the PCI memory for the devcmd opcode because we read a 0xff value if the PCI bus is broken, which can cause us to report a bogus dev_cmd opcode later. Fixes: 523847df1b37 ("pds_core: add devcmd device interfaces") Signed-off-by: Shannon Nelson Reviewed-by: Brett Creeley Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230824161754.34264-6-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/pds_core/dev.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c index 524f422ee7ac..f77cd9f5a2fd 100644 --- a/drivers/net/ethernet/amd/pds_core/dev.c +++ b/drivers/net/ethernet/amd/pds_core/dev.c @@ -121,7 +121,7 @@ static const char *pdsc_devcmd_str(int opcode) } } -static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds) +static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds) { struct device *dev = pdsc->dev; unsigned long start_time; @@ -131,9 +131,6 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds) int done = 0; int err = 0; int status; - int opcode; - - opcode = ioread8(&pdsc->cmd_regs->cmd.opcode); start_time = jiffies; max_wait = start_time + (max_seconds * HZ); @@ -180,7 +177,7 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd, memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd)); pdsc_devcmd_dbell(pdsc); - err = pdsc_devcmd_wait(pdsc, max_seconds); + err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds); memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp)); if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq) -- cgit From 439c4be98318751415a8f3690e4fa0fb62474a72 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:37 +0100 Subject: sfc: introduce ethernet pedit set action infrastructure Introduce the initial ethernet pedit set action infrastructure in preparation for adding mac src and dst pedit action offloads. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mae.c | 83 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/ethernet/sfc/mae.h | 4 ++ drivers/net/ethernet/sfc/tc.c | 70 +++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/tc.h | 56 ++++++++++++++++++++++++---- 4 files changed, 202 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 3b8780c76b6e..a7ad7ab8c5f4 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -1219,6 +1219,71 @@ fail: return rc; } +/** + * efx_mae_allocate_pedit_mac() - allocate pedit MAC address in HW. + * @efx: NIC we're installing a pedit MAC address on + * @ped: pedit MAC action to be installed + * + * Attempts to install @ped in HW and populates its id with an index of this + * entry in the firmware MAC address table on success. + * + * Return: negative value on error, 0 in success. + */ +int efx_mae_allocate_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN); + size_t outlen; + int rc; + + BUILD_BUG_ON(MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_LEN != + sizeof(ped->h_addr)); + memcpy(MCDI_PTR(inbuf, MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR), ped->h_addr, + sizeof(ped->h_addr)); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_ALLOC, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + ped->fw_id = MCDI_DWORD(outbuf, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID); + return 0; +} + +/** + * efx_mae_free_pedit_mac() - free pedit MAC address in HW. + * @efx: NIC we're installing a pedit MAC address on + * @ped: pedit MAC action that needs to be freed + * + * Frees @ped in HW, check that firmware did not free a different one and clears + * the id (which denotes the index of the entry in the MAC address table). + */ +void efx_mae_free_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_MAC_ADDR_FREE_IN_MAC_ID, ped->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_FREE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc || outlen < sizeof(outbuf)) + return; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what MAC addresses exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) != ped->fw_id)) + return; + /* We're probably about to free @ped, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + ped->fw_id = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL; +} + int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); @@ -1231,10 +1296,20 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop, MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap); - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, - MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, - MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); + if (act->src_mac) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, + act->src_mac->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, + MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); + + if (act->dst_mac) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, + act->dst_mac->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, + MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); + if (act->count && !WARN_ON(!act->count->cnt)) MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, act->count->cnt->fw_id); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index e88e80574f15..8df30bc4f3ba 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -103,6 +103,10 @@ int efx_mae_update_encap_md(struct efx_nic *efx, int efx_mae_free_encap_md(struct efx_nic *efx, struct efx_tc_encap_action *encap); +int efx_mae_allocate_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped); +void efx_mae_free_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped); int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 039180c61c83..8a9fc2f47514 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -86,6 +86,12 @@ s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) return mport; } +static const struct rhashtable_params efx_tc_mac_ht_params = { + .key_len = offsetofend(struct efx_tc_mac_pedit_action, h_addr), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_mac_pedit_action, linkage), +}; + static const struct rhashtable_params efx_tc_encap_match_ht_params = { .key_len = offsetof(struct efx_tc_encap_match, linkage), .key_offset = 0, @@ -110,6 +116,56 @@ static const struct rhashtable_params efx_tc_recirc_ht_params = { .head_offset = offsetof(struct efx_tc_recirc_id, linkage), }; +static struct efx_tc_mac_pedit_action __maybe_unused *efx_tc_flower_get_mac(struct efx_nic *efx, + unsigned char h_addr[ETH_ALEN], + struct netlink_ext_ack *extack) +{ + struct efx_tc_mac_pedit_action *ped, *old; + int rc; + + ped = kzalloc(sizeof(*ped), GFP_USER); + if (!ped) + return ERR_PTR(-ENOMEM); + memcpy(ped->h_addr, h_addr, ETH_ALEN); + old = rhashtable_lookup_get_insert_fast(&efx->tc->mac_ht, + &ped->linkage, + efx_tc_mac_ht_params); + if (old) { + /* don't need our new entry */ + kfree(ped); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found, ref taken */ + return old; + } + + rc = efx_mae_allocate_pedit_mac(efx, ped); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to store pedit MAC address in hw"); + goto out_remove; + } + + /* ref and return */ + refcount_set(&ped->ref, 1); + return ped; +out_remove: + rhashtable_remove_fast(&efx->tc->mac_ht, &ped->linkage, + efx_tc_mac_ht_params); + kfree(ped); + return ERR_PTR(rc); +} + +static void __maybe_unused efx_tc_flower_put_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + if (!refcount_dec_and_test(&ped->ref)) + return; /* still in use */ + rhashtable_remove_fast(&efx->tc->mac_ht, &ped->linkage, + efx_tc_mac_ht_params); + efx_mae_free_pedit_mac(efx, ped); + kfree(ped); +} + static void efx_tc_free_action_set(struct efx_nic *efx, struct efx_tc_action_set *act, bool in_hw) { @@ -2156,6 +2212,14 @@ static void efx_tc_lhs_free(void *ptr, void *arg) kfree(rule); } +static void efx_tc_mac_free(void *ptr, void *__unused) +{ + struct efx_tc_mac_pedit_action *ped = ptr; + + WARN_ON(refcount_read(&ped->ref)); + kfree(ped); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -2196,6 +2260,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = efx_tc_init_counters(efx); if (rc < 0) goto fail_counters; + rc = rhashtable_init(&efx->tc->mac_ht, &efx_tc_mac_ht_params); + if (rc < 0) + goto fail_mac_ht; rc = rhashtable_init(&efx->tc->encap_match_ht, &efx_tc_encap_match_ht_params); if (rc < 0) goto fail_encap_match_ht; @@ -2233,6 +2300,8 @@ fail_lhs_rule_ht: fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); fail_encap_match_ht: + rhashtable_destroy(&efx->tc->mac_ht); +fail_mac_ht: efx_tc_destroy_counters(efx); fail_counters: efx_tc_destroy_encap_actions(efx); @@ -2268,6 +2337,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) rhashtable_free_and_destroy(&efx->tc->recirc_ht, efx_tc_recirc_free, efx); WARN_ON(!ida_is_empty(&efx->tc->recirc_ida)); ida_destroy(&efx->tc->recirc_ida); + rhashtable_free_and_destroy(&efx->tc->mac_ht, efx_tc_mac_free, NULL); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 40d2c803fca8..7b6a6a3d8e4c 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -18,6 +18,23 @@ #define IS_ALL_ONES(v) (!(typeof (v))~(v)) +/** + * struct efx_tc_mac_pedit_action - mac pedit action fields + * + * @h_addr: mac address field of ethernet header + * @linkage: rhashtable reference + * @ref: reference count + * @fw_id: index of this entry in firmware MAC address table + * + * MAC address edits are indirected through a table in the hardware + */ +struct efx_tc_mac_pedit_action { + u8 h_addr[ETH_ALEN]; + struct rhash_head linkage; + refcount_t ref; + u32 fw_id; /* index of this entry in firmware MAC address table */ +}; + static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) { return !memchr_inv(addr, 0xff, sizeof(*addr)); @@ -25,20 +42,43 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) struct efx_tc_encap_action; /* see tc_encap_actions.h */ +/** + * struct efx_tc_action_set - collection of tc action fields + * + * @vlan_push: the number of vlan headers to push + * @vlan_pop: the number of vlan headers to pop + * @decap: used to indicate a tunnel header decapsulation should take place + * @deliver: used to indicate a deliver action should take place + * @vlan_tci: tci fields for vlan push actions + * @vlan_proto: ethernet types for vlan push actions + * @count: counter mapping + * @encap_md: encap entry in tc_encap_ht table + * @encap_user: linked list of encap users (encap_md->users) + * @user: owning action-set-list. Only populated if @encap_md is; used by efx_tc_update_encap() fallback handling + * @count_user: linked list of counter users (counter->users) + * @dest_mport: destination mport + * @src_mac: source mac entry in tc_mac_ht table + * @dst_mac: destination mac entry in tc_mac_ht table + * @fw_id: index of this entry in firmware actions table + * @list: linked list of tc actions + * + */ struct efx_tc_action_set { u16 vlan_push:2; u16 vlan_pop:2; u16 decap:1; u16 deliver:1; - __be16 vlan_tci[2]; /* TCIs for vlan_push */ - __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ + __be16 vlan_tci[2]; + __be16 vlan_proto[2]; struct efx_tc_counter_index *count; - struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ - struct list_head encap_user; /* entry on encap_md->users list */ - struct efx_tc_action_set_list *user; /* Only populated if encap_md */ - struct list_head count_user; /* entry on counter->users list, if encap */ + struct efx_tc_encap_action *encap_md; + struct list_head encap_user; + struct efx_tc_action_set_list *user; + struct list_head count_user; u32 dest_mport; - u32 fw_id; /* index of this entry in firmware actions table */ + struct efx_tc_mac_pedit_action *src_mac; + struct efx_tc_mac_pedit_action *dst_mac; + u32 fw_id; struct list_head list; }; @@ -220,6 +260,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @counter_ht: Hashtable of TC counters (FW IDs and counter values) * @counter_id_ht: Hashtable mapping TC counter cookies to counters * @encap_ht: Hashtable of TC encap actions + * @mac_ht: Hashtable of MAC address entries (for pedits) * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules @@ -257,6 +298,7 @@ struct efx_tc_state { struct rhashtable counter_ht; struct rhashtable counter_id_ht; struct rhashtable encap_ht; + struct rhashtable mac_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable lhs_rule_ht; -- cgit From 0c676503bd4ff726f5a4adc8fb54e09a78685b1f Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:38 +0100 Subject: sfc: add mac source and destination pedit action offload Introduce the first pedit set offload functionality for the sfc driver. In addition to this, add offload functionality for both mac source and destination pedit set actions. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.c | 209 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 207 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 8a9fc2f47514..b9d7c4bb7e69 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -116,7 +116,7 @@ static const struct rhashtable_params efx_tc_recirc_ht_params = { .head_offset = offsetof(struct efx_tc_recirc_id, linkage), }; -static struct efx_tc_mac_pedit_action __maybe_unused *efx_tc_flower_get_mac(struct efx_nic *efx, +static struct efx_tc_mac_pedit_action *efx_tc_flower_get_mac(struct efx_nic *efx, unsigned char h_addr[ETH_ALEN], struct netlink_ext_ack *extack) { @@ -155,7 +155,7 @@ out_remove: return ERR_PTR(rc); } -static void __maybe_unused efx_tc_flower_put_mac(struct efx_nic *efx, +static void efx_tc_flower_put_mac(struct efx_nic *efx, struct efx_tc_mac_pedit_action *ped) { if (!refcount_dec_and_test(&ped->ref)) @@ -191,6 +191,10 @@ static void efx_tc_free_action_set(struct efx_nic *efx, list_del(&act->encap_user); efx_tc_flower_release_encap_md(efx, act->encap_md); } + if (act->src_mac) + efx_tc_flower_put_mac(efx, act->src_mac); + if (act->dst_mac) + efx_tc_flower_put_mac(efx, act->dst_mac); kfree(act); } @@ -753,6 +757,7 @@ static const char *efx_tc_encap_type_name(enum efx_encap_type typ) /* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */ enum efx_tc_action_order { EFX_TC_AO_DECAP, + EFX_TC_AO_PEDIT_MAC_ADDRS, EFX_TC_AO_VLAN_POP, EFX_TC_AO_VLAN_PUSH, EFX_TC_AO_COUNT, @@ -767,6 +772,11 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, case EFX_TC_AO_DECAP: if (act->decap) return false; + /* PEDIT_MAC_ADDRS must not happen before DECAP, though it + * can wait until much later + */ + if (act->dst_mac || act->src_mac) + return false; fallthrough; case EFX_TC_AO_VLAN_POP: if (act->vlan_pop >= 2) @@ -786,6 +796,7 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, if (act->count) return false; fallthrough; + case EFX_TC_AO_PEDIT_MAC_ADDRS: case EFX_TC_AO_ENCAP: if (act->encap_md) return false; @@ -956,6 +967,191 @@ static void efx_tc_flower_release_lhs_actions(struct efx_nic *efx, efx_tc_flower_put_counter_index(efx, act->count); } +/** + * struct efx_tc_mangler_state - accumulates 32-bit pedits into fields + * + * @dst_mac_32: dst_mac[0:3] has been populated + * @dst_mac_16: dst_mac[4:5] has been populated + * @src_mac_16: src_mac[0:1] has been populated + * @src_mac_32: src_mac[2:5] has been populated + * @dst_mac: h_dest field of ethhdr + * @src_mac: h_source field of ethhdr + * + * Since FLOW_ACTION_MANGLE comes in 32-bit chunks that do not + * necessarily equate to whole fields of the packet header, this + * structure is used to hold the cumulative effect of the partial + * field pedits that have been processed so far. + */ +struct efx_tc_mangler_state { + u8 dst_mac_32:1; /* eth->h_dest[0:3] */ + u8 dst_mac_16:1; /* eth->h_dest[4:5] */ + u8 src_mac_16:1; /* eth->h_source[0:1] */ + u8 src_mac_32:1; /* eth->h_source[2:5] */ + unsigned char dst_mac[ETH_ALEN]; + unsigned char src_mac[ETH_ALEN]; +}; + +/** efx_tc_complete_mac_mangle() - pull complete field pedits out of @mung + * @efx: NIC we're installing a flow rule on + * @act: action set (cursor) to update + * @mung: accumulated partial mangles + * @extack: netlink extended ack for reporting errors + * + * Check @mung to find any combinations of partial mangles that can be + * combined into a complete packet field edit, add that edit to @act, + * and consume the partial mangles from @mung. + */ + +static int efx_tc_complete_mac_mangle(struct efx_nic *efx, + struct efx_tc_action_set *act, + struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack) +{ + struct efx_tc_mac_pedit_action *ped; + + if (mung->dst_mac_32 && mung->dst_mac_16) { + ped = efx_tc_flower_get_mac(efx, mung->dst_mac, extack); + if (IS_ERR(ped)) + return PTR_ERR(ped); + + /* Check that we have not already populated dst_mac */ + if (act->dst_mac) + efx_tc_flower_put_mac(efx, act->dst_mac); + + act->dst_mac = ped; + + /* consume the incomplete state */ + mung->dst_mac_32 = 0; + mung->dst_mac_16 = 0; + } + if (mung->src_mac_16 && mung->src_mac_32) { + ped = efx_tc_flower_get_mac(efx, mung->src_mac, extack); + if (IS_ERR(ped)) + return PTR_ERR(ped); + + /* Check that we have not already populated src_mac */ + if (act->src_mac) + efx_tc_flower_put_mac(efx, act->src_mac); + + act->src_mac = ped; + + /* consume the incomplete state */ + mung->src_mac_32 = 0; + mung->src_mac_16 = 0; + } + return 0; +} + +/** + * efx_tc_mangle() - handle a single 32-bit (or less) pedit + * @efx: NIC we're installing a flow rule on + * @act: action set (cursor) to update + * @fa: FLOW_ACTION_MANGLE action metadata + * @mung: accumulator for partial mangles + * @extack: netlink extended ack for reporting errors + * + * Identify the fields written by a FLOW_ACTION_MANGLE, and record + * the partial mangle state in @mung. If this mangle completes an + * earlier partial mangle, consume and apply to @act by calling + * efx_tc_complete_mac_mangle(). + */ + +static int efx_tc_mangle(struct efx_nic *efx, struct efx_tc_action_set *act, + const struct flow_action_entry *fa, + struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack) +{ + __le32 mac32; + __le16 mac16; + + switch (fa->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_ETH: + BUILD_BUG_ON(offsetof(struct ethhdr, h_dest) != 0); + BUILD_BUG_ON(offsetof(struct ethhdr, h_source) != 6); + if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_PEDIT_MAC_ADDRS)) { + NL_SET_ERR_MSG_MOD(extack, + "Pedit mangle mac action violates action order"); + return -EOPNOTSUPP; + } + switch (fa->mangle.offset) { + case 0: + if (fa->mangle.mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth.dst32 mangle", + fa->mangle.mask); + return -EOPNOTSUPP; + } + /* Ethernet address is little-endian */ + mac32 = cpu_to_le32(fa->mangle.val); + memcpy(mung->dst_mac, &mac32, sizeof(mac32)); + mung->dst_mac_32 = 1; + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + case 4: + if (fa->mangle.mask == 0xffff) { + mac16 = cpu_to_le16(fa->mangle.val >> 16); + memcpy(mung->src_mac, &mac16, sizeof(mac16)); + mung->src_mac_16 = 1; + } else if (fa->mangle.mask == 0xffff0000) { + mac16 = cpu_to_le16((u16)fa->mangle.val); + memcpy(mung->dst_mac + 4, &mac16, sizeof(mac16)); + mung->dst_mac_16 = 1; + } else { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth+4 mangle is not high or low 16b", + fa->mangle.mask); + return -EOPNOTSUPP; + } + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + case 8: + if (fa->mangle.mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth.src32 mangle", + fa->mangle.mask); + return -EOPNOTSUPP; + } + mac32 = cpu_to_le32(fa->mangle.val); + memcpy(mung->src_mac + 2, &mac32, sizeof(mac32)); + mung->src_mac_32 = 1; + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported: mangle eth+%u %x/%x", + fa->mangle.offset, fa->mangle.val, fa->mangle.mask); + return -EOPNOTSUPP; + } + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled mangle htype %u for action rule", + fa->mangle.htype); + return -EOPNOTSUPP; + } + return 0; +} + +/** + * efx_tc_incomplete_mangle() - check for leftover partial pedits + * @mung: accumulator for partial mangles + * @extack: netlink extended ack for reporting errors + * + * Since the MAE can only overwrite whole fields, any partial + * field mangle left over on reaching packet delivery (mirred or + * end of TC actions) cannot be offloaded. Check for any such + * and reject them with -%EOPNOTSUPP. + */ + +static int efx_tc_incomplete_mangle(struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack) +{ + if (mung->dst_mac_32 || mung->dst_mac_16) { + NL_SET_ERR_MSG_MOD(extack, "Incomplete pedit of destination MAC address"); + return -EOPNOTSUPP; + } + if (mung->src_mac_16 || mung->src_mac_32) { + NL_SET_ERR_MSG_MOD(extack, "Incomplete pedit of source MAC address"); + return -EOPNOTSUPP; + } + return 0; +} + static int efx_tc_flower_replace_foreign(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc) @@ -1351,6 +1547,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx, struct netlink_ext_ack *extack = tc->common.extack; const struct ip_tunnel_info *encap_info = NULL; struct efx_tc_flow_rule *rule = NULL, *old; + struct efx_tc_mangler_state mung = {}; struct efx_tc_action_set *act = NULL; const struct flow_action_entry *fa; struct efx_rep *from_efv, *to_efv; @@ -1687,6 +1884,11 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_proto[act->vlan_push] = fa->vlan.proto; act->vlan_push++; break; + case FLOW_ACTION_MANGLE: + rc = efx_tc_mangle(efx, act, fa, &mung, extack); + if (rc < 0) + goto release; + break; case FLOW_ACTION_TUNNEL_ENCAP: if (encap_info) { /* Can't specify encap multiple times. @@ -1726,6 +1928,9 @@ static int efx_tc_flower_replace(struct efx_nic *efx, } } + rc = efx_tc_incomplete_mangle(&mung, extack); + if (rc < 0) + goto release; if (act) { /* Not shot/redirected, so deliver to default dest */ if (from_efv == EFX_EFV_PF) -- cgit From 66f728872636e1167aedc5a18be6760083911900 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:39 +0100 Subject: sfc: add decrement ttl by offloading set ipv4 ttl actions Offload pedit set ipv4 ttl field, where the ttl field has already been matched and the new value is one less, by translating it to a decrement. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/mae.c | 6 ++-- drivers/net/ethernet/sfc/tc.c | 75 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/ethernet/sfc/tc.h | 2 ++ 3 files changed, 79 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index a7ad7ab8c5f4..c3e2b4a21d10 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -1291,10 +1291,12 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) size_t outlen; int rc; - MCDI_POPULATE_DWORD_3(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, + MCDI_POPULATE_DWORD_4(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push, MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop, - MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap); + MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap, + MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, + act->do_ttl_dec); if (act->src_mac) MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index b9d7c4bb7e69..57bdd56b7113 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -31,6 +31,7 @@ enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) return EFX_ENCAP_TYPE_NONE; } +#define EFX_TC_HDR_TYPE_TTL_MASK ((u32)0xff) #define EFX_EFV_PF NULL /* Look up the representor information (efv) for a device. * May return NULL for the PF (us), or an error pointer for a device that @@ -757,6 +758,7 @@ static const char *efx_tc_encap_type_name(enum efx_encap_type typ) /* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */ enum efx_tc_action_order { EFX_TC_AO_DECAP, + EFX_TC_AO_DEC_TTL, EFX_TC_AO_PEDIT_MAC_ADDRS, EFX_TC_AO_VLAN_POP, EFX_TC_AO_VLAN_PUSH, @@ -777,6 +779,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, */ if (act->dst_mac || act->src_mac) return false; + + /* Decrementing ttl must not happen before DECAP */ + if (act->do_ttl_dec) + return false; fallthrough; case EFX_TC_AO_VLAN_POP: if (act->vlan_pop >= 2) @@ -803,6 +809,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, fallthrough; case EFX_TC_AO_DELIVER: return !act->deliver; + case EFX_TC_AO_DEC_TTL: + if (act->encap_md) + return false; + return !act->do_ttl_dec; default: /* Bad caller. Whatever they wanted to do, say they can't. */ WARN_ON_ONCE(1); @@ -1049,6 +1059,7 @@ static int efx_tc_complete_mac_mangle(struct efx_nic *efx, * @fa: FLOW_ACTION_MANGLE action metadata * @mung: accumulator for partial mangles * @extack: netlink extended ack for reporting errors + * @match: original match used along with the mangle action * * Identify the fields written by a FLOW_ACTION_MANGLE, and record * the partial mangle state in @mung. If this mangle completes an @@ -1059,10 +1070,12 @@ static int efx_tc_complete_mac_mangle(struct efx_nic *efx, static int efx_tc_mangle(struct efx_nic *efx, struct efx_tc_action_set *act, const struct flow_action_entry *fa, struct efx_tc_mangler_state *mung, - struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack, + struct efx_tc_match *match) { __le32 mac32; __le16 mac16; + u8 tr_ttl; switch (fa->mangle.htype) { case FLOW_ACT_MANGLE_HDR_TYPE_ETH: @@ -1119,6 +1132,64 @@ static int efx_tc_mangle(struct efx_nic *efx, struct efx_tc_action_set *act, return -EOPNOTSUPP; } break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: + switch (fa->mangle.offset) { + case offsetof(struct iphdr, ttl): + /* we currently only support pedit IP4 when it applies + * to TTL and then only when it can be achieved with a + * decrement ttl action + */ + + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != ~EFX_TC_HDR_TYPE_TTL_MASK) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) out of range, only support mangle action on ipv4.ttl", + fa->mangle.mask); + return -EOPNOTSUPP; + } + + /* we can only convert to a dec ttl when we have an + * exact match on the ttl field + */ + if (match->mask.ip_ttl != U8_MAX) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle ipv4.ttl when we have an exact match on ttl, mask used for match (%#x)", + match->mask.ip_ttl); + return -EOPNOTSUPP; + } + + /* check that we don't try to decrement 0, which equates + * to setting the ttl to 0xff + */ + if (match->value.ip_ttl == 0) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: we cannot decrement ttl past 0"); + return -EOPNOTSUPP; + } + + /* check that we do not decrement ttl twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + + /* check pedit can be achieved with decrement action */ + tr_ttl = match->value.ip_ttl - 1; + if ((fa->mangle.val & EFX_TC_HDR_TYPE_TTL_MASK) == tr_ttl) { + act->do_ttl_dec = 1; + return 0; + } + + fallthrough; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle on the ttl field (offset is %u)", + fa->mangle.offset); + return -EOPNOTSUPP; + } + break; default: NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled mangle htype %u for action rule", fa->mangle.htype); @@ -1885,7 +1956,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_push++; break; case FLOW_ACTION_MANGLE: - rc = efx_tc_mangle(efx, act, fa, &mung, extack); + rc = efx_tc_mangle(efx, act, fa, &mung, extack, &match); if (rc < 0) goto release; break; diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 7b6a6a3d8e4c..4dd2c378fd9f 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -48,6 +48,7 @@ struct efx_tc_encap_action; /* see tc_encap_actions.h */ * @vlan_push: the number of vlan headers to push * @vlan_pop: the number of vlan headers to pop * @decap: used to indicate a tunnel header decapsulation should take place + * @do_ttl_dec: used to indicate IP TTL / Hop Limit should be decremented * @deliver: used to indicate a deliver action should take place * @vlan_tci: tci fields for vlan push actions * @vlan_proto: ethernet types for vlan push actions @@ -67,6 +68,7 @@ struct efx_tc_action_set { u16 vlan_push:2; u16 vlan_pop:2; u16 decap:1; + u16 do_ttl_dec:1; u16 deliver:1; __be16 vlan_tci[2]; __be16 vlan_proto[2]; -- cgit From 9dbc8d2b9a02f938d32741297d56cc364dc0dce6 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:40 +0100 Subject: sfc: add decrement ipv6 hop limit by offloading set hop limit actions Offload pedit set ipv6 hop limit, where the hop limit has already been matched and the new value is one less, by translating it to a decrement. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.c | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 57bdd56b7113..354c635be59f 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -32,6 +32,8 @@ enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) } #define EFX_TC_HDR_TYPE_TTL_MASK ((u32)0xff) +/* Hoplimit is stored in the most significant byte in the pedit ipv6 header action */ +#define EFX_TC_HDR_TYPE_HLIMIT_MASK ~((u32)0xff000000) #define EFX_EFV_PF NULL /* Look up the representor information (efv) for a device. * May return NULL for the PF (us), or an error pointer for a device that @@ -1190,6 +1192,63 @@ static int efx_tc_mangle(struct efx_nic *efx, struct efx_tc_action_set *act, return -EOPNOTSUPP; } break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: + switch (fa->mangle.offset) { + case round_down(offsetof(struct ipv6hdr, hop_limit), 4): + /* we currently only support pedit IP6 when it applies + * to the hoplimit and then only when it can be achieved + * with a decrement hoplimit action + */ + + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != EFX_TC_HDR_TYPE_HLIMIT_MASK) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) out of range, only support mangle action on ipv6.hop_limit", + fa->mangle.mask); + + return -EOPNOTSUPP; + } + + /* we can only convert to a dec ttl when we have an + * exact match on the ttl field + */ + if (match->mask.ip_ttl != U8_MAX) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle ipv6.hop_limit when we have an exact match on ttl, mask used for match (%#x)", + match->mask.ip_ttl); + return -EOPNOTSUPP; + } + + /* check that we don't try to decrement 0, which equates + * to setting the ttl to 0xff + */ + if (match->value.ip_ttl == 0) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: we cannot decrement hop_limit past 0"); + return -EOPNOTSUPP; + } + + /* check that we do not decrement hoplimit twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + + /* check pedit can be achieved with decrement action */ + tr_ttl = match->value.ip_ttl - 1; + if ((fa->mangle.val >> 24) == tr_ttl) { + act->do_ttl_dec = 1; + return 0; + } + + fallthrough; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle on the hop_limit field"); + return -EOPNOTSUPP; + } default: NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled mangle htype %u for action rule", fa->mangle.htype); -- cgit From 64848f062e33df61fb1f9f7b7a3dc7b44e0d36d7 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:41 +0100 Subject: sfc: introduce pedit add actions on the ipv4 ttl field Introduce pedit add actions and use it to achieve decrement ttl offload. Decrement ttl can be achieved by adding 0xff to the ttl field. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.c | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 354c635be59f..dfe3a8bf74f0 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -1054,6 +1054,47 @@ static int efx_tc_complete_mac_mangle(struct efx_nic *efx, return 0; } +static int efx_tc_pedit_add(struct efx_nic *efx, struct efx_tc_action_set *act, + const struct flow_action_entry *fa, + struct netlink_ext_ack *extack) +{ + switch (fa->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: + switch (fa->mangle.offset) { + case offsetof(struct iphdr, ttl): + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != ~EFX_TC_HDR_TYPE_TTL_MASK) + break; + + /* Adding 0xff is equivalent to decrementing the ttl. + * Other added values are not supported. + */ + if ((fa->mangle.val & EFX_TC_HDR_TYPE_TTL_MASK) != U8_MAX) + break; + + /* check that we do not decrement ttl twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + act->do_ttl_dec = 1; + return 0; + default: + break; + } + break; + default: + break; + } + + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: ttl add action type %x %x %x/%x", + fa->mangle.htype, fa->mangle.offset, + fa->mangle.val, fa->mangle.mask); + return -EOPNOTSUPP; +} + /** * efx_tc_mangle() - handle a single 32-bit (or less) pedit * @efx: NIC we're installing a flow rule on @@ -2014,6 +2055,11 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_proto[act->vlan_push] = fa->vlan.proto; act->vlan_push++; break; + case FLOW_ACTION_ADD: + rc = efx_tc_pedit_add(efx, act, fa, extack); + if (rc < 0) + goto release; + break; case FLOW_ACTION_MANGLE: rc = efx_tc_mangle(efx, act, fa, &mung, extack, &match); if (rc < 0) -- cgit From e8e0bd60e4833e5bcfa220d7b4c07456c83c1ea2 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 24 Aug 2023 12:28:42 +0100 Subject: sfc: extend pedit add action to handle decrement ipv6 hop limit Extend the pedit add actions to handle this case for ipv6. Similar to ipv4 dec ttl, decrementing ipv6 hop limit can be achieved by adding 0xff to the hop limit field. Co-developed-by: Edward Cree Signed-off-by: Edward Cree Signed-off-by: Pieter Jansen van Vuuren Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index dfe3a8bf74f0..047322b04d4f 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -1084,6 +1084,31 @@ static int efx_tc_pedit_add(struct efx_nic *efx, struct efx_tc_action_set *act, break; } break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: + switch (fa->mangle.offset) { + case round_down(offsetof(struct ipv6hdr, hop_limit), 4): + /* check that pedit applies to hoplimit only */ + if (fa->mangle.mask != EFX_TC_HDR_TYPE_HLIMIT_MASK) + break; + + /* Adding 0xff is equivalent to decrementing the hoplimit. + * Other added values are not supported. + */ + if ((fa->mangle.val >> 24) != U8_MAX) + break; + + /* check that we do not decrement hoplimit twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + act->do_ttl_dec = 1; + return 0; + default: + break; + } + break; default: break; } -- cgit From c1e0230eeaab26984f6e5c5575486e96a63e2e48 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 24 Aug 2023 17:16:16 +0530 Subject: net: ti: icss-iep: Add IEP driver Add a driver for Industrial Ethernet Peripheral (IEP) block of PRUSS to support timestamping of ethernet packets and thus support PTP and PPS for PRU ethernet ports. Signed-off-by: Roger Quadros Signed-off-by: Lokesh Vutla Signed-off-by: Murali Karicheri Signed-off-by: Vignesh Raghavendra Reviewed-by: Simon Horman Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Kconfig | 11 + drivers/net/ethernet/ti/Makefile | 1 + drivers/net/ethernet/ti/icssg/icss_iep.c | 939 +++++++++++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icss_iep.h | 38 ++ 4 files changed, 989 insertions(+) create mode 100644 drivers/net/ethernet/ti/icssg/icss_iep.c create mode 100644 drivers/net/ethernet/ti/icssg/icss_iep.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 63e510b6860f..1af5a90720ec 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -196,4 +196,15 @@ config TI_ICSSG_PRUETH to support the Ethernet operation. Currently, it supports Ethernet with 1G and 100M link speed. +config TI_ICSS_IEP + tristate "TI PRU ICSS IEP driver" + depends on TI_PRUSS + default TI_PRUSS + help + This driver enables support for the PRU-ICSS Industrial Ethernet + Peripheral within a PRU-ICSS subsystem present on various TI SoCs. + + To compile this driver as a module, choose M here. The module + will be called icss_iep. + endif # NET_VENDOR_TI diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 9176d79c36e1..34fd7a716ba6 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -38,3 +38,4 @@ icssg-prueth-y := k3-cppi-desc-pool.o \ icssg/icssg_mii_cfg.o \ icssg/icssg_stats.o \ icssg/icssg_ethtool.o +obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c new file mode 100644 index 000000000000..bcc056bf45da --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -0,0 +1,939 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icss_iep.h" + +#define IEP_MAX_DEF_INC 0xf +#define IEP_MAX_COMPEN_INC 0xfff +#define IEP_MAX_COMPEN_COUNT 0xffffff + +#define IEP_GLOBAL_CFG_CNT_ENABLE BIT(0) +#define IEP_GLOBAL_CFG_DEFAULT_INC_MASK GENMASK(7, 4) +#define IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT 4 +#define IEP_GLOBAL_CFG_COMPEN_INC_MASK GENMASK(19, 8) +#define IEP_GLOBAL_CFG_COMPEN_INC_SHIFT 8 + +#define IEP_GLOBAL_STATUS_CNT_OVF BIT(0) + +#define IEP_CMP_CFG_SHADOW_EN BIT(17) +#define IEP_CMP_CFG_CMP0_RST_CNT_EN BIT(0) +#define IEP_CMP_CFG_CMP_EN(cmp) (GENMASK(16, 1) & (1 << ((cmp) + 1))) + +#define IEP_CMP_STATUS(cmp) (1 << (cmp)) + +#define IEP_SYNC_CTRL_SYNC_EN BIT(0) +#define IEP_SYNC_CTRL_SYNC_N_EN(n) (GENMASK(2, 1) & (BIT(1) << (n))) + +#define IEP_MIN_CMP 0 +#define IEP_MAX_CMP 15 + +#define ICSS_IEP_64BIT_COUNTER_SUPPORT BIT(0) +#define ICSS_IEP_SLOW_COMPEN_REG_SUPPORT BIT(1) +#define ICSS_IEP_SHADOW_MODE_SUPPORT BIT(2) + +#define LATCH_INDEX(ts_index) ((ts_index) + 6) +#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(n) BIT(LATCH_INDEX(n)) +#define IEP_CAP_CFG_CAP_ASYNC_EN(n) BIT(LATCH_INDEX(n) + 10) + +enum { + ICSS_IEP_GLOBAL_CFG_REG, + ICSS_IEP_GLOBAL_STATUS_REG, + ICSS_IEP_COMPEN_REG, + ICSS_IEP_SLOW_COMPEN_REG, + ICSS_IEP_COUNT_REG0, + ICSS_IEP_COUNT_REG1, + ICSS_IEP_CAPTURE_CFG_REG, + ICSS_IEP_CAPTURE_STAT_REG, + + ICSS_IEP_CAP6_RISE_REG0, + ICSS_IEP_CAP6_RISE_REG1, + + ICSS_IEP_CAP7_RISE_REG0, + ICSS_IEP_CAP7_RISE_REG1, + + ICSS_IEP_CMP_CFG_REG, + ICSS_IEP_CMP_STAT_REG, + ICSS_IEP_CMP0_REG0, + ICSS_IEP_CMP0_REG1, + ICSS_IEP_CMP1_REG0, + ICSS_IEP_CMP1_REG1, + + ICSS_IEP_CMP8_REG0, + ICSS_IEP_CMP8_REG1, + ICSS_IEP_SYNC_CTRL_REG, + ICSS_IEP_SYNC0_STAT_REG, + ICSS_IEP_SYNC1_STAT_REG, + ICSS_IEP_SYNC_PWIDTH_REG, + ICSS_IEP_SYNC0_PERIOD_REG, + ICSS_IEP_SYNC1_DELAY_REG, + ICSS_IEP_SYNC_START_REG, + ICSS_IEP_MAX_REGS, +}; + +/** + * struct icss_iep_plat_data - Plat data to handle SoC variants + * @config: Regmap configuration data + * @reg_offs: register offsets to capture offset differences across SoCs + * @flags: Flags to represent IEP properties + */ +struct icss_iep_plat_data { + struct regmap_config *config; + u32 reg_offs[ICSS_IEP_MAX_REGS]; + u32 flags; +}; + +struct icss_iep { + struct device *dev; + void __iomem *base; + const struct icss_iep_plat_data *plat_data; + struct regmap *map; + struct device_node *client_np; + unsigned long refclk_freq; + int clk_tick_time; /* one refclk tick time in ns */ + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; + struct mutex ptp_clk_mutex; /* PHC access serializer */ + spinlock_t irq_lock; /* CMP IRQ vs icss_iep_ptp_enable access */ + u32 def_inc; + s16 slow_cmp_inc; + u32 slow_cmp_count; + const struct icss_iep_clockops *ops; + void *clockops_data; + u32 cycle_time_ns; + u32 perout_enabled; + bool pps_enabled; + int cap_cmp_irq; + u64 period; + u32 latch_enable; +}; + +/** + * icss_iep_get_count_hi() - Get the upper 32 bit IEP counter + * @iep: Pointer to structure representing IEP. + * + * Return: upper 32 bit IEP counter + */ +int icss_iep_get_count_hi(struct icss_iep *iep) +{ + u32 val = 0; + + if (iep && (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)) + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + + return val; +} +EXPORT_SYMBOL_GPL(icss_iep_get_count_hi); + +/** + * icss_iep_get_count_low() - Get the lower 32 bit IEP counter + * @iep: Pointer to structure representing IEP. + * + * Return: lower 32 bit IEP counter + */ +int icss_iep_get_count_low(struct icss_iep *iep) +{ + u32 val = 0; + + if (iep) + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); + + return val; +} +EXPORT_SYMBOL_GPL(icss_iep_get_count_low); + +/** + * icss_iep_get_ptp_clock_idx() - Get PTP clock index using IEP driver + * @iep: Pointer to structure representing IEP. + * + * Return: PTP clock index, -1 if not registered + */ +int icss_iep_get_ptp_clock_idx(struct icss_iep *iep) +{ + if (!iep || !iep->ptp_clock) + return -1; + return ptp_clock_index(iep->ptp_clock); +} +EXPORT_SYMBOL_GPL(icss_iep_get_ptp_clock_idx); + +static void icss_iep_set_counter(struct icss_iep *iep, u64 ns) +{ + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + writel(upper_32_bits(ns), iep->base + + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + writel(upper_32_bits(ns), iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); +} + +static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns); + +/** + * icss_iep_settime() - Set time of the PTP clock using IEP driver + * @iep: Pointer to structure representing IEP. + * @ns: Time to be set in nanoseconds + * + * This API uses writel() instead of regmap_write() for write operations as + * regmap_write() is too slow and this API is time sensitive. + */ +static void icss_iep_settime(struct icss_iep *iep, u64 ns) +{ + unsigned long flags; + + if (iep->ops && iep->ops->settime) { + iep->ops->settime(iep->clockops_data, ns); + return; + } + + spin_lock_irqsave(&iep->irq_lock, flags); + if (iep->pps_enabled || iep->perout_enabled) + writel(0, iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + + icss_iep_set_counter(iep, ns); + + if (iep->pps_enabled || iep->perout_enabled) { + icss_iep_update_to_next_boundary(iep, ns); + writel(IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN, + iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + } + spin_unlock_irqrestore(&iep->irq_lock, flags); +} + +/** + * icss_iep_gettime() - Get time of the PTP clock using IEP driver + * @iep: Pointer to structure representing IEP. + * @sts: Pointer to structure representing PTP system timestamp. + * + * This API uses readl() instead of regmap_read() for read operations as + * regmap_read() is too slow and this API is time sensitive. + * + * Return: The current timestamp of the PTP clock using IEP driver + */ +static u64 icss_iep_gettime(struct icss_iep *iep, + struct ptp_system_timestamp *sts) +{ + u32 ts_hi = 0, ts_lo; + unsigned long flags; + + if (iep->ops && iep->ops->gettime) + return iep->ops->gettime(iep->clockops_data, sts); + + /* use local_irq_x() to make it work for both RT/non-RT */ + local_irq_save(flags); + + /* no need to play with hi-lo, hi is latched when lo is read */ + ptp_read_system_prets(sts); + ts_lo = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); + ptp_read_system_postts(sts); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + ts_hi = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + + local_irq_restore(flags); + + return (u64)ts_lo | (u64)ts_hi << 32; +} + +static void icss_iep_enable(struct icss_iep *iep) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_CNT_ENABLE, + IEP_GLOBAL_CFG_CNT_ENABLE); +} + +static void icss_iep_disable(struct icss_iep *iep) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_CNT_ENABLE, + 0); +} + +static void icss_iep_enable_shadow_mode(struct icss_iep *iep) +{ + u32 cycle_time; + int cmp; + + cycle_time = iep->cycle_time_ns - iep->def_inc; + + icss_iep_disable(iep); + + /* disable shadow mode */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_SHADOW_EN, 0); + + /* enable shadow mode */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_SHADOW_EN, IEP_CMP_CFG_SHADOW_EN); + + /* clear counters */ + icss_iep_set_counter(iep, 0); + + /* clear overflow status */ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_STATUS_REG, + IEP_GLOBAL_STATUS_CNT_OVF, + IEP_GLOBAL_STATUS_CNT_OVF); + + /* clear compare status */ + for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) { + regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG, + IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp)); + } + + /* enable reset counter on CMP0 event */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP0_RST_CNT_EN, + IEP_CMP_CFG_CMP0_RST_CNT_EN); + /* enable compare */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(0), + IEP_CMP_CFG_CMP_EN(0)); + + /* set CMP0 value to cycle time */ + regmap_write(iep->map, ICSS_IEP_CMP0_REG0, cycle_time); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP0_REG1, cycle_time); + + icss_iep_set_counter(iep, 0); + icss_iep_enable(iep); +} + +static void icss_iep_set_default_inc(struct icss_iep *iep, u8 def_inc) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_DEFAULT_INC_MASK, + def_inc << IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT); +} + +static void icss_iep_set_compensation_inc(struct icss_iep *iep, u16 compen_inc) +{ + struct device *dev = regmap_get_device(iep->map); + + if (compen_inc > IEP_MAX_COMPEN_INC) { + dev_err(dev, "%s: too high compensation inc %d\n", + __func__, compen_inc); + compen_inc = IEP_MAX_COMPEN_INC; + } + + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_COMPEN_INC_MASK, + compen_inc << IEP_GLOBAL_CFG_COMPEN_INC_SHIFT); +} + +static void icss_iep_set_compensation_count(struct icss_iep *iep, + u32 compen_count) +{ + struct device *dev = regmap_get_device(iep->map); + + if (compen_count > IEP_MAX_COMPEN_COUNT) { + dev_err(dev, "%s: too high compensation count %d\n", + __func__, compen_count); + compen_count = IEP_MAX_COMPEN_COUNT; + } + + regmap_write(iep->map, ICSS_IEP_COMPEN_REG, compen_count); +} + +static void icss_iep_set_slow_compensation_count(struct icss_iep *iep, + u32 compen_count) +{ + regmap_write(iep->map, ICSS_IEP_SLOW_COMPEN_REG, compen_count); +} + +/* PTP PHC operations */ +static int icss_iep_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + s32 ppb = scaled_ppm_to_ppb(scaled_ppm); + u32 cyc_count; + u16 cmp_inc; + + mutex_lock(&iep->ptp_clk_mutex); + + /* ppb is amount of frequency we want to adjust in 1GHz (billion) + * e.g. 100ppb means we need to speed up clock by 100Hz + * i.e. at end of 1 second (1 billion ns) clock time, we should be + * counting 100 more ns. + * We use IEP slow compensation to achieve continuous freq. adjustment. + * There are 2 parts. Cycle time and adjustment per cycle. + * Simplest case would be 1 sec Cycle time. Then adjustment + * pre cycle would be (def_inc + ppb) value. + * Cycle time will have to be chosen based on how worse the ppb is. + * e.g. smaller the ppb, cycle time has to be large. + * The minimum adjustment we can do is +-1ns per cycle so let's + * reduce the cycle time to get 1ns per cycle adjustment. + * 1ppb = 1sec cycle time & 1ns adjust + * 1000ppb = 1/1000 cycle time & 1ns adjust per cycle + */ + + if (iep->cycle_time_ns) + iep->slow_cmp_inc = iep->clk_tick_time; /* 4ns adj per cycle */ + else + iep->slow_cmp_inc = 1; /* 1ns adjust per cycle */ + + if (ppb < 0) { + iep->slow_cmp_inc = -iep->slow_cmp_inc; + ppb = -ppb; + } + + cyc_count = NSEC_PER_SEC; /* 1s cycle time @1GHz */ + cyc_count /= ppb; /* cycle time per ppb */ + + /* slow_cmp_count is decremented every clock cycle, e.g. @250MHz */ + if (!iep->cycle_time_ns) + cyc_count /= iep->clk_tick_time; + iep->slow_cmp_count = cyc_count; + + /* iep->clk_tick_time is def_inc */ + cmp_inc = iep->clk_tick_time + iep->slow_cmp_inc; + icss_iep_set_compensation_inc(iep, cmp_inc); + icss_iep_set_slow_compensation_count(iep, iep->slow_cmp_count); + + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + s64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + if (iep->ops && iep->ops->adjtime) { + iep->ops->adjtime(iep->clockops_data, delta); + } else { + ns = icss_iep_gettime(iep, NULL); + ns += delta; + icss_iep_settime(iep, ns); + } + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_gettimeex(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + ns = icss_iep_gettime(iep, sts); + *ts = ns_to_timespec64(ns); + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + ns = timespec64_to_ns(ts); + icss_iep_settime(iep, ns); + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns) +{ + u64 ns, p_ns; + u32 offset; + + ns = icss_iep_gettime(iep, NULL); + if (start_ns < ns) + start_ns = ns; + p_ns = iep->period; + /* Round up to next period boundary */ + start_ns += p_ns - 1; + offset = do_div(start_ns, p_ns); + start_ns = start_ns * p_ns; + /* If it is too close to update, shift to next boundary */ + if (p_ns - offset < 10) + start_ns += p_ns; + + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(start_ns)); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(start_ns)); +} + +static int icss_iep_perout_enable_hw(struct icss_iep *iep, + struct ptp_perout_request *req, int on) +{ + int ret; + u64 cmp; + + if (iep->ops && iep->ops->perout_enable) { + ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp); + if (ret) + return ret; + + if (on) { + /* Configure CMP */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp)); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp)); + /* Configure SYNC, 1ms pulse width */ + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000); + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); + } else { + /* Disable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), 0); + + /* clear regs */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); + } + } else { + if (on) { + u64 start_ns; + + iep->period = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + start_ns = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + icss_iep_update_to_next_boundary(iep, start_ns); + + /* Enable Sync in single shot mode */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, + IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); + } else { + /* Disable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), 0); + + /* clear CMP regs */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); + + /* Disable sync */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); + } + } + + return 0; +} + +static int icss_iep_perout_enable(struct icss_iep *iep, + struct ptp_perout_request *req, int on) +{ + unsigned long flags; + int ret = 0; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->pps_enabled) { + ret = -EBUSY; + goto exit; + } + + if (iep->perout_enabled == !!on) + goto exit; + + spin_lock_irqsave(&iep->irq_lock, flags); + ret = icss_iep_perout_enable_hw(iep, req, on); + if (!ret) + iep->perout_enabled = !!on; + spin_unlock_irqrestore(&iep->irq_lock, flags); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_pps_enable(struct icss_iep *iep, int on) +{ + struct ptp_clock_request rq; + struct timespec64 ts; + unsigned long flags; + int ret = 0; + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->perout_enabled) { + ret = -EBUSY; + goto exit; + } + + if (iep->pps_enabled == !!on) + goto exit; + + spin_lock_irqsave(&iep->irq_lock, flags); + + rq.perout.index = 0; + if (on) { + ns = icss_iep_gettime(iep, NULL); + ts = ns_to_timespec64(ns); + rq.perout.period.sec = 1; + rq.perout.period.nsec = 0; + rq.perout.start.sec = ts.tv_sec + 2; + rq.perout.start.nsec = 0; + ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); + } else { + ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); + } + + if (!ret) + iep->pps_enabled = !!on; + + spin_unlock_irqrestore(&iep->irq_lock, flags); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_extts_enable(struct icss_iep *iep, u32 index, int on) +{ + u32 val, cap, ret = 0; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->ops && iep->ops->extts_enable) { + ret = iep->ops->extts_enable(iep->clockops_data, index, on); + goto exit; + } + + if (((iep->latch_enable & BIT(index)) >> index) == on) + goto exit; + + regmap_read(iep->map, ICSS_IEP_CAPTURE_CFG_REG, &val); + cap = IEP_CAP_CFG_CAP_ASYNC_EN(index) | IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(index); + if (on) { + val |= cap; + iep->latch_enable |= BIT(index); + } else { + val &= ~cap; + iep->latch_enable &= ~BIT(index); + } + regmap_write(iep->map, ICSS_IEP_CAPTURE_CFG_REG, val); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: + return icss_iep_perout_enable(iep, &rq->perout, on); + case PTP_CLK_REQ_PPS: + return icss_iep_pps_enable(iep, on); + case PTP_CLK_REQ_EXTTS: + return icss_iep_extts_enable(iep, rq->extts.index, on); + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info icss_iep_ptp_info = { + .owner = THIS_MODULE, + .name = "ICSS IEP timer", + .max_adj = 10000000, + .adjfine = icss_iep_ptp_adjfine, + .adjtime = icss_iep_ptp_adjtime, + .gettimex64 = icss_iep_ptp_gettimeex, + .settime64 = icss_iep_ptp_settime, + .enable = icss_iep_ptp_enable, +}; + +struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx) +{ + struct platform_device *pdev; + struct device_node *iep_np; + struct icss_iep *iep; + + iep_np = of_parse_phandle(np, "ti,iep", idx); + if (!iep_np || !of_device_is_available(iep_np)) + return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(iep_np); + of_node_put(iep_np); + + if (!pdev) + /* probably IEP not yet probed */ + return ERR_PTR(-EPROBE_DEFER); + + iep = platform_get_drvdata(pdev); + if (!iep) + return ERR_PTR(-EPROBE_DEFER); + + device_lock(iep->dev); + if (iep->client_np) { + device_unlock(iep->dev); + dev_err(iep->dev, "IEP is already acquired by %s", + iep->client_np->name); + return ERR_PTR(-EBUSY); + } + iep->client_np = np; + device_unlock(iep->dev); + get_device(iep->dev); + + return iep; +} +EXPORT_SYMBOL_GPL(icss_iep_get_idx); + +struct icss_iep *icss_iep_get(struct device_node *np) +{ + return icss_iep_get_idx(np, 0); +} +EXPORT_SYMBOL_GPL(icss_iep_get); + +void icss_iep_put(struct icss_iep *iep) +{ + device_lock(iep->dev); + iep->client_np = NULL; + device_unlock(iep->dev); + put_device(iep->dev); +} +EXPORT_SYMBOL_GPL(icss_iep_put); + +int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops, + void *clockops_data, u32 cycle_time_ns) +{ + int ret = 0; + + iep->cycle_time_ns = cycle_time_ns; + iep->clk_tick_time = iep->def_inc; + iep->ops = clkops; + iep->clockops_data = clockops_data; + icss_iep_set_default_inc(iep, iep->def_inc); + icss_iep_set_compensation_inc(iep, iep->def_inc); + icss_iep_set_compensation_count(iep, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */ + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT) + icss_iep_set_slow_compensation_count(iep, 0); + + if (!(iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) || + !(iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT)) + goto skip_perout; + + if (iep->ops && iep->ops->perout_enable) { + iep->ptp_info.n_per_out = 1; + iep->ptp_info.pps = 1; + } + + if (iep->ops && iep->ops->extts_enable) + iep->ptp_info.n_ext_ts = 2; + +skip_perout: + if (cycle_time_ns) + icss_iep_enable_shadow_mode(iep); + else + icss_iep_enable(iep); + icss_iep_settime(iep, ktime_get_real_ns()); + + iep->ptp_clock = ptp_clock_register(&iep->ptp_info, iep->dev); + if (IS_ERR(iep->ptp_clock)) { + ret = PTR_ERR(iep->ptp_clock); + iep->ptp_clock = NULL; + dev_err(iep->dev, "Failed to register ptp clk %d\n", ret); + } + + return ret; +} +EXPORT_SYMBOL_GPL(icss_iep_init); + +int icss_iep_exit(struct icss_iep *iep) +{ + if (iep->ptp_clock) { + ptp_clock_unregister(iep->ptp_clock); + iep->ptp_clock = NULL; + } + icss_iep_disable(iep); + + return 0; +} +EXPORT_SYMBOL_GPL(icss_iep_exit); + +static int icss_iep_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct icss_iep *iep; + struct clk *iep_clk; + + iep = devm_kzalloc(dev, sizeof(*iep), GFP_KERNEL); + if (!iep) + return -ENOMEM; + + iep->dev = dev; + iep->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(iep->base)) + return -ENODEV; + + iep_clk = devm_clk_get(dev, NULL); + if (IS_ERR(iep_clk)) + return PTR_ERR(iep_clk); + + iep->refclk_freq = clk_get_rate(iep_clk); + + iep->def_inc = NSEC_PER_SEC / iep->refclk_freq; /* ns per clock tick */ + if (iep->def_inc > IEP_MAX_DEF_INC) { + dev_err(dev, "Failed to set def_inc %d. IEP_clock is too slow to be supported\n", + iep->def_inc); + return -EINVAL; + } + + iep->plat_data = device_get_match_data(dev); + if (!iep->plat_data) + return -EINVAL; + + iep->map = devm_regmap_init(dev, NULL, iep, iep->plat_data->config); + if (IS_ERR(iep->map)) { + dev_err(dev, "Failed to create regmap for IEP %ld\n", + PTR_ERR(iep->map)); + return PTR_ERR(iep->map); + } + + iep->ptp_info = icss_iep_ptp_info; + mutex_init(&iep->ptp_clk_mutex); + spin_lock_init(&iep->irq_lock); + dev_set_drvdata(dev, iep); + icss_iep_disable(iep); + + return 0; +} + +static bool am654_icss_iep_valid_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ICSS_IEP_GLOBAL_CFG_REG ... ICSS_IEP_SYNC_START_REG: + return true; + default: + return false; + } + + return false; +} + +static int icss_iep_regmap_write(void *context, unsigned int reg, + unsigned int val) +{ + struct icss_iep *iep = context; + + writel(val, iep->base + iep->plat_data->reg_offs[reg]); + + return 0; +} + +static int icss_iep_regmap_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct icss_iep *iep = context; + + *val = readl(iep->base + iep->plat_data->reg_offs[reg]); + + return 0; +} + +static struct regmap_config am654_icss_iep_regmap_config = { + .name = "icss iep", + .reg_stride = 1, + .reg_write = icss_iep_regmap_write, + .reg_read = icss_iep_regmap_read, + .writeable_reg = am654_icss_iep_valid_reg, + .readable_reg = am654_icss_iep_valid_reg, + .fast_io = 1, +}; + +static const struct icss_iep_plat_data am654_icss_iep_plat_data = { + .flags = ICSS_IEP_64BIT_COUNTER_SUPPORT | + ICSS_IEP_SLOW_COMPEN_REG_SUPPORT | + ICSS_IEP_SHADOW_MODE_SUPPORT, + .reg_offs = { + [ICSS_IEP_GLOBAL_CFG_REG] = 0x00, + [ICSS_IEP_COMPEN_REG] = 0x08, + [ICSS_IEP_SLOW_COMPEN_REG] = 0x0C, + [ICSS_IEP_COUNT_REG0] = 0x10, + [ICSS_IEP_COUNT_REG1] = 0x14, + [ICSS_IEP_CAPTURE_CFG_REG] = 0x18, + [ICSS_IEP_CAPTURE_STAT_REG] = 0x1c, + + [ICSS_IEP_CAP6_RISE_REG0] = 0x50, + [ICSS_IEP_CAP6_RISE_REG1] = 0x54, + + [ICSS_IEP_CAP7_RISE_REG0] = 0x60, + [ICSS_IEP_CAP7_RISE_REG1] = 0x64, + + [ICSS_IEP_CMP_CFG_REG] = 0x70, + [ICSS_IEP_CMP_STAT_REG] = 0x74, + [ICSS_IEP_CMP0_REG0] = 0x78, + [ICSS_IEP_CMP0_REG1] = 0x7c, + [ICSS_IEP_CMP1_REG0] = 0x80, + [ICSS_IEP_CMP1_REG1] = 0x84, + + [ICSS_IEP_CMP8_REG0] = 0xc0, + [ICSS_IEP_CMP8_REG1] = 0xc4, + [ICSS_IEP_SYNC_CTRL_REG] = 0x180, + [ICSS_IEP_SYNC0_STAT_REG] = 0x188, + [ICSS_IEP_SYNC1_STAT_REG] = 0x18c, + [ICSS_IEP_SYNC_PWIDTH_REG] = 0x190, + [ICSS_IEP_SYNC0_PERIOD_REG] = 0x194, + [ICSS_IEP_SYNC1_DELAY_REG] = 0x198, + [ICSS_IEP_SYNC_START_REG] = 0x19c, + }, + .config = &am654_icss_iep_regmap_config, +}; + +static const struct of_device_id icss_iep_of_match[] = { + { + .compatible = "ti,am654-icss-iep", + .data = &am654_icss_iep_plat_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, icss_iep_of_match); + +static struct platform_driver icss_iep_driver = { + .driver = { + .name = "icss-iep", + .of_match_table = icss_iep_of_match, + }, + .probe = icss_iep_probe, +}; +module_platform_driver(icss_iep_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TI ICSS IEP driver"); +MODULE_AUTHOR("Roger Quadros "); +MODULE_AUTHOR("Md Danish Anwar "); diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.h b/drivers/net/ethernet/ti/icssg/icss_iep.h new file mode 100644 index 000000000000..9eee44ae4990 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icss_iep.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSS_IEP_H +#define __NET_TI_ICSS_IEP_H + +#include +#include +#include + +struct icss_iep; + +/* Firmware specific clock operations */ +struct icss_iep_clockops { + void (*settime)(void *clockops_data, u64 ns); + void (*adjtime)(void *clockops_data, s64 delta); + u64 (*gettime)(void *clockops_data, struct ptp_system_timestamp *sts); + int (*perout_enable)(void *clockops_data, + struct ptp_perout_request *req, int on, + u64 *cmp); + int (*extts_enable)(void *clockops_data, u32 index, int on); +}; + +struct icss_iep *icss_iep_get(struct device_node *np); +struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx); +void icss_iep_put(struct icss_iep *iep); +int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops, + void *clockops_data, u32 cycle_time_ns); +int icss_iep_exit(struct icss_iep *iep); +int icss_iep_get_count_low(struct icss_iep *iep); +int icss_iep_get_count_hi(struct icss_iep *iep); +int icss_iep_get_ptp_clock_idx(struct icss_iep *iep); + +#endif /* __NET_TI_ICSS_IEP_H */ -- cgit From 186734c158865747f7160b461afcabfaab8f9bca Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 24 Aug 2023 17:16:17 +0530 Subject: net: ti: icssg-prueth: add packet timestamping and ptp support Add packet timestamping TS and PTP PHC clock support. For AM65x and AM64x: - IEP1 is not used - IEP0 is configured in shadow mode with 1ms cycle and shared between Linux and FW. It provides time and TS in number cycles, so special conversation in ns is required. - IEP0 shared between PRUeth ports. - IEP0 supports PPS, periodic output. - IEP0 settime() and enabling PPS required FW interraction. - RX TS provided with each packet in CPPI5 descriptor. - TX TS returned through separate ICSSG hw queues for each port. TX TS readiness is signaled by INTC IRQ. Only one packet at time can be requested for TX TS. Signed-off-by: Roger Quadros Co-developed-by: Grygorii Strashko Signed-off-by: Grygorii Strashko Signed-off-by: Vignesh Raghavendra Reviewed-by: Simon Horman Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/Kconfig | 1 + drivers/net/ethernet/ti/icssg/icss_iep.h | 1 + drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 21 ++ drivers/net/ethernet/ti/icssg/icssg_prueth.c | 424 +++++++++++++++++++++++++- drivers/net/ethernet/ti/icssg/icssg_prueth.h | 26 +- 5 files changed, 467 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 1af5a90720ec..88b5b1b47779 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -186,6 +186,7 @@ config CPMAC config TI_ICSSG_PRUETH tristate "TI Gigabit PRU Ethernet driver" select PHYLIB + select TI_ICSS_IEP depends on PRU_REMOTEPROC depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER help diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.h b/drivers/net/ethernet/ti/icssg/icss_iep.h index 9eee44ae4990..9c7f4d0a0916 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.h +++ b/drivers/net/ethernet/ti/icssg/icss_iep.h @@ -13,6 +13,7 @@ #include struct icss_iep; +extern const struct icss_iep_clockops prueth_iep_clockops; /* Firmware specific clock operations */ struct icss_iep_clockops { diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c index 02c312f01d10..a27ec1dcc8d5 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c @@ -109,6 +109,26 @@ static void emac_get_ethtool_stats(struct net_device *ndev, *(data++) = emac->stats[i]; } +static int emac_get_ts_info(struct net_device *ndev, + struct ethtool_ts_info *info) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + info->so_timestamping = + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + info->phc_index = icss_iep_get_ptp_clock_idx(emac->iep); + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); + + return 0; +} + static int emac_set_channels(struct net_device *ndev, struct ethtool_channels *ch) { @@ -176,6 +196,7 @@ const struct ethtool_ops icssg_ethtool_ops = { .get_sset_count = emac_get_sset_count, .get_ethtool_stats = emac_get_ethtool_stats, .get_strings = emac_get_strings, + .get_ts_info = emac_get_ts_info, .get_channels = emac_get_channels, .set_channels = emac_set_channels, .get_link_ksettings = emac_get_link_ksettings, diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 47b941fb0198..1bcb4e174652 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -56,6 +56,8 @@ /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) +#define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ + static void prueth_cleanup_rx_chns(struct prueth_emac *emac, struct prueth_rx_chn *rx_chn, int max_rflows) @@ -471,6 +473,37 @@ static int prueth_dma_rx_push(struct prueth_emac *emac, desc_rx, desc_dma); } +static u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns) +{ + u32 iepcount_lo, iepcount_hi, hi_rollover_count; + u64 ns; + + iepcount_lo = lo & GENMASK(19, 0); + iepcount_hi = (hi & GENMASK(11, 0)) << 12 | lo >> 20; + hi_rollover_count = hi >> 11; + + ns = ((u64)hi_rollover_count) << 23 | (iepcount_hi + hi_sw); + ns = ns * cycle_time_ns + iepcount_lo; + + return ns; +} + +static void emac_rx_timestamp(struct prueth_emac *emac, + struct sk_buff *skb, u32 *psdata) +{ + struct skb_shared_hwtstamps *ssh; + u64 ns; + + u32 hi_sw = readl(emac->prueth->shram.va + + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET); + ns = icssg_ts_to_ns(hi_sw, psdata[1], psdata[0], + IEP_DEFAULT_CYCLE_TIME_NS); + + ssh = skb_hwtstamps(skb); + memset(ssh, 0, sizeof(*ssh)); + ssh->hwtstamp = ns_to_ktime(ns); +} + static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) { struct prueth_rx_chn *rx_chn = &emac->rx_chns; @@ -480,6 +513,7 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) struct sk_buff *skb, *new_skb; dma_addr_t desc_dma, buf_dma; void **swdata; + u32 *psdata; int ret; ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma); @@ -497,6 +531,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) swdata = cppi5_hdesc_get_swdata(desc_rx); skb = *swdata; + psdata = cppi5_hdesc_get_psdata(desc_rx); + /* RX HW timestamp */ + if (emac->rx_ts_enabled) + emac_rx_timestamp(emac, skb, psdata); + cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); pkt_len = cppi5_hdesc_get_pktlen(desc_rx); @@ -557,6 +596,86 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma) dev_kfree_skb_any(skb); } +static int emac_get_tx_ts(struct prueth_emac *emac, + struct emac_tx_ts_response *rsp) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + int addr; + + addr = icssg_queue_pop(prueth, slice == 0 ? + ICSSG_TS_POP_SLICE0 : ICSSG_TS_POP_SLICE1); + if (addr < 0) + return addr; + + memcpy_fromio(rsp, prueth->shram.va + addr, sizeof(*rsp)); + /* return buffer back for to pool */ + icssg_queue_push(prueth, slice == 0 ? + ICSSG_TS_PUSH_SLICE0 : ICSSG_TS_PUSH_SLICE1, addr); + + return 0; +} + +static void tx_ts_work(struct prueth_emac *emac) +{ + struct skb_shared_hwtstamps ssh; + struct emac_tx_ts_response tsr; + struct sk_buff *skb; + int ret = 0; + u32 hi_sw; + u64 ns; + + /* There may be more than one pending requests */ + while (1) { + ret = emac_get_tx_ts(emac, &tsr); + if (ret) /* nothing more */ + break; + + if (tsr.cookie >= PRUETH_MAX_TX_TS_REQUESTS || + !emac->tx_ts_skb[tsr.cookie]) { + netdev_err(emac->ndev, "Invalid TX TS cookie 0x%x\n", + tsr.cookie); + break; + } + + skb = emac->tx_ts_skb[tsr.cookie]; + emac->tx_ts_skb[tsr.cookie] = NULL; /* free slot */ + if (!skb) { + netdev_err(emac->ndev, "Driver Bug! got NULL skb\n"); + break; + } + + hi_sw = readl(emac->prueth->shram.va + + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET); + ns = icssg_ts_to_ns(hi_sw, tsr.hi_ts, tsr.lo_ts, + IEP_DEFAULT_CYCLE_TIME_NS); + + memset(&ssh, 0, sizeof(ssh)); + ssh.hwtstamp = ns_to_ktime(ns); + + skb_tstamp_tx(skb, &ssh); + dev_consume_skb_any(skb); + + if (atomic_dec_and_test(&emac->tx_ts_pending)) /* no more? */ + break; + } +} + +static int prueth_tx_ts_cookie_get(struct prueth_emac *emac) +{ + int i; + + /* search and get the next free slot */ + for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) { + if (!emac->tx_ts_skb[i]) { + emac->tx_ts_skb[i] = ERR_PTR(-EBUSY); /* reserve slot */ + return i; + } + } + + return -EBUSY; +} + /** * emac_ndo_start_xmit - EMAC Transmit function * @skb: SKB pointer @@ -577,6 +696,8 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device struct prueth_tx_chn *tx_chn; dma_addr_t desc_dma, buf_dma; int i, ret = 0, q_idx; + bool in_tx_ts = 0; + int tx_ts_cookie; void **swdata; u32 pkt_len; u32 *epib; @@ -608,6 +729,18 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device epib = first_desc->epib; epib[0] = 0; epib[1] = 0; + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + emac->tx_ts_enabled) { + tx_ts_cookie = prueth_tx_ts_cookie_get(emac); + if (tx_ts_cookie >= 0) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + /* Request TX timestamp */ + epib[0] = (u32)tx_ts_cookie; + epib[1] = 0x80000000; /* TX TS request */ + emac->tx_ts_skb[tx_ts_cookie] = skb_get(skb); + in_tx_ts = 1; + } + } /* set dst tag to indicate internal qid at the firmware which is at * bit8..bit15. bit0..bit7 indicates port num for directed @@ -629,7 +762,7 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device if (!next_desc) { netdev_err(ndev, "tx: failed to allocate frag. descriptor\n"); - goto free_desc_stop_q_busy; + goto free_desc_stop_q_busy_cleanup_tx_ts; } buf_dma = skb_frag_dma_map(tx_chn->dma_dev, frag, 0, frag_size, @@ -638,7 +771,7 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device netdev_err(ndev, "tx: Failed to map skb page\n"); k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); ret = NETDEV_TX_OK; - goto drop_free_descs; + goto cleanup_tx_ts; } cppi5_hdesc_reset_hbdesc(next_desc); @@ -670,6 +803,9 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device goto drop_free_descs; } + if (in_tx_ts) + atomic_inc(&emac->tx_ts_pending); + if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) { netif_tx_stop_queue(netif_txq); /* Barrier, so that stop_queue visible to other cpus */ @@ -682,6 +818,12 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device return NETDEV_TX_OK; +cleanup_tx_ts: + if (in_tx_ts) { + dev_kfree_skb_any(emac->tx_ts_skb[tx_ts_cookie]); + emac->tx_ts_skb[tx_ts_cookie] = NULL; + } + drop_free_descs: prueth_xmit_free(tx_chn, first_desc); @@ -694,7 +836,11 @@ drop_free_skb: return ret; -free_desc_stop_q_busy: +free_desc_stop_q_busy_cleanup_tx_ts: + if (in_tx_ts) { + dev_kfree_skb_any(emac->tx_ts_skb[tx_ts_cookie]); + emac->tx_ts_skb[tx_ts_cookie] = NULL; + } prueth_xmit_free(tx_chn, first_desc); drop_stop_q_busy: @@ -717,6 +863,16 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma) dev_kfree_skb_any(skb); } +static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id) +{ + struct prueth_emac *emac = dev_id; + + /* currently only TX timestamp is being returned */ + tx_ts_work(emac); + + return IRQ_HANDLED; +} + static irqreturn_t prueth_rx_irq(int irq, void *dev_id) { struct prueth_emac *emac = dev_id; @@ -820,6 +976,18 @@ static void prueth_emac_stop(struct prueth_emac *emac) rproc_shutdown(prueth->pru[slice]); } +static void prueth_cleanup_tx_ts(struct prueth_emac *emac) +{ + int i; + + for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) { + if (emac->tx_ts_skb[i]) { + dev_kfree_skb_any(emac->tx_ts_skb[i]); + emac->tx_ts_skb[i] = NULL; + } + } +} + /* called back by PHY layer if there is change in link state of hw port*/ static void emac_adjust_link(struct net_device *ndev) { @@ -881,6 +1049,7 @@ static void emac_adjust_link(struct net_device *ndev) netif_tx_wake_all_queues(ndev); } else { netif_tx_stop_all_queues(ndev); + prueth_cleanup_tx_ts(emac); } } @@ -992,6 +1161,139 @@ static int emac_phy_connect(struct prueth_emac *emac) return 0; } +static u64 prueth_iep_gettime(void *clockops_data, struct ptp_system_timestamp *sts) +{ + u32 hi_rollover_count, hi_rollover_count_r; + struct prueth_emac *emac = clockops_data; + struct prueth *prueth = emac->prueth; + void __iomem *fw_hi_r_count_addr; + void __iomem *fw_count_hi_addr; + u32 iepcount_hi, iepcount_hi_r; + unsigned long flags; + u32 iepcount_lo; + u64 ts = 0; + + fw_count_hi_addr = prueth->shram.va + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET; + fw_hi_r_count_addr = prueth->shram.va + TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET; + + local_irq_save(flags); + do { + iepcount_hi = icss_iep_get_count_hi(emac->iep); + iepcount_hi += readl(fw_count_hi_addr); + hi_rollover_count = readl(fw_hi_r_count_addr); + ptp_read_system_prets(sts); + iepcount_lo = icss_iep_get_count_low(emac->iep); + ptp_read_system_postts(sts); + + iepcount_hi_r = icss_iep_get_count_hi(emac->iep); + iepcount_hi_r += readl(fw_count_hi_addr); + hi_rollover_count_r = readl(fw_hi_r_count_addr); + } while ((iepcount_hi_r != iepcount_hi) || + (hi_rollover_count != hi_rollover_count_r)); + local_irq_restore(flags); + + ts = ((u64)hi_rollover_count) << 23 | iepcount_hi; + ts = ts * (u64)IEP_DEFAULT_CYCLE_TIME_NS + iepcount_lo; + + return ts; +} + +static void prueth_iep_settime(void *clockops_data, u64 ns) +{ + struct icssg_setclock_desc __iomem *sc_descp; + struct prueth_emac *emac = clockops_data; + struct icssg_setclock_desc sc_desc; + u64 cyclecount; + u32 cycletime; + int timeout; + + if (!emac->fw_running) + return; + + sc_descp = emac->prueth->shram.va + TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET; + + cycletime = IEP_DEFAULT_CYCLE_TIME_NS; + cyclecount = ns / cycletime; + + memset(&sc_desc, 0, sizeof(sc_desc)); + sc_desc.margin = cycletime - 1000; + sc_desc.cyclecounter0_set = cyclecount & GENMASK(31, 0); + sc_desc.cyclecounter1_set = (cyclecount & GENMASK(63, 32)) >> 32; + sc_desc.iepcount_set = ns % cycletime; + sc_desc.CMP0_current = cycletime - 4; //Count from 0 to (cycle time)-4 + + memcpy_toio(sc_descp, &sc_desc, sizeof(sc_desc)); + + writeb(1, &sc_descp->request); + + timeout = 5; /* fw should take 2-3 ms */ + while (timeout--) { + if (readb(&sc_descp->acknowledgment)) + return; + + usleep_range(500, 1000); + } + + dev_err(emac->prueth->dev, "settime timeout\n"); +} + +static int prueth_perout_enable(void *clockops_data, + struct ptp_perout_request *req, int on, + u64 *cmp) +{ + struct prueth_emac *emac = clockops_data; + u32 reduction_factor = 0, offset = 0; + struct timespec64 ts; + u64 ns_period; + + if (!on) + return 0; + + /* Any firmware specific stuff for PPS/PEROUT handling */ + ts.tv_sec = req->period.sec; + ts.tv_nsec = req->period.nsec; + ns_period = timespec64_to_ns(&ts); + + /* f/w doesn't support period less than cycle time */ + if (ns_period < IEP_DEFAULT_CYCLE_TIME_NS) + return -ENXIO; + + reduction_factor = ns_period / IEP_DEFAULT_CYCLE_TIME_NS; + offset = ns_period % IEP_DEFAULT_CYCLE_TIME_NS; + + /* f/w requires at least 1uS within a cycle so CMP + * can trigger after SYNC is enabled + */ + if (offset < 5 * NSEC_PER_USEC) + offset = 5 * NSEC_PER_USEC; + + /* if offset is close to cycle time then we will miss + * the CMP event for last tick when IEP rolls over. + * In normal mode, IEP tick is 4ns. + * In slow compensation it could be 0ns or 8ns at + * every slow compensation cycle. + */ + if (offset > IEP_DEFAULT_CYCLE_TIME_NS - 8) + offset = IEP_DEFAULT_CYCLE_TIME_NS - 8; + + /* we're in shadow mode so need to set upper 32-bits */ + *cmp = (u64)offset << 32; + + writel(reduction_factor, emac->prueth->shram.va + + TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET); + + writel(0, emac->prueth->shram.va + + TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET); + + return 0; +} + +const struct icss_iep_clockops prueth_iep_clockops = { + .settime = prueth_iep_settime, + .gettime = prueth_iep_gettime, + .perout_enable = prueth_perout_enable, +}; + /** * emac_ndo_open - EMAC device open * @ndev: network adapter device @@ -1066,10 +1368,20 @@ static int emac_ndo_open(struct net_device *ndev) icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu); + if (!prueth->emacs_initialized) { + ret = icss_iep_init(emac->iep, &prueth_iep_clockops, + emac, IEP_DEFAULT_CYCLE_TIME_NS); + } + + ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq, + IRQF_ONESHOT, dev_name(dev), emac); + if (ret) + goto stop; + /* Prepare RX */ ret = prueth_prepare_rx_chan(emac, &emac->rx_chns, PRUETH_MAX_PKT_SIZE); if (ret) - goto stop; + goto free_tx_ts_irq; ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn); if (ret) @@ -1102,6 +1414,8 @@ reset_tx_chan: prueth_reset_tx_chan(emac, i, false); reset_rx_chn: prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false); +free_tx_ts_irq: + free_irq(emac->tx_ts_irq, emac); stop: prueth_emac_stop(emac); free_rx_irq: @@ -1173,6 +1487,14 @@ static int emac_ndo_stop(struct net_device *ndev) /* stop PRUs */ prueth_emac_stop(emac); + if (prueth->emacs_initialized == 1) + icss_iep_exit(emac->iep); + + /* stop PRUs */ + prueth_emac_stop(emac); + + free_irq(emac->tx_ts_irq, emac); + free_irq(emac->rx_chns.irq[rx_flow], emac); prueth_ndev_del_tx_napi(emac, emac->tx_ch_num); prueth_cleanup_tx_chns(emac); @@ -1235,8 +1557,79 @@ static void emac_ndo_set_rx_mode(struct net_device *ndev) queue_work(emac->cmd_wq, &emac->rx_mode_work); } +static int emac_set_ts_config(struct net_device *ndev, struct ifreq *ifr) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct hwtstamp_config config; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + emac->tx_ts_enabled = 0; + break; + case HWTSTAMP_TX_ON: + emac->tx_ts_enabled = 1; + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + emac->rx_ts_enabled = 0; + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + emac->rx_ts_enabled = 1; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + +static int emac_get_ts_config(struct net_device *ndev, struct ifreq *ifr) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct hwtstamp_config config; + + config.flags = 0; + config.tx_type = emac->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config.rx_filter = emac->rx_ts_enabled ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) { + switch (cmd) { + case SIOCGHWTSTAMP: + return emac_get_ts_config(ndev, ifr); + case SIOCSHWTSTAMP: + return emac_set_ts_config(ndev, ifr); + default: + break; + } + return phy_do_ioctl(ndev, ifr, cmd); } @@ -1316,6 +1709,7 @@ static int prueth_netdev_init(struct prueth *prueth, struct prueth_emac *emac; struct net_device *ndev; enum prueth_port port; + const char *irq_name; enum prueth_mac mac; port = prueth_node_port(eth_node); @@ -1355,6 +1749,15 @@ static int prueth_netdev_init(struct prueth *prueth, emac->tx_ch_num = 1; + irq_name = "tx_ts0"; + if (emac->port_id == PRUETH_PORT_MII1) + irq_name = "tx_ts1"; + emac->tx_ts_irq = platform_get_irq_byname_optional(prueth->pdev, irq_name); + if (emac->tx_ts_irq < 0) { + ret = dev_err_probe(prueth->dev, emac->tx_ts_irq, "could not get tx_ts_irq\n"); + goto free; + } + SET_NETDEV_DEV(ndev, prueth->dev); spin_lock_init(&emac->lock); mutex_init(&emac->cmd_lock); @@ -1680,6 +2083,13 @@ static int prueth_probe(struct platform_device *pdev) dev_dbg(dev, "sram: pa %llx va %p size %zx\n", prueth->msmcram.pa, prueth->msmcram.va, prueth->msmcram.size); + prueth->iep0 = icss_iep_get_idx(np, 0); + if (IS_ERR(prueth->iep0)) { + ret = dev_err_probe(dev, PTR_ERR(prueth->iep0), "iep0 get failed\n"); + prueth->iep0 = NULL; + goto free_pool; + } + /* setup netdev interfaces */ if (eth0_node) { ret = prueth_netdev_init(prueth, eth0_node); @@ -1688,6 +2098,7 @@ static int prueth_probe(struct platform_device *pdev) eth0_node->name); goto netdev_exit; } + prueth->emac[PRUETH_MAC0]->iep = prueth->iep0; } if (eth1_node) { @@ -1697,6 +2108,8 @@ static int prueth_probe(struct platform_device *pdev) eth1_node->name); goto netdev_exit; } + + prueth->emac[PRUETH_MAC1]->iep = prueth->iep0; } /* register the network devices */ @@ -1754,6 +2167,7 @@ netdev_exit: prueth_netdev_exit(prueth, eth_node); } +free_pool: gen_pool_free(prueth->sram_pool, (unsigned long)prueth->msmcram.va, msmc_ram_size); @@ -1798,6 +2212,8 @@ static void prueth_remove(struct platform_device *pdev) prueth_netdev_exit(prueth, eth_node); } + icss_iep_put(prueth->iep0); + gen_pool_free(prueth->sram_pool, (unsigned long)prueth->msmcram.va, MSMC_RAM_SIZE); diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index a8ce4d01ef16..a56ab4cdc83c 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -35,6 +35,7 @@ #include #include "icssg_config.h" +#include "icss_iep.h" #include "icssg_switch_map.h" #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN) @@ -122,6 +123,8 @@ struct prueth_rx_chn { */ #define PRUETH_MAX_TX_QUEUES 4 +#define PRUETH_MAX_TX_TS_REQUESTS 50 /* Max simultaneous TX_TS requests */ + /* data for each emac port */ struct prueth_emac { bool fw_running; @@ -139,6 +142,9 @@ struct prueth_emac { struct device_node *phy_node; phy_interface_t phy_if; enum prueth_port port_id; + struct icss_iep *iep; + unsigned int rx_ts_enabled : 1; + unsigned int tx_ts_enabled : 1; /* DMA related */ struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES]; @@ -150,7 +156,15 @@ struct prueth_emac { spinlock_t lock; /* serialize access */ - unsigned long state; + /* TX HW Timestamping */ + /* TX TS cookie will be index to the tx_ts_skb array */ + struct sk_buff *tx_ts_skb[PRUETH_MAX_TX_TS_REQUESTS]; + atomic_t tx_ts_pending; + int tx_ts_irq; + + u8 cmd_seq; + /* shutdown related */ + u32 cmd_data[4]; struct completion cmd_complete; /* Mutex to serialize access to firmware command interface */ struct mutex cmd_lock; @@ -193,6 +207,7 @@ struct prueth_pdata { * @pdata: pointer to platform data for ICSSG driver * @icssg_hwcmdseq: seq counter or HWQ messages * @emacs_initialized: num of EMACs/ext ports that are up/running + * @iep0: pointer to IEP0 device */ struct prueth { struct device *dev; @@ -214,8 +229,15 @@ struct prueth { struct platform_device *pdev; struct prueth_pdata pdata; u8 icssg_hwcmdseq; - int emacs_initialized; + struct icss_iep *iep0; +}; + +struct emac_tx_ts_response { + u32 reserved[2]; + u32 cookie; + u32 lo_ts; + u32 hi_ts; }; /* get PRUSS SLICE number from prueth_emac */ -- cgit From 443a2367ba3c96e0f35ce801bcdfb2ce91f5038c Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 24 Aug 2023 17:16:18 +0530 Subject: net: ti: icssg-prueth: am65x SR2.0 add 10M full duplex support For AM65x SR2.0 it's required to enable IEP1 in raw 64bit mode which is used by PRU FW to monitor the link and apply w/a for 10M link issue. Note. No public errata available yet. Without this w/a the PRU FW will stuck if link state changes under TX traffic pressure. Hence, add support for 10M full duplex for AM65x SR2.0: - add new IEP API to enable IEP, but without PTP support - add pdata quirk_10m_link_issue to enable 10M link issue w/a. Signed-off-by: Grygorii Strashko Signed-off-by: Vignesh Raghavendra Reviewed-by: Roger Quadros Reviewed-by: Simon Horman Reviewed-by: Jacob Keller Signed-off-by: MD Danish Anwar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/icssg/icss_iep.c | 26 ++++++++++++++++++++++++++ drivers/net/ethernet/ti/icssg/icss_iep.h | 2 ++ drivers/net/ethernet/ti/icssg/icssg_config.c | 7 +++++++ drivers/net/ethernet/ti/icssg/icssg_prueth.c | 27 +++++++++++++++++++++++++-- drivers/net/ethernet/ti/icssg/icssg_prueth.h | 2 ++ 5 files changed, 62 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c index bcc056bf45da..4cf2a52e4378 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.c +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -727,6 +727,32 @@ void icss_iep_put(struct icss_iep *iep) } EXPORT_SYMBOL_GPL(icss_iep_put); +void icss_iep_init_fw(struct icss_iep *iep) +{ + /* start IEP for FW use in raw 64bit mode, no PTP support */ + iep->clk_tick_time = iep->def_inc; + iep->cycle_time_ns = 0; + iep->ops = NULL; + iep->clockops_data = NULL; + icss_iep_set_default_inc(iep, iep->def_inc); + icss_iep_set_compensation_inc(iep, iep->def_inc); + icss_iep_set_compensation_count(iep, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */ + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT) + icss_iep_set_slow_compensation_count(iep, 0); + + icss_iep_enable(iep); + icss_iep_settime(iep, 0); +} +EXPORT_SYMBOL_GPL(icss_iep_init_fw); + +void icss_iep_exit_fw(struct icss_iep *iep) +{ + icss_iep_disable(iep); +} +EXPORT_SYMBOL_GPL(icss_iep_exit_fw); + int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops, void *clockops_data, u32 cycle_time_ns) { diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.h b/drivers/net/ethernet/ti/icssg/icss_iep.h index 9c7f4d0a0916..803a4b714893 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.h +++ b/drivers/net/ethernet/ti/icssg/icss_iep.h @@ -35,5 +35,7 @@ int icss_iep_exit(struct icss_iep *iep); int icss_iep_get_count_low(struct icss_iep *iep); int icss_iep_get_count_hi(struct icss_iep *iep); int icss_iep_get_ptp_clock_idx(struct icss_iep *iep); +void icss_iep_init_fw(struct icss_iep *iep); +void icss_iep_exit_fw(struct icss_iep *iep); #endif /* __NET_TI_ICSS_IEP_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c index ab648d3efe85..933b84666574 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.c +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -210,6 +210,10 @@ void icssg_config_ipg(struct prueth_emac *emac) case SPEED_100: icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); break; + case SPEED_10: + /* IPG for 10M is same as 100M */ + icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); + break; default: /* Other links speeds not supported */ netdev_err(emac->ndev, "Unsupported link speed\n"); @@ -440,6 +444,9 @@ void icssg_config_set_speed(struct prueth_emac *emac) case SPEED_100: fw_speed = FW_LINK_SPEED_100M; break; + case SPEED_10: + fw_speed = FW_LINK_SPEED_10M; + break; default: /* Other links speeds not supported */ netdev_err(emac->ndev, "Unsupported link speed\n"); diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 1bcb4e174652..410612f43cbd 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -1149,7 +1149,6 @@ static int emac_phy_connect(struct prueth_emac *emac) /* remove unsupported modes */ phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); - phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT); @@ -2090,13 +2089,29 @@ static int prueth_probe(struct platform_device *pdev) goto free_pool; } + prueth->iep1 = icss_iep_get_idx(np, 1); + if (IS_ERR(prueth->iep1)) { + ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n"); + icss_iep_put(prueth->iep0); + prueth->iep0 = NULL; + prueth->iep1 = NULL; + goto free_pool; + } + + if (prueth->pdata.quirk_10m_link_issue) { + /* Enable IEP1 for FW in 64bit mode as W/A for 10M FD link detect issue under TX + * traffic. + */ + icss_iep_init_fw(prueth->iep1); + } + /* setup netdev interfaces */ if (eth0_node) { ret = prueth_netdev_init(prueth, eth0_node); if (ret) { dev_err_probe(dev, ret, "netdev init %s failed\n", eth0_node->name); - goto netdev_exit; + goto exit_iep; } prueth->emac[PRUETH_MAC0]->iep = prueth->iep0; } @@ -2167,6 +2182,10 @@ netdev_exit: prueth_netdev_exit(prueth, eth_node); } +exit_iep: + if (prueth->pdata.quirk_10m_link_issue) + icss_iep_exit_fw(prueth->iep1); + free_pool: gen_pool_free(prueth->sram_pool, (unsigned long)prueth->msmcram.va, msmc_ram_size); @@ -2212,6 +2231,10 @@ static void prueth_remove(struct platform_device *pdev) prueth_netdev_exit(prueth, eth_node); } + if (prueth->pdata.quirk_10m_link_issue) + icss_iep_exit_fw(prueth->iep1); + + icss_iep_put(prueth->iep1); icss_iep_put(prueth->iep0); gen_pool_free(prueth->sram_pool, diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index a56ab4cdc83c..3fe80a8758d3 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -208,6 +208,7 @@ struct prueth_pdata { * @icssg_hwcmdseq: seq counter or HWQ messages * @emacs_initialized: num of EMACs/ext ports that are up/running * @iep0: pointer to IEP0 device + * @iep1: pointer to IEP1 device */ struct prueth { struct device *dev; @@ -231,6 +232,7 @@ struct prueth { u8 icssg_hwcmdseq; int emacs_initialized; struct icss_iep *iep0; + struct icss_iep *iep1; }; struct emac_tx_ts_response { -- cgit From c46fb77383a6d5eea723c785135e79d73614f1c3 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 24 Aug 2023 23:28:31 -0700 Subject: net/mlx5: Drop extra layer of locks in IPsec There is no need in holding devlink lock as it gives nothing compared to already used write mode_lock. Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230825062836.103744-4-saeed@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 67eab99f95b1..28c4b9724e38 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3903,38 +3903,28 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode) bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - devl_lock(devlink); - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) { - devl_unlock(devlink); - /* Failure means no eswitch => not possible to change encap */ + if (!mlx5_esw_allowed(esw)) return true; - } down_write(&esw->mode_lock); if (esw->mode != MLX5_ESWITCH_LEGACY && esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) { up_write(&esw->mode_lock); - devl_unlock(devlink); return false; } esw->offloads.num_block_encap++; up_write(&esw->mode_lock); - devl_unlock(devlink); return true; } void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) + if (!mlx5_esw_allowed(esw)) return; down_write(&esw->mode_lock); -- cgit From e2537341667830fa1e6dd51bc9dbf19c58954d35 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 24 Aug 2023 23:28:32 -0700 Subject: net/mlx5e: Rewrite IPsec vs. TC block interface In the commit 366e46242b8e ("net/mlx5e: Make IPsec offload work together with eswitch and TC"), new API to block IPsec vs. TC creation was introduced. Internally, that API used devlink lock to avoid races with userspace, but it is not really needed as dev->priv.eswitch is stable and can't be changed. So remove dependency on devlink lock and move block encap code back to its original place. Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230825062836.103744-5-saeed@kernel.org Signed-off-by: Jakub Kicinski --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 63 +++++++++------------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 15 ++---- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 53 ++++-------------- 3 files changed, 38 insertions(+), 93 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index a1cfddd05bc4..7dba4221993f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -254,6 +254,8 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, mlx5_del_flow_rules(rx->sa.rule); mlx5_destroy_flow_group(rx->sa.group); mlx5_destroy_flow_table(rx->ft.sa); + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); if (rx == ipsec->rx_esw) { mlx5_esw_ipsec_rx_status_destroy(ipsec, rx); } else { @@ -357,6 +359,8 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, goto err_add; /* Create FT */ + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (rx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(attr.ns, attr.sa_level, attr.prio, 2, flags); @@ -411,6 +415,8 @@ err_pol_ft: err_fs: mlx5_destroy_flow_table(rx->ft.sa); err_fs_ft: + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(rx->status.rule); mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); err_add: @@ -428,26 +434,19 @@ static int rx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (rx->ft.refcnt) goto skip; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); - - err = mlx5_eswitch_block_mode_trylock(mdev); + err = mlx5_eswitch_block_mode(mdev); if (err) - goto err_out; + return err; err = rx_create(mdev, ipsec, rx, family); - mlx5_eswitch_block_mode_unlock(mdev, err); - if (err) - goto err_out; + if (err) { + mlx5_eswitch_unblock_mode(mdev); + return err; + } skip: rx->ft.refcnt++; return 0; - -err_out: - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); - return err; } static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, @@ -456,12 +455,8 @@ static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, if (--rx->ft.refcnt) return; - mlx5_eswitch_unblock_mode_lock(ipsec->mdev); rx_destroy(ipsec->mdev, ipsec, rx, family); - mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); - - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(ipsec->mdev); + mlx5_eswitch_unblock_mode(ipsec->mdev); } static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, @@ -581,6 +576,8 @@ static void tx_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, mlx5_destroy_flow_group(tx->sa.group); } mlx5_destroy_flow_table(tx->ft.sa); + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(ipsec->mdev); mlx5_del_flow_rules(tx->status.rule); mlx5_destroy_flow_table(tx->ft.status); } @@ -621,6 +618,8 @@ static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, if (err) goto err_status_rule; + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (tx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(tx->ns, attr.sa_level, attr.prio, 4, flags); @@ -687,6 +686,8 @@ err_pol_ft: err_sa_miss: mlx5_destroy_flow_table(tx->ft.sa); err_sa_ft: + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(tx->status.rule); err_status_rule: mlx5_destroy_flow_table(tx->ft.status); @@ -720,32 +721,22 @@ static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (tx->ft.refcnt) goto skip; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); - - err = mlx5_eswitch_block_mode_trylock(mdev); + err = mlx5_eswitch_block_mode(mdev); if (err) - goto err_out; + return err; err = tx_create(ipsec, tx, ipsec->roce); if (err) { - mlx5_eswitch_block_mode_unlock(mdev, err); - goto err_out; + mlx5_eswitch_unblock_mode(mdev); + return err; } if (tx == ipsec->tx_esw) ipsec_esw_tx_ft_policy_set(mdev, tx->ft.pol); - mlx5_eswitch_block_mode_unlock(mdev, err); - skip: tx->ft.refcnt++; return 0; - -err_out: - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); - return err; } static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) @@ -753,19 +744,13 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) if (--tx->ft.refcnt) return; - mlx5_eswitch_unblock_mode_lock(ipsec->mdev); - if (tx == ipsec->tx_esw) { mlx5_esw_ipsec_restore_dest_uplink(ipsec->mdev); ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); } tx_destroy(ipsec, tx, ipsec->roce); - - mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); - - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(ipsec->mdev); + mlx5_eswitch_unblock_mode(ipsec->mdev); } static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 6fcece69d3be..ed3abcd70c46 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -829,10 +829,8 @@ int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev); void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev); -int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev); -void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err); -void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev); -void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev); +int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev); +void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev); static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) { @@ -916,13 +914,8 @@ static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) { } -static inline int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) { return 0; } - -static inline void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) {} - -static inline void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) {} - -static inline void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) {} +static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; } +static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESWITCH_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 28c4b9724e38..d4697dadd27d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3641,65 +3641,32 @@ static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink) return net_eq(devl_net, netdev_net); } -int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) +int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; int err; - devl_lock(devlink); - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) { - /* Failure means no eswitch => not possible to change eswitch mode */ - devl_unlock(devlink); + if (!mlx5_esw_allowed(esw)) return 0; - } + /* Take TC into account */ err = mlx5_esw_try_lock(esw); - if (err < 0) { - devl_unlock(devlink); + if (err < 0) return err; - } - - return 0; -} - -void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) -{ - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; - - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) - return; - if (!err) - esw->offloads.num_block_mode++; + esw->offloads.num_block_mode++; mlx5_esw_unlock(esw); - devl_unlock(devlink); + return 0; } -void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) +void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) + if (!mlx5_esw_allowed(esw)) return; down_write(&esw->mode_lock); -} - -void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) -{ - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; - - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) - return; - esw->offloads.num_block_mode--; up_write(&esw->mode_lock); } -- cgit From 8efd7b17a3b03242c97281d88463ad56e8f551f8 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 24 Aug 2023 23:28:34 -0700 Subject: net/mlx5: Provide an interface to block change of IPsec capabilities mlx5 HW can't perform IPsec offload operation simultaneously both on PF and VFs at the same time. While the previous patches added devlink knobs to change IPsec capabilities dynamically, there is a need to add a logic to block such IPsec capabilities for the cases when IPsec is already configured. Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230825062836.103744-7-saeed@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 20 +++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 32 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 9 ++++++ 3 files changed, 60 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 3b88a8bb7082..7d4ceb9b9c16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -38,6 +38,7 @@ #include #include "en.h" +#include "eswitch.h" #include "ipsec.h" #include "ipsec_rxtx.h" #include "en_rep.h" @@ -670,6 +671,11 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, if (err) goto err_xfrm; + if (!mlx5_eswitch_block_ipsec(priv->mdev)) { + err = -EBUSY; + goto err_xfrm; + } + /* check esn */ if (x->props.flags & XFRM_STATE_ESN) mlx5e_ipsec_update_esn_state(sa_entry); @@ -678,7 +684,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, err = mlx5_ipsec_create_work(sa_entry); if (err) - goto err_xfrm; + goto unblock_ipsec; err = mlx5e_ipsec_create_dwork(sa_entry); if (err) @@ -735,6 +741,8 @@ release_work: if (sa_entry->work) kfree(sa_entry->work->data); kfree(sa_entry->work); +unblock_ipsec: + mlx5_eswitch_unblock_ipsec(priv->mdev); err_xfrm: kfree(sa_entry); NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state"); @@ -764,6 +772,7 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) static void mlx5e_xfrm_free_state(struct xfrm_state *x) { struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) goto sa_entry_free; @@ -780,6 +789,7 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) if (sa_entry->work) kfree(sa_entry->work->data); kfree(sa_entry->work); + mlx5_eswitch_unblock_ipsec(ipsec->mdev); sa_entry_free: kfree(sa_entry); } @@ -1055,6 +1065,11 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, pol_entry->x = x; pol_entry->ipsec = priv->ipsec; + if (!mlx5_eswitch_block_ipsec(priv->mdev)) { + err = -EBUSY; + goto ipsec_busy; + } + mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs); err = mlx5e_accel_ipsec_fs_add_pol(pol_entry); if (err) @@ -1064,6 +1079,8 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, return 0; err_fs: + mlx5_eswitch_unblock_ipsec(priv->mdev); +ipsec_busy: kfree(pol_entry); NL_SET_ERR_MSG_MOD(extack, "Device failed to offload this policy"); return err; @@ -1074,6 +1091,7 @@ static void mlx5e_xfrm_del_policy(struct xfrm_policy *x) struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); mlx5e_accel_ipsec_fs_del_pol(pol_entry); + mlx5_eswitch_unblock_ipsec(pol_entry->ipsec->mdev); } static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index db1c2a076364..38a149dd479f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -48,6 +48,7 @@ #include "devlink.h" #include "ecpf.h" #include "en/mod_hdr.h" +#include "en_accel/ipsec.h" enum { MLX5_ACTION_NONE = 0, @@ -2336,3 +2337,34 @@ struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) return mlx5_esw_allowed(esw) ? esw->dev : NULL; } EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); + +bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) +{ + struct mlx5_eswitch *esw = dev->priv.eswitch; + + if (!mlx5_esw_allowed(esw)) + return true; + + mutex_lock(&esw->state_lock); + if (esw->enabled_ipsec_vf_count) { + mutex_unlock(&esw->state_lock); + return false; + } + + dev->num_ipsec_offloads++; + mutex_unlock(&esw->state_lock); + return true; +} + +void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) +{ + struct mlx5_eswitch *esw = dev->priv.eswitch; + + if (!mlx5_esw_allowed(esw)) + /* Failure means no eswitch => core dev is not a PF */ + return; + + mutex_lock(&esw->state_lock); + dev->num_ipsec_offloads--; + mutex_unlock(&esw->state_lock); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index ed3abcd70c46..0e51fd066fcc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -380,6 +380,7 @@ struct mlx5_eswitch { struct blocking_notifier_head n_head; struct xarray paired; struct mlx5_devcom_comp_dev *devcom; + u16 enabled_ipsec_vf_count; }; void esw_offloads_disable(struct mlx5_eswitch *esw); @@ -855,6 +856,8 @@ mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, struct mlx5_esw_flow_attr *esw_attr, int attr_idx); +bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev); +void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev); #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } @@ -916,6 +919,12 @@ static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; } static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {} +static inline bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) +{ + return false; +} + +static inline void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESWITCH_H__ */ -- cgit From 06bab69658a8afb493204448f29703e12e6d3960 Mon Sep 17 00:00:00 2001 From: Dima Chumak Date: Thu, 24 Aug 2023 23:28:35 -0700 Subject: net/mlx5: Implement devlink port function cmds to control ipsec_crypto Implement devlink port function commands to enable / disable IPsec crypto offloads. This is used to control the IPsec capability of the device. When ipsec_crypto is enabled for a VF, it prevents adding IPsec crypto offloads on the PF, because the two cannot be active simultaneously due to HW constraints. Conversely, if there are any active IPsec crypto offloads on the PF, it's not allowed to enable ipsec_crypto on a VF, until PF IPsec offloads are cleared. Signed-off-by: Dima Chumak Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230825062836.103744-8-saeed@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 4 + .../net/ethernet/mellanox/mlx5/core/esw/ipsec.c | 309 +++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 8 + drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 14 + .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 85 ++++++ 6 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index b56b187a9097..7e94caca4888 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -69,7 +69,7 @@ mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o # mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \ ecpf.o rdma.o esw/legacy.o \ - esw/devlink_port.o esw/vporttbl.o esw/qos.o + esw/devlink_port.o esw/vporttbl.o esw/qos.o esw/ipsec.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \ esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 3c254a710006..12205e913417 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -92,6 +92,10 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, +#ifdef CONFIG_XFRM_OFFLOAD + .port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get, + .port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set, +#endif /* CONFIG_XFRM_OFFLOAD */ }; static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c new file mode 100644 index 000000000000..187fb5f2d0cb --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +#include +#include +#include "mlx5_core.h" +#include "eswitch.h" + +static int esw_ipsec_vf_query_generic(struct mlx5_core_dev *dev, u16 vport_num, bool *result) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int err; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) { + *result = false; + return 0; + } + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_cap); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + *result = MLX5_GET(cmd_hca_cap, hca_cap, ipsec_offload); +free: + kvfree(query_cap); + return err; +} + +enum esw_vport_ipsec_offload { + MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD, +}; + +int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *vport) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + bool ipsec_enabled; + int err; + + /* Querying IPsec caps only makes sense when generic ipsec_offload + * HCA cap is enabled + */ + err = esw_ipsec_vf_query_generic(dev, vport->vport, &ipsec_enabled); + if (err) + return err; + + if (!ipsec_enabled) { + vport->info.ipsec_crypto_enabled = false; + return 0; + } + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_cap(dev, vport->vport, query_cap, MLX5_CAP_IPSEC); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + vport->info.ipsec_crypto_enabled = + MLX5_GET(ipsec_cap, hca_cap, ipsec_crypto_offload); +free: + kvfree(query_cap); + return err; +} + +static int esw_ipsec_vf_set_generic(struct mlx5_core_dev *dev, u16 vport_num, bool ipsec_ofld) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + void *hca_cap, *query_cap, *cap; + int ret; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_cap); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + MLX5_SET(cmd_hca_cap, cap, ipsec_offload, ipsec_ofld); + + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport_num); + + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1); + ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_set_bytype(struct mlx5_core_dev *dev, struct mlx5_vport *vport, + bool enable, enum esw_vport_ipsec_offload type) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + void *hca_cap, *query_cap, *cap; + int ret; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_cap(dev, vport->vport, query_cap, MLX5_CAP_IPSEC); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + + switch (type) { + case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: + MLX5_SET(ipsec_cap, cap, ipsec_crypto_offload, enable); + break; + default: + ret = -EOPNOTSUPP; + goto free; + } + + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport->vport); + + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_IPSEC << 1); + ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_crypto_aux_caps_set(struct mlx5_core_dev *dev, u16 vport_num, bool enable) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + struct mlx5_eswitch *esw = dev->priv.eswitch; + void *hca_cap, *query_cap, *cap; + int ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_ETHERNET_OFFLOADS); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + MLX5_SET(per_protocol_networking_offload_caps, cap, insert_trailer, enable); + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport_num); + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_ETHERNET_OFFLOADS << 1); + ret = mlx5_cmd_exec_in(esw->dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_offload_set_bytype(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable, enum esw_vport_ipsec_offload type) +{ + struct mlx5_core_dev *dev = esw->dev; + int err; + + if (vport->vport == MLX5_VPORT_PF) + return -EOPNOTSUPP; + + if (type == MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD) { + err = esw_ipsec_vf_crypto_aux_caps_set(dev, vport->vport, enable); + if (err) + return err; + } + + if (enable) { + err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + if (err) + return err; + err = esw_ipsec_vf_set_bytype(dev, vport, enable, type); + if (err) + return err; + } else { + err = esw_ipsec_vf_set_bytype(dev, vport, enable, type); + if (err) + return err; + err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + if (err) + return err; + } + + switch (type) { + case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: + vport->info.ipsec_crypto_enabled = enable; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int esw_ipsec_offload_supported(struct mlx5_core_dev *dev, u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_GENERAL); + if (ret) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(cmd_hca_cap, hca_cap, log_max_dek)) + ret = -EOPNOTSUPP; +free: + kvfree(query_cap); + return ret; +} + +bool mlx5_esw_ipsec_vf_offload_supported(struct mlx5_core_dev *dev) +{ + /* Old firmware doesn't support ipsec_offload capability for VFs. This + * can be detected by checking reformat_add_esp_trasport capability - + * when this cap isn't supported it means firmware cannot be trusted + * about what it reports for ipsec_offload cap. + */ + return MLX5_CAP_FLOWTABLE_NIC_TX(dev, reformat_add_esp_trasport); +} + +int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int err; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) + return -EOPNOTSUPP; + + err = esw_ipsec_offload_supported(dev, vport_num); + if (err) + return err; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_ETHERNET_OFFLOADS); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(per_protocol_networking_offload_caps, hca_cap, swp)) + goto free; + +free: + kvfree(query_cap); + return err; +} + +int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable) +{ + return esw_ipsec_vf_offload_set_bytype(esw, vport, enable, + MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 38a149dd479f..79ae6ad94f55 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -832,6 +832,9 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport * hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable); + + err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport); + out_free: kfree(query_ctx); return err; @@ -914,6 +917,8 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, /* Sync with current vport context */ vport->enabled_events = enabled_events; vport->enabled = true; + if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled) + esw->enabled_ipsec_vf_count++; /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well * in smartNIC as it's a vport group manager. @@ -970,6 +975,9 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) mlx5_esw_vport_vhca_id_clear(esw, vport_num); + if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled) + esw->enabled_ipsec_vf_count--; + /* We don't assume VFs will cleanup after themselves. * Calling vport change handler while vport is disabled will cleanup * the vport resources. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 0e51fd066fcc..cde5712aa697 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -163,6 +163,7 @@ struct mlx5_vport_info { u8 trusted: 1; u8 roce_enabled: 1; u8 mig_enabled: 1; + u8 ipsec_crypto_enabled: 1; }; /* Vport context events */ @@ -559,6 +560,12 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack); +#ifdef CONFIG_XFRM_OFFLOAD +int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack); +#endif /* CONFIG_XFRM_OFFLOAD */ void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type); int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, @@ -858,6 +865,13 @@ int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_h struct mlx5_esw_flow_attr *esw_attr, int attr_idx); bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev); void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev); +bool mlx5_esw_ipsec_vf_offload_supported(struct mlx5_core_dev *dev); +int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, + struct mlx5_vport *vport); +int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num); +int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable); #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index d4697dadd27d..f37d30a096c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4367,3 +4367,88 @@ mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handl return mlx5_modify_rule_destination(rule, &new_dest, &old_dest); } + +#ifdef CONFIG_XFRM_OFFLOAD +int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + int err = 0; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + if (!mlx5_esw_ipsec_vf_offload_supported(esw->dev)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support IPSec crypto"); + return -EOPNOTSUPP; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + goto unlock; + } + + *is_enabled = vport->info.ipsec_crypto_enabled; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + u16 vport_num; + int err; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); + err = mlx5_esw_ipsec_vf_crypto_offload_supported(esw->dev, vport_num); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Device doesn't support IPsec crypto"); + return err; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); + goto unlock; + } + + if (vport->info.ipsec_crypto_enabled == enable) + goto unlock; + + if (!esw->enabled_ipsec_vf_count && esw->dev->num_ipsec_offloads) { + err = -EBUSY; + goto unlock; + } + + err = mlx5_esw_ipsec_vf_crypto_offload_set(esw, vport, enable); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to set IPsec crypto"); + goto unlock; + } + + vport->info.ipsec_crypto_enabled = enable; + if (enable) + esw->enabled_ipsec_vf_count++; + else + esw->enabled_ipsec_vf_count--; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} +#endif /* CONFIG_XFRM_OFFLOAD */ -- cgit From b691b1116e820450de8a5d50eb4ce546a7de93dc Mon Sep 17 00:00:00 2001 From: Dima Chumak Date: Thu, 24 Aug 2023 23:28:36 -0700 Subject: net/mlx5: Implement devlink port function cmds to control ipsec_packet Implement devlink port function commands to enable / disable IPsec packet offloads. This is used to control the IPsec capability of the device. When ipsec_offload is enabled for a VF, it prevents adding IPsec packet offloads on the PF, because the two cannot be active simultaneously due to HW constraints. Conversely, if there are any active IPsec packet offloads on the PF, it's not allowed to enable ipsec_packet on a VF, until PF IPsec offloads are cleared. Signed-off-by: Dima Chumak Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed Link: https://lore.kernel.org/r/20230825062836.103744-9-saeed@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/esw/devlink_port.c | 2 + .../net/ethernet/mellanox/mlx5/core/esw/ipsec.c | 62 +++++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 7 +- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 12 ++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 84 ++++++++++++++++++++++ 5 files changed, 163 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 12205e913417..d8e739cbcbce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -95,6 +95,8 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { #ifdef CONFIG_XFRM_OFFLOAD .port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get, .port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set, + .port_fn_ipsec_packet_get = mlx5_devlink_port_fn_ipsec_packet_get, + .port_fn_ipsec_packet_set = mlx5_devlink_port_fn_ipsec_packet_set, #endif /* CONFIG_XFRM_OFFLOAD */ }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c index 187fb5f2d0cb..da10e04777cf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c @@ -37,6 +37,7 @@ free: enum esw_vport_ipsec_offload { MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD, + MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD, }; int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *vport) @@ -55,6 +56,7 @@ int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport * if (!ipsec_enabled) { vport->info.ipsec_crypto_enabled = false; + vport->info.ipsec_packet_enabled = false; return 0; } @@ -69,6 +71,8 @@ int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport * hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); vport->info.ipsec_crypto_enabled = MLX5_GET(ipsec_cap, hca_cap, ipsec_crypto_offload); + vport->info.ipsec_packet_enabled = + MLX5_GET(ipsec_cap, hca_cap, ipsec_full_offload); free: kvfree(query_cap); return err; @@ -143,6 +147,9 @@ static int esw_ipsec_vf_set_bytype(struct mlx5_core_dev *dev, struct mlx5_vport case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: MLX5_SET(ipsec_cap, cap, ipsec_crypto_offload, enable); break; + case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD: + MLX5_SET(ipsec_cap, cap, ipsec_full_offload, enable); + break; default: ret = -EOPNOTSUPP; goto free; @@ -222,15 +229,28 @@ static int esw_ipsec_vf_offload_set_bytype(struct mlx5_eswitch *esw, struct mlx5 err = esw_ipsec_vf_set_bytype(dev, vport, enable, type); if (err) return err; - err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + err = mlx5_esw_ipsec_vf_offload_get(dev, vport); if (err) return err; + + /* The generic ipsec_offload cap can be disabled only if both + * ipsec_crypto_offload and ipsec_full_offload aren't enabled. + */ + if (!vport->info.ipsec_crypto_enabled && + !vport->info.ipsec_packet_enabled) { + err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + if (err) + return err; + } } switch (type) { case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: vport->info.ipsec_crypto_enabled = enable; break; + case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD: + vport->info.ipsec_packet_enabled = enable; + break; default: return -EINVAL; } @@ -301,9 +321,49 @@ free: return err; } +int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int ret; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) + return -EOPNOTSUPP; + + ret = esw_ipsec_offload_supported(dev, vport_num); + if (ret) + return ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_FLOW_TABLE); + if (ret) + goto out; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(flow_table_nic_cap, hca_cap, flow_table_properties_nic_receive.decap)) { + ret = -EOPNOTSUPP; + goto out; + } + +out: + kvfree(query_cap); + return ret; +} + int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, bool enable) { return esw_ipsec_vf_offload_set_bytype(esw, vport, enable, MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD); } + +int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable) +{ + return esw_ipsec_vf_offload_set_bytype(esw, vport, enable, + MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 79ae6ad94f55..6cd7d6497e10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -834,7 +834,6 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport * vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable); err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport); - out_free: kfree(query_ctx); return err; @@ -917,7 +916,8 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, /* Sync with current vport context */ vport->enabled_events = enabled_events; vport->enabled = true; - if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled) + if (vport->vport != MLX5_VPORT_PF && + (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) esw->enabled_ipsec_vf_count++; /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well @@ -975,7 +975,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) mlx5_esw_vport_vhca_id_clear(esw, vport_num); - if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled) + if (vport->vport != MLX5_VPORT_PF && + (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) esw->enabled_ipsec_vf_count--; /* We don't assume VFs will cleanup after themselves. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index cde5712aa697..37ab66e7b403 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -164,6 +164,7 @@ struct mlx5_vport_info { u8 roce_enabled: 1; u8 mig_enabled: 1; u8 ipsec_crypto_enabled: 1; + u8 ipsec_packet_enabled: 1; }; /* Vport context events */ @@ -565,6 +566,10 @@ int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_en struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack); #endif /* CONFIG_XFRM_OFFLOAD */ void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type); @@ -872,6 +877,13 @@ int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev, u16 vport_num); int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, bool enable); +int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable); +int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num); +void mlx5_esw_vport_ipsec_offload_enable(struct mlx5_eswitch *esw); +void mlx5_esw_vport_ipsec_offload_disable(struct mlx5_eswitch *esw); + #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index f37d30a096c0..752fb0dfb111 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4451,4 +4451,88 @@ unlock: mutex_unlock(&esw->state_lock); return err; } + +int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + int err = 0; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + if (!mlx5_esw_ipsec_vf_offload_supported(esw->dev)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support IPsec packet"); + return -EOPNOTSUPP; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + goto unlock; + } + + *is_enabled = vport->info.ipsec_packet_enabled; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port, + bool enable, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + u16 vport_num; + int err; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); + err = mlx5_esw_ipsec_vf_packet_offload_supported(esw->dev, vport_num); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Device doesn't support IPsec packet mode"); + return err; + } + + vport = mlx5_devlink_port_vport_get(port); + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); + goto unlock; + } + + if (vport->info.ipsec_packet_enabled == enable) + goto unlock; + + if (!esw->enabled_ipsec_vf_count && esw->dev->num_ipsec_offloads) { + err = -EBUSY; + goto unlock; + } + + err = mlx5_esw_ipsec_vf_packet_offload_set(esw, vport, enable); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Failed to set IPsec packet mode"); + goto unlock; + } + + vport->info.ipsec_packet_enabled = enable; + if (enable) + esw->enabled_ipsec_vf_count++; + else + esw->enabled_ipsec_vf_count--; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} #endif /* CONFIG_XFRM_OFFLOAD */ -- cgit From bb5ed01cd2428cd25b1c88a3a9cba87055eb289f Mon Sep 17 00:00:00 2001 From: Radoslaw Tyl Date: Thu, 24 Aug 2023 13:46:19 -0700 Subject: igb: set max size RX buffer when store bad packet is enabled Increase the RX buffer size to 3K when the SBP bit is on. The size of the RX buffer determines the number of pages allocated which may not be sufficient for receive frames larger than the set MTU size. Cc: stable@vger.kernel.org Fixes: 89eaefb61dc9 ("igb: Support RX-ALL feature flag.") Reported-by: Manfred Rudigier Signed-off-by: Radoslaw Tyl Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igb/igb_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9a2561409b06..08e3df37089f 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4814,6 +4814,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, static void igb_set_rx_buffer_len(struct igb_adapter *adapter, struct igb_ring *rx_ring) { +#if (PAGE_SIZE < 8192) + struct e1000_hw *hw = &adapter->hw; +#endif + /* set build_skb and buffer size flags */ clear_ring_build_skb_enabled(rx_ring); clear_ring_uses_large_buffer(rx_ring); @@ -4824,10 +4828,9 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter, set_ring_build_skb_enabled(rx_ring); #if (PAGE_SIZE < 8192) - if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) - return; - - set_ring_uses_large_buffer(rx_ring); + if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || + rd32(E1000_RCTL) & E1000_RCTL_SBP) + set_ring_uses_large_buffer(rx_ring); #endif } -- cgit From 5266733c798652925aaf556aacc3f3389abc9d32 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Fri, 25 Aug 2023 16:10:19 +0530 Subject: octeontx2-af: CN10KB: Add USGMII LMAC mode Upon physical link change, firmware reports to the kernel about the change along with the details like speed, lmac_type_id, etc. Kernel derives lmac_type based on lmac_type_id received from firmware. This patch extends current lmac list with new USGMII mode supported by CN10KB RPM block. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Kovvuri Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 1 + drivers/net/ethernet/marvell/octeontx2/af/cgx.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 988383e20bb8..9392ef95a245 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -55,6 +55,7 @@ static const char *cgx_lmactype_string[LMAC_MODE_MAX] = { [LMAC_MODE_50G_R] = "50G_R", [LMAC_MODE_100G_R] = "100G_R", [LMAC_MODE_USXGMII] = "USXGMII", + [LMAC_MODE_USGMII] = "USGMII", }; /* CGX PHY management internal APIs */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h index 574114179688..6f7d1dee5830 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h @@ -110,6 +110,7 @@ enum LMAC_TYPE { LMAC_MODE_50G_R = 8, LMAC_MODE_100G_R = 9, LMAC_MODE_USXGMII = 10, + LMAC_MODE_USGMII = 11, LMAC_MODE_MAX, }; -- cgit From f027fd51edebb326c1edb5d283ceaa7b8f7508df Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Fri, 25 Aug 2023 16:10:20 +0530 Subject: octeontx2-af: Don't treat lack of CGX interfaces as error Don't treat lack of CGX LMACs on the system as a error. Instead ignore it so that LBK VFs are created and can be used. Signed-off-by: Sunil Goutham Signed-off-by: Hariprasad Kelam Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index b3f766b970ca..4e3aec7bdbee 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -345,7 +345,7 @@ int rvu_cgx_init(struct rvu *rvu) rvu->cgx_cnt_max = cgx_get_cgxcnt_max(); if (!rvu->cgx_cnt_max) { dev_info(rvu->dev, "No CGX devices found!\n"); - return -ENODEV; + return 0; } rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max * -- cgit From 2f387525d484c0eca841b71842e1cd672220c20c Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Fri, 25 Aug 2023 16:10:21 +0530 Subject: octeontx2-af: Add validation of lmac With the addition of new MAC blocks like CN10K RPM and CN10KB RPM_USX, LMACs are noncontiguous. Though in most of the functions, lmac validation checks exist but in few functions they are missing. This patch adds the same. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Kovvuri Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 9392ef95a245..e06f77ad6106 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -232,6 +232,9 @@ int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr) int index, id; u64 cfg; + if (!lmac) + return -ENODEV; + /* access mac_ops to know csr_offset */ mac_ops = cgx_dev->mac_ops; @@ -550,15 +553,16 @@ void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable) { struct cgx *cgx = cgx_get_pdata(cgx_id); struct lmac *lmac = lmac_pdata(lmac_id, cgx); - u16 max_dmac = lmac->mac_to_index_bmap.max; struct mac_ops *mac_ops; + u16 max_dmac; int index, i; u64 cfg = 0; int id; - if (!cgx) + if (!cgx || !lmac) return; + max_dmac = lmac->mac_to_index_bmap.max; id = get_sequence_id_of_lmac(cgx, lmac_id); mac_ops = cgx->mac_ops; @@ -731,7 +735,7 @@ int cgx_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp) int corr_reg, uncorr_reg; struct cgx *cgx = cgxd; - if (!cgx || lmac_id >= cgx->lmac_count) + if (!is_lmac_valid(cgx, lmac_id)) return -ENODEV; if (cgx->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE) -- cgit From 17d1368f4f19eec2047c7527e7e606496481f1bf Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Fri, 25 Aug 2023 16:10:22 +0530 Subject: octeontx2-af: print error message incase of invalid pf mapping During AF driver initialization, it creates a mapping between pf to cgx,lmac pair. Whenever there is a physical link change, using this mapping driver forwards the message to the associated netdev. This patch prints error message incase of cgx,lmac pair is not associated with any pf netdev. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Kovvuri Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 4e3aec7bdbee..f2b1edf1bb43 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -236,6 +236,11 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu) linfo = &event->link_uinfo; pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id); + if (!pfmap) { + dev_err(rvu->dev, "CGX port%d:%d not mapped with PF\n", + event->cgx_id, event->lmac_id); + return; + } do { pfid = find_first_bit(&pfmap, -- cgit From ec1b90886f3cd7e90d4c0381dffb418e2d3a1473 Mon Sep 17 00:00:00 2001 From: Mikhail Kobuk Date: Fri, 25 Aug 2023 22:04:41 +0300 Subject: ethernet: tg3: remove unreachable code 'tp->irq_max' value is either 1 [L16336] or 5 [L16354], as indicated in tg3_get_invariants(). Therefore, 'i' can't exceed 4 in tg3_init_one() that makes (i <= 4) always true. Moreover, 'intmbx' value set at the last iteration is not used later in it's scope. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 78f90dcf184b ("tg3: Move napi_add calls below tg3_get_invariants") Signed-off-by: Mikhail Kobuk Reviewed-by: Alexey Khoroshilov Reviewed-by: Simon Horman Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index cb2810f175cc..5408ed051772 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17795,10 +17795,7 @@ static int tg3_init_one(struct pci_dev *pdev, tnapi->tx_pending = TG3_DEF_TX_RING_PENDING; tnapi->int_mbox = intmbx; - if (i <= 4) - intmbx += 0x8; - else - intmbx += 0x4; + intmbx += 0x8; tnapi->consmbox = rcvmbx; tnapi->prodmbox = sndmbx; -- cgit From 90ca51e8c654699b672ba61aeaa418dfb3252e5e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 25 Aug 2023 21:44:01 +0200 Subject: r8169: fix ASPM-related issues on a number of systems with NIC version from RTL8168h This effectively reverts 4b5f82f6aaef. On a number of systems ASPM L1 causes tx timeouts with RTL8168h, see referenced bug report. Fixes: 4b5f82f6aaef ("r8169: enable ASPM L1/L1.1 from RTL8168h") Cc: stable@vger.kernel.org Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217814 Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 5eb50b265c0b..6351a2dc13bc 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5239,13 +5239,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disable ASPM L1 as that cause random device stop working * problems as well as full system hangs for some PCIe devices users. - * Chips from RTL8168h partially have issues with L1.2, but seem - * to work fine with L1 and L1.1. */ if (rtl_aspm_is_safe(tp)) rc = 0; - else if (tp->mac_version >= RTL_GIGA_MAC_VER_46) - rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); else rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); tp->aspm_manageable = !rc; -- cgit From 72f93a3136ee18fd59fa6579f84c07e93424681e Mon Sep 17 00:00:00 2001 From: Antonio Napolitano Date: Sat, 26 Aug 2023 01:05:50 +0200 Subject: r8152: add vendor/device ID pair for D-Link DUB-E250 The D-Link DUB-E250 is an RTL8156 based 2.5G Ethernet controller. Add the vendor and product ID values to the driver. This makes Ethernet work with the adapter. Signed-off-by: Antonio Napolitano Link: https://lore.kernel.org/r/CV200KJEEUPC.WPKAHXCQJ05I@mercurius Signed-off-by: Jakub Kicinski --- drivers/net/usb/r8152.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index bb234cf0cea0..332c853ca99b 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -9832,6 +9832,7 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, {} }; -- cgit From a014c35556b9045ece8426df2b38eb3c5e1c1aa0 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Sat, 26 Aug 2023 11:02:51 +0100 Subject: net: stmmac: clarify difference between "interface" and "phy_interface" Clarify the difference between "interface" and "phy_interface" in struct plat_stmmacenet_data, both by adding a comment, and also renaming "interface" to be "mac_interface". The difference between these are: MAC ----- optional PCS ----- SerDes ----- optional PHY ----- Media ^ ^ mac_interface phy_interface Note that phylink currently only deals with phy_interface. Signed-off-by: Russell King (Oracle) Link: https://lore.kernel.org/r/E1qZq83-005tts-6K@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 14 +++++++------- drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c | 20 ++++++++++---------- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 8 ++++---- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 6 +++--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++-- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 +++--- 11 files changed, 38 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 535856fffaea..df34e34cc14f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -70,7 +70,7 @@ static int imx8mp_set_intf_mode(struct plat_stmmacenet_data *plat_dat) struct imx_priv_data *dwmac = plat_dat->bsp_priv; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = GPR_ENET_QOS_INTF_SEL_MII; break; @@ -87,7 +87,7 @@ static int imx8mp_set_intf_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("imx dwmac doesn't support %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } @@ -110,7 +110,7 @@ static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) struct imx_priv_data *dwmac = plat_dat->bsp_priv; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = MX93_GPR_ENET_QOS_INTF_SEL_MII; break; @@ -125,7 +125,7 @@ static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) break; default: dev_dbg(dwmac->dev, "imx dwmac doesn't support %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } @@ -192,8 +192,8 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod plat_dat = dwmac->plat_dat; if (dwmac->ops->mac_rgmii_txclk_auto_adj || - (plat_dat->interface == PHY_INTERFACE_MODE_RMII) || - (plat_dat->interface == PHY_INTERFACE_MODE_MII)) + (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) || + (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII)) return; switch (speed) { @@ -260,7 +260,7 @@ static int imx_dwmac_mx93_reset(void *priv, void __iomem *ioaddr) value |= DMA_BUS_MODE_SFT_RESET; writel(value, ioaddr + DMA_BUS_MODE); - if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { + if (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) { usleep_range(100, 200); writel(RMII_RESET_SPEED, ioaddr + MAC_CTRL_REG); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c index e22ef0d6bc73..0a20c3d24722 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c @@ -89,7 +89,7 @@ static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII); @@ -118,7 +118,7 @@ static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -130,13 +130,13 @@ static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) { struct ingenic_mac *mac = plat_dat->bsp_priv; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -149,14 +149,14 @@ static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -169,7 +169,7 @@ static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) | FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); @@ -177,7 +177,7 @@ static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -190,7 +190,7 @@ static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) | FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) | @@ -220,7 +220,7 @@ static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index a25c187d3185..2cd6fce5c993 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -117,7 +117,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id } plat->phy_interface = phy_mode; - plat->interface = PHY_INTERFACE_MODE_GMII; + plat->mac_interface = PHY_INTERFACE_MODE_GMII; pci_set_master(pdev); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c index 18e84ba693a6..d0aa674ce705 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c @@ -50,9 +50,9 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } - if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { + if (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII; - } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { + } else if (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; } else { dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 7580077383c0..cd796ec04132 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -587,7 +587,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev, { int i; - plat->interface = priv_plat->phy_mode; + plat->mac_interface = priv_plat->phy_mode; if (priv_plat->mac_wol) plat->flags |= STMMAC_FLAG_USE_PHY_WOL; else diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 7db176e8691f..9bf102bbc6a0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -236,7 +236,7 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) struct net_device *ndev = dev_get_drvdata(dwmac->dev); struct stmmac_priv *priv = netdev_priv(ndev); - return priv->plat->interface; + return priv->plat->mac_interface; } static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c index 892612564694..9289bb87c3e3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c @@ -60,7 +60,7 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat) unsigned int mode; int err; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: mode = STARFIVE_DWMAC_PHY_INFT_RMII; break; @@ -72,7 +72,7 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat) default: dev_err(dwmac->dev, "unsupported interface %d\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index 3a09085819dc..26ea8c687881 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -171,7 +171,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) clk_rate = clk_get_rate(dwmac->clk_eth_ck); dwmac->enable_eth_ck = false; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk) dwmac->enable_eth_ck = true; @@ -210,7 +210,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); /* Do not manage others interfaces */ return -EINVAL; } @@ -230,7 +230,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) u32 reg = dwmac->mode_reg; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = SYSCFG_MCU_ETH_SEL_MII; pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); @@ -241,7 +241,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); /* Do not manage others interfaces */ return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index c23420863a8d..01e77368eef1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1016,7 +1016,7 @@ static int sun8i_dwmac_set_syscon(struct device *dev, if (gmac->variant->support_rmii) reg &= ~SYSCON_RMII_EN; - switch (plat->interface) { + switch (plat->mac_interface) { case PHY_INTERFACE_MODE_MII: /* default */ break; @@ -1031,7 +1031,7 @@ static int sun8i_dwmac_set_syscon(struct device *dev, break; default: dev_err(dev, "Unsupported interface mode: %s", - phy_modes(plat->interface)); + phy_modes(plat->mac_interface)); return -EINVAL; } @@ -1231,7 +1231,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) /* platform data specifying hardware features and callbacks. * hardware features were copied from Allwinner drivers. */ - plat_dat->interface = interface; + plat_dat->mac_interface = interface; plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; plat_dat->tx_coe = 1; plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 33ca5c50bdcd..9a3182b9e767 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1119,7 +1119,7 @@ static const struct phylink_mac_ops stmmac_phylink_mac_ops = { */ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) { - int interface = priv->plat->interface; + int interface = priv->plat->mac_interface; if (priv->dma_cap.pcs) { if ((interface == PHY_INTERFACE_MODE_RGMII) || @@ -1214,7 +1214,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband; - /* Set the platform/firmware specified interface mode */ + /* Set the platform/firmware specified interface mode. Note, phylink + * deals with the PHY interface mode, not the MAC interface mode. + */ __set_bit(mode, priv->phylink_config.supported_interfaces); /* If we have an xpcs, it defines which PHY interfaces are supported. */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index ff330423ee66..35f4b1484029 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -419,9 +419,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) return ERR_PTR(phy_mode); plat->phy_interface = phy_mode; - plat->interface = stmmac_of_get_mac_mode(np); - if (plat->interface < 0) - plat->interface = plat->phy_interface; + plat->mac_interface = stmmac_of_get_mac_mode(np); + if (plat->mac_interface < 0) + plat->mac_interface = plat->phy_interface; /* Some wrapper drivers still rely on phy_node. Let's save it while * they are not converted to phylink. */ -- cgit From 042bf24ac98702e0b240034f6a8b219104095b06 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 27 Aug 2023 19:31:41 +0200 Subject: net: ethernet: mtk_wed: add some more info in wed_txinfo_show handler Add some new info in Wireless Ethernet Dispatcher wed_txinfo_show debugfs handler useful during debugging. Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/3390292655d568180b73d2a25576f61aa63310e5.1693157377.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_wed_debugfs.c | 11 ++++++++++- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c index b244c02c5b51..5446d3be1c3a 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c @@ -127,8 +127,17 @@ wed_txinfo_show(struct seq_file *s, void *data) DUMP_WDMA_RING(WDMA_RING_RX(0)), DUMP_WDMA_RING(WDMA_RING_RX(1)), - DUMP_STR("TX FREE"), + DUMP_STR("WED TX FREE"), DUMP_WED(WED_RX_MIB(0)), + DUMP_WED_RING(WED_RING_RX(0)), + DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), + DUMP_WED(WED_RX_MIB(1)), + DUMP_WED_RING(WED_RING_RX(1)), + DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), + + DUMP_STR("WED WPDMA TX FREE"), + DUMP_WED_RING(WED_WPDMA_RING_RX(0)), + DUMP_WED_RING(WED_WPDMA_RING_RX(1)), }; struct mtk_wed_hw *hw = s->private; struct mtk_wed_device *dev = hw->wed_dev; diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h index 0a50bb98c5ea..47ea69feb3b2 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h @@ -266,6 +266,8 @@ struct mtk_wdma_desc { #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) +#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) +#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) -- cgit From 6c9cfb853063f317b2953c5e852b6bac1eb0cade Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 27 Aug 2023 19:33:47 +0200 Subject: net: ethernet: mtk_wed: minor change in wed_{tx,rx}info_show No functional changes, just cosmetic ones. Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/71e046c72a978745f0435af265dda610aa9bfbcf.1693157578.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_wed_debugfs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c index 5446d3be1c3a..e24afeaea0da 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c @@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev, } } - static int wed_txinfo_show(struct seq_file *s, void *data) { @@ -142,10 +141,8 @@ wed_txinfo_show(struct seq_file *s, void *data) struct mtk_wed_hw *hw = s->private; struct mtk_wed_device *dev = hw->wed_dev; - if (!dev) - return 0; - - dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + if (dev) + dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); return 0; } @@ -217,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void *data) struct mtk_wed_hw *hw = s->private; struct mtk_wed_device *dev = hw->wed_dev; - if (!dev) - return 0; - - dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + if (dev) + dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); return 0; } -- cgit