Thread (36 messages) 36 messages, 4 authors, 2024-08-05
STALE710d
Revisions (15)
  1. rfc current
  2. v2 [diff vs current]
  3. v1 [diff vs current]
  4. v2 [diff vs current]
  5. v3 [diff vs current]
  6. v4 [diff vs current]
  7. v5 [diff vs current]
  8. v6 [diff vs current]
  9. v7 [diff vs current]
  10. v8 [diff vs current]
  11. v9 [diff vs current]
  12. v10 [diff vs current]
  13. v11 [diff vs current]
  14. v12 [diff vs current]
  15. v12 [diff vs current]

[RFC PATCH net-next 08/10] net: hibmcge: Implement workqueue and some ethtool_ops functions

From: Jijie Shao <shaojijie@huawei.com>
Date: 2024-07-31 09:48:26
Also in: lkml
Subsystem: hisilicon network hibmcge driver, hisilicon network subsystem driver, networking drivers, the rest · Maintainers: Jijie Shao, Jian Shen, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Implement a workqueue in this module, The workqueue is invoked
once every second to update link status.

Implement the .get_drvinfo .get_link .get_link_ksettings to get
the basic information and working status of the driver.
Implement the .set_link_ksettings to modify the rate, duplex,
and auto-negotiation status.

Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
 .../ethernet/hisilicon/hibmcge/hbg_common.h   |  1 +
 .../ethernet/hisilicon/hibmcge/hbg_ethtool.c  | 56 +++++++++++
 .../ethernet/hisilicon/hibmcge/hbg_ethtool.h  | 11 +++
 .../net/ethernet/hisilicon/hibmcge/hbg_main.c | 96 ++++++++++++++++++-
 4 files changed, 161 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
 create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
index 25563af04897..45ec4b463e70 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
@@ -146,6 +146,7 @@ struct hbg_priv {
 	struct hbg_vector vectors;
 	struct hbg_ring tx_ring;
 	struct hbg_ring rx_ring;
+	struct delayed_work service_task;
 };
 
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
new file mode 100644
index 000000000000..3acd6eae189e
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include "hbg_common.h"
+#include "hbg_ethtool.h"
+#include "hbg_hw.h"
+#include "hbg_main.h"
+#include "hbg_mdio.h"
+
+static void hbg_ethtool_get_drvinfo(struct net_device *netdev,
+				    struct ethtool_drvinfo *drvinfo)
+{
+	strscpy(drvinfo->version, HBG_MOD_VERSION, sizeof(drvinfo->version));
+	drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
+}
+
+static u32 hbg_ethtool_get_link(struct net_device *netdev)
+{
+	struct hbg_priv *priv = netdev_priv(netdev);
+
+	return priv->mac.link_status;
+}
+
+static int hbg_ethtool_get_ksettings(struct net_device *netdev,
+				     struct ethtool_link_ksettings *ksettings)
+{
+	struct hbg_priv *priv = netdev_priv(netdev);
+
+	phy_ethtool_ksettings_get(priv->mac.phydev, ksettings);
+	return 0;
+}
+
+static int hbg_ethtool_set_ksettings(struct net_device *netdev,
+				     const struct ethtool_link_ksettings *cmd)
+{
+	struct hbg_priv *priv = netdev_priv(netdev);
+
+	if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
+		return -EINVAL;
+
+	return phy_ethtool_ksettings_set(priv->mac.phydev, cmd);
+}
+
+static const struct ethtool_ops hbg_ethtool_ops = {
+	.get_drvinfo		= hbg_ethtool_get_drvinfo,
+	.get_link		= hbg_ethtool_get_link,
+	.get_link_ksettings	= hbg_ethtool_get_ksettings,
+	.set_link_ksettings	= hbg_ethtool_set_ksettings,
+};
+
+void hbg_ethtool_set_ops(struct net_device *netdev)
+{
+	netdev->ethtool_ops = &hbg_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h
new file mode 100644
index 000000000000..628707ec2686
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_ETHTOOL_H
+#define __HBG_ETHTOOL_H
+
+#include <linux/netdevice.h>
+
+void hbg_ethtool_set_ops(struct net_device *netdev);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index bb5f8321da8a..bea596123c37 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -6,12 +6,15 @@
 #include <linux/netdevice.h>
 #include <linux/pci.h>
 #include "hbg_common.h"
+#include "hbg_ethtool.h"
 #include "hbg_hw.h"
 #include "hbg_irq.h"
 #include "hbg_main.h"
 #include "hbg_mdio.h"
 #include "hbg_txrx.h"
 
+static struct workqueue_struct *hbg_workqueue;
+
 static void hbg_enable_intr(struct hbg_priv *priv, bool enabled)
 {
 	u32 i;
@@ -136,6 +139,52 @@ static const struct net_device_ops hbg_netdev_ops = {
 	.ndo_tx_timeout		= hbg_net_tx_timeout,
 };
 
+static void hbg_update_link_status(struct hbg_priv *priv)
+{
+	u32 link;
+
+	link = hbg_get_link_status(priv);
+	if (link == priv->mac.link_status)
+		return;
+
+	priv->mac.link_status = link;
+	if (link == HBG_LINK_DOWN) {
+		netif_carrier_off(priv->netdev);
+		netif_tx_stop_all_queues(priv->netdev);
+		dev_info(&priv->pdev->dev, "link down!");
+	} else {
+		netif_tx_wake_all_queues(priv->netdev);
+		netif_carrier_on(priv->netdev);
+		dev_info(&priv->pdev->dev, "link up!");
+	}
+}
+
+static void hbg_service_task(struct work_struct *work)
+{
+	struct hbg_priv *priv =
+		container_of(work, struct hbg_priv, service_task.work);
+
+	hbg_update_link_status(priv);
+
+	mod_delayed_work(hbg_workqueue, &priv->service_task,
+			 round_jiffies_relative(HZ));
+}
+
+static void hbg_delaywork_init(struct hbg_priv *priv)
+{
+	INIT_DELAYED_WORK(&priv->service_task, hbg_service_task);
+	mod_delayed_work(hbg_workqueue, &priv->service_task,
+			 round_jiffies_relative(HZ));
+}
+
+static void hbg_delaywork_uninit(void *data)
+{
+	struct hbg_priv *priv = data;
+
+	if (priv->service_task.work.func)
+		cancel_delayed_work_sync(&priv->service_task);
+}
+
 static const u32 hbg_mode_ability[] = {
 	ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
 	ETHTOOL_LINK_MODE_100baseT_Full_BIT,
@@ -177,12 +226,17 @@ static int hbg_init(struct net_device *netdev)
 	ret = hbg_irq_init(priv);
 	if (ret)
 		return ret;
-
 	ret = devm_add_action_or_reset(&priv->pdev->dev, hbg_irq_uninit, priv);
 	if (ret)
 		return ret;
 
-	return hbg_mac_init(priv);
+	ret = hbg_mac_init(priv);
+	if (ret)
+		return ret;
+
+	hbg_delaywork_init(priv);
+	return devm_add_action_or_reset(&priv->pdev->dev,
+					hbg_delaywork_uninit, priv);
 }
 
 static int hbg_pci_init(struct pci_dev *pdev)
@@ -249,6 +303,7 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		return dev_err_probe(&pdev->dev, ret,
 				     "failed to register netdev\n");
 
+	hbg_ethtool_set_ops(netdev);
 	set_bit(HBG_NIC_STATE_INITED, &priv->state);
 	return 0;
 }
@@ -264,7 +319,42 @@ static struct pci_driver hbg_driver = {
 	.id_table	= hbg_pci_tbl,
 	.probe		= hbg_probe,
 };
-module_pci_driver(hbg_driver);
+
+static int __init hbg_module_init(void)
+{
+	int ret;
+
+	hbg_workqueue = alloc_workqueue("%s", WQ_UNBOUND, 0, HBG_DEV_NAME);
+	if (!hbg_workqueue) {
+		pr_err("%s: failed to create workqueue\n", HBG_DEV_NAME);
+		return -ENOMEM;
+	}
+
+	ret = pci_register_driver(&hbg_driver);
+	if (ret) {
+		pr_err("%s: failed to register PCI driver, ret = %d\n",
+		       HBG_DEV_NAME, ret);
+		goto err_destroy_workqueue;
+	}
+
+	return 0;
+
+err_destroy_workqueue:
+	destroy_workqueue(hbg_workqueue);
+	hbg_workqueue = NULL;
+
+	return ret;
+}
+module_init(hbg_module_init);
+
+static void __exit hbg_module_exit(void)
+{
+	pci_unregister_driver(&hbg_driver);
+	flush_workqueue(hbg_workqueue);
+	destroy_workqueue(hbg_workqueue);
+	hbg_workqueue = NULL;
+}
+module_exit(hbg_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
-- 
2.33.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help