From: Jijie Shao <shaojijie@huawei.com>
To: <davem@davemloft.net>, <edumazet@google.com>, <kuba@kernel.org>,
<pabeni@redhat.com>
Cc: <shenjian15@huawei.com>, <wangpeiyang1@huawei.com>,
<liuyonglong@huawei.com>, <chenhao418@huawei.com>,
<sudongming1@huawei.com>, <xujunsheng@huawei.com>,
<shiyongbang@huawei.com>, <libaihan@huawei.com>, <andrew@lunn.ch>,
<jdamato@fastly.com>, <horms@kernel.org>,
<kalesh-anakkur.purayil@broadcom.com>,
<christophe.jaillet@wanadoo.fr>, <jonathan.cameron@huawei.com>,
<shameerali.kolothum.thodi@huawei.com>, <salil.mehta@huawei.com>,
<netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<shaojijie@huawei.com>
Subject: [PATCH V11 net-next 04/10] net: hibmcge: Add interrupt supported in this module
Date: Tue, 8 Oct 2024 10:23:52 +0800 [thread overview]
Message-ID: <20241008022358.863393-5-shaojijie@huawei.com> (raw)
In-Reply-To: <20241008022358.863393-1-shaojijie@huawei.com>
The driver supports four interrupts: TX interrupt, RX interrupt,
mdio interrupt, and error interrupt.
Actually, the driver does not use the mdio interrupt.
Therefore, the driver does not request the mdio interrupt.
The error interrupt distinguishes different error information
by using different masks. To distinguish different errors,
the statistics count is added for each error.
To ensure the consistency of the code process, masks are added for the
TX interrupt and RX interrupt.
This patch implements interrupt request, and provides a
unified entry for the interrupt handler function. However,
the specific interrupt handler function of each interrupt
is not implemented currently.
Because of pcim_enable_device(), the interrupt vector
is already device managed and does not need to be free actively.
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
ChangeLog:
v10 -> v11:
- Fix a syntax error in comment, suggested by Christophe JAILLET.
v10: https://lore.kernel.org/all/20240912025127.3912972-1-shaojijie@huawei.com/
RFC v1 -> RFC v2:
- Replace request_irq with devm_request_irq, suggested by Jonathan.
- Replace BIT_MASK() with BIT(), suggested by Jonathan.
- Introduce irq_handle in struct hbg_irq_info in advance to reduce code changes,
suggested by Jonathan.
RFC v1: https://lore.kernel.org/all/20240731094245.1967834-1-shaojijie@huawei.com/
---
.../ethernet/hisilicon/hibmcge/hbg_common.h | 18 +++
.../net/ethernet/hisilicon/hibmcge/hbg_hw.c | 55 +++++++++
.../net/ethernet/hisilicon/hibmcge/hbg_hw.h | 4 +
.../net/ethernet/hisilicon/hibmcge/hbg_irq.c | 114 ++++++++++++++++++
.../net/ethernet/hisilicon/hibmcge/hbg_irq.h | 11 ++
.../net/ethernet/hisilicon/hibmcge/hbg_main.c | 5 +
.../net/ethernet/hisilicon/hibmcge/hbg_reg.h | 27 +++++
7 files changed, 234 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c
create mode 100644 drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
index bb88a37518cb..ee4890d91ddd 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
@@ -12,6 +12,7 @@
#define HBG_STATUS_ENABLE 0x1
#define HBG_RX_SKIP1 0x00
#define HBG_RX_SKIP2 0x01
+#define HBG_VECTOR_NUM 4
enum hbg_nic_state {
HBG_NIC_STATE_EVENT_HANDLING = 0,
@@ -37,6 +38,22 @@ struct hbg_dev_specs {
u32 rx_buf_size;
};
+struct hbg_irq_info {
+ const char *name;
+ u32 mask;
+ bool reenable;
+ bool need_print;
+ u64 count;
+
+ void (*irq_handle)(struct hbg_priv *priv, struct hbg_irq_info *irq_info);
+};
+
+struct hbg_vector {
+ char name[HBG_VECTOR_NUM][32];
+ struct hbg_irq_info *info_array;
+ u32 info_array_len;
+};
+
struct hbg_mac {
struct mii_bus *mdio_bus;
struct phy_device *phydev;
@@ -55,6 +72,7 @@ struct hbg_priv {
struct hbg_dev_specs dev_specs;
unsigned long state;
struct hbg_mac mac;
+ struct hbg_vector vectors;
};
#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
index 7b99c3295b02..b201f2bc4ffe 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
@@ -74,6 +74,61 @@ static int hbg_hw_dev_specs_init(struct hbg_priv *priv)
return 0;
}
+u32 hbg_hw_get_irq_status(struct hbg_priv *priv)
+{
+ u32 status;
+
+ status = hbg_reg_read(priv, HBG_REG_CF_INTRPT_STAT_ADDR);
+
+ status |= FIELD_PREP(HBG_INT_MSK_TX_B,
+ hbg_reg_read(priv, HBG_REG_CF_IND_TXINT_STAT_ADDR));
+ status |= FIELD_PREP(HBG_INT_MSK_RX_B,
+ hbg_reg_read(priv, HBG_REG_CF_IND_RXINT_STAT_ADDR));
+
+ return status;
+}
+
+void hbg_hw_irq_clear(struct hbg_priv *priv, u32 mask)
+{
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_TXINT_CLR_ADDR, 0x1);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_RXINT_CLR_ADDR, 0x1);
+
+ return hbg_reg_write(priv, HBG_REG_CF_INTRPT_CLR_ADDR, mask);
+}
+
+bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask)
+{
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_read(priv, HBG_REG_CF_IND_TXINT_MSK_ADDR);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_read(priv, HBG_REG_CF_IND_RXINT_MSK_ADDR);
+
+ return hbg_reg_read(priv, HBG_REG_CF_INTRPT_MSK_ADDR) & mask;
+}
+
+void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable)
+{
+ u32 value;
+
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_TXINT_MSK_ADDR, enable);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_RXINT_MSK_ADDR, enable);
+
+ value = hbg_reg_read(priv, HBG_REG_CF_INTRPT_MSK_ADDR);
+ if (enable)
+ value |= mask;
+ else
+ value &= ~mask;
+
+ hbg_reg_write(priv, HBG_REG_CF_INTRPT_MSK_ADDR, value);
+}
+
void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex)
{
hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR,
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
index 47df597b885f..4d09bdd41c76 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
@@ -45,5 +45,9 @@ int hbg_hw_event_notify(struct hbg_priv *priv,
enum hbg_hw_event_type event_type);
int hbg_hw_init(struct hbg_priv *priv);
void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex);
+u32 hbg_hw_get_irq_status(struct hbg_priv *priv);
+void hbg_hw_irq_clear(struct hbg_priv *priv, u32 mask);
+bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask);
+void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c
new file mode 100644
index 000000000000..9a8e2ad267a0
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/interrupt.h>
+#include "hbg_irq.h"
+#include "hbg_hw.h"
+
+static void hbg_irq_handle_err(struct hbg_priv *priv,
+ struct hbg_irq_info *irq_info)
+{
+ if (irq_info->need_print)
+ dev_err(&priv->pdev->dev,
+ "receive error interrupt: %s\n", irq_info->name);
+}
+
+#define HBG_TXRX_IRQ_I(name, handle) \
+ {#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
+#define HBG_ERR_IRQ_I(name, need_print) \
+ {#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
+
+static struct hbg_irq_info hbg_irqs[] = {
+ HBG_TXRX_IRQ_I(RX, NULL),
+ HBG_TXRX_IRQ_I(TX, NULL),
+ HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true),
+ HBG_ERR_IRQ_I(TX_AHB_ERR, true),
+ HBG_ERR_IRQ_I(RX_BUF_AVL, false),
+ HBG_ERR_IRQ_I(REL_BUF_ERR, true),
+ HBG_ERR_IRQ_I(TXCFG_AVL, false),
+ HBG_ERR_IRQ_I(TX_DROP, false),
+ HBG_ERR_IRQ_I(RX_DROP, false),
+ HBG_ERR_IRQ_I(RX_AHB_ERR, true),
+ HBG_ERR_IRQ_I(MAC_FIFO_ERR, false),
+ HBG_ERR_IRQ_I(RBREQ_ERR, false),
+ HBG_ERR_IRQ_I(WE_ERR, false),
+};
+
+static irqreturn_t hbg_irq_handle(int irq_num, void *p)
+{
+ struct hbg_irq_info *info;
+ struct hbg_priv *priv = p;
+ u32 status;
+ u32 i;
+
+ status = hbg_hw_get_irq_status(priv);
+ for (i = 0; i < priv->vectors.info_array_len; i++) {
+ info = &priv->vectors.info_array[i];
+ if (status & info->mask) {
+ if (!hbg_hw_irq_is_enabled(priv, info->mask))
+ continue;
+
+ hbg_hw_irq_enable(priv, info->mask, false);
+ hbg_hw_irq_clear(priv, info->mask);
+
+ info->count++;
+ if (info->irq_handle)
+ info->irq_handle(priv, info);
+
+ if (info->reenable)
+ hbg_hw_irq_enable(priv, info->mask, true);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const char *irq_names_map[HBG_VECTOR_NUM] = { "tx", "rx", "err", "mdio" };
+
+int hbg_irq_init(struct hbg_priv *priv)
+{
+ struct hbg_vector *vectors = &priv->vectors;
+ struct device *dev = &priv->pdev->dev;
+ int ret, id;
+ u32 i;
+
+ /* used pcim_enable_device(), so the vectors become device managed */
+ ret = pci_alloc_irq_vectors(priv->pdev, HBG_VECTOR_NUM, HBG_VECTOR_NUM,
+ PCI_IRQ_MSI | PCI_IRQ_MSIX);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to allocate MSI vectors\n");
+
+ if (ret != HBG_VECTOR_NUM)
+ return dev_err_probe(dev, -EINVAL,
+ "requested %u MSI, but allocated %d MSI\n",
+ HBG_VECTOR_NUM, ret);
+
+ /* mdio irq not requested, so the number of requested interrupts
+ * is HBG_VECTOR_NUM - 1.
+ */
+ for (i = 0; i < HBG_VECTOR_NUM - 1; i++) {
+ id = pci_irq_vector(priv->pdev, i);
+ if (id < 0)
+ return dev_err_probe(dev, id, "failed to get irq number\n");
+
+ snprintf(vectors->name[i], sizeof(vectors->name[i]), "%s-%s-%s",
+ dev_driver_string(dev), pci_name(priv->pdev),
+ irq_names_map[i]);
+
+ ret = devm_request_irq(dev, id, hbg_irq_handle, 0,
+ vectors->name[i], priv);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to requset irq: %s\n",
+ irq_names_map[i]);
+ }
+
+ vectors->info_array = hbg_irqs;
+ vectors->info_array_len = ARRAY_SIZE(hbg_irqs);
+ return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h
new file mode 100644
index 000000000000..5c5323cfc751
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_IRQ_H
+#define __HBG_IRQ_H
+
+#include "hbg_common.h"
+
+int hbg_irq_init(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index 546c36021905..e71ff821c582 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include "hbg_common.h"
#include "hbg_hw.h"
+#include "hbg_irq.h"
#include "hbg_mdio.h"
static int hbg_init(struct hbg_priv *priv)
@@ -20,6 +21,10 @@ static int hbg_init(struct hbg_priv *priv)
if (ret)
return ret;
+ ret = hbg_irq_init(priv);
+ if (ret)
+ return ret;
+
return hbg_mdio_init(priv);
}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
index 40decafd1e04..8cdf018c2de9 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
@@ -51,6 +51,27 @@
#define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B BIT(3)
/* PCU */
+#define HBG_REG_CF_INTRPT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x042C)
+#define HBG_INT_MSK_WE_ERR_B BIT(31)
+#define HBG_INT_MSK_RBREQ_ERR_B BIT(30)
+#define HBG_INT_MSK_MAC_FIFO_ERR_B BIT(29)
+#define HBG_INT_MSK_RX_AHB_ERR_B BIT(28)
+#define HBG_INT_MSK_RX_DROP_B BIT(26)
+#define HBG_INT_MSK_TX_DROP_B BIT(25)
+#define HBG_INT_MSK_TXCFG_AVL_B BIT(24)
+#define HBG_INT_MSK_REL_BUF_ERR_B BIT(23)
+#define HBG_INT_MSK_RX_BUF_AVL_B BIT(22)
+#define HBG_INT_MSK_TX_AHB_ERR_B BIT(21)
+#define HBG_INT_MSK_SRAM_PARITY_ERR_B BIT(20)
+#define HBG_INT_MSK_MAC_APP_TX_FIFO_ERR_B BIT(19)
+#define HBG_INT_MSK_MAC_APP_RX_FIFO_ERR_B BIT(18)
+#define HBG_INT_MSK_MAC_PCS_TX_FIFO_ERR_B BIT(17)
+#define HBG_INT_MSK_MAC_PCS_RX_FIFO_ERR_B BIT(16)
+#define HBG_INT_MSK_MAC_MII_FIFO_ERR_B BIT(15)
+#define HBG_INT_MSK_TX_B BIT(1) /* just used in driver */
+#define HBG_INT_MSK_RX_B BIT(0) /* just used in driver */
+#define HBG_REG_CF_INTRPT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0434)
+#define HBG_REG_CF_INTRPT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x0438)
#define HBG_REG_RX_BUF_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x04E4)
#define HBG_REG_RX_BUF_SIZE_M GENMASK(15, 0)
#define HBG_REG_BUS_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x04E8)
@@ -64,6 +85,12 @@
#define HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE2_M GENMASK(3, 0)
#define HBG_REG_RX_PKT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x04F4)
#define HBG_REG_RX_PKT_MODE_PARSE_MODE_M GENMASK(22, 21)
+#define HBG_REG_CF_IND_TXINT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x0694)
+#define HBG_REG_CF_IND_TXINT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0698)
+#define HBG_REG_CF_IND_TXINT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x069C)
+#define HBG_REG_CF_IND_RXINT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x06a0)
+#define HBG_REG_CF_IND_RXINT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x06a4)
+#define HBG_REG_CF_IND_RXINT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x06a8)
enum hbg_port_mode {
/* 0x0 ~ 0x5 are reserved */
--
2.33.0
next prev parent reply other threads:[~2024-10-08 2:30 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-08 2:23 [PATCH V11 net-next 00/10] Add support of HIBMCGE Ethernet Driver Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 01/10] net: hibmcge: Add pci table supported in this module Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 02/10] net: hibmcge: Add read/write registers supported through the bar space Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 03/10] net: hibmcge: Add mdio and hardware configuration supported in this module Jijie Shao
2024-10-08 2:23 ` Jijie Shao [this message]
2024-10-10 10:22 ` [PATCH V11 net-next 04/10] net: hibmcge: Add interrupt " Simon Horman
2024-10-10 14:24 ` Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 05/10] net: hibmcge: Implement some .ndo functions Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 06/10] net: hibmcge: Implement .ndo_start_xmit function Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 07/10] net: hibmcge: Implement rx_poll function to receive packets Jijie Shao
2024-10-09 21:35 ` Joe Damato
2024-10-09 21:42 ` Joe Damato
2024-10-10 1:04 ` Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 08/10] net: hibmcge: Implement some ethtool_ops functions Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 09/10] net: hibmcge: Add a Makefile and update Kconfig for hibmcge Jijie Shao
2024-10-08 2:23 ` [PATCH V11 net-next 10/10] net: hibmcge: Add maintainer " Jijie Shao
2024-10-10 2:37 ` Jakub Kicinski
2024-10-10 14:26 ` Jijie Shao
2024-10-10 2:36 ` [PATCH V11 net-next 00/10] Add support of HIBMCGE Ethernet Driver Jakub Kicinski
2024-10-10 14:25 ` Jijie Shao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241008022358.863393-5-shaojijie@huawei.com \
--to=shaojijie@huawei.com \
--cc=andrew@lunn.ch \
--cc=chenhao418@huawei.com \
--cc=christophe.jaillet@wanadoo.fr \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jdamato@fastly.com \
--cc=jonathan.cameron@huawei.com \
--cc=kalesh-anakkur.purayil@broadcom.com \
--cc=kuba@kernel.org \
--cc=libaihan@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=liuyonglong@huawei.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=salil.mehta@huawei.com \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=shenjian15@huawei.com \
--cc=shiyongbang@huawei.com \
--cc=sudongming1@huawei.com \
--cc=wangpeiyang1@huawei.com \
--cc=xujunsheng@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).