File Index
Files and directories
Sign in
FILE

hbg_irq.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2// Copyright (c) 2024 Hisilicon Limited.
  3
  4#include <linux/interrupt.h>
  5#include "hbg_irq.h"
  6#include "hbg_hw.h"
  7
  8static void hbg_irq_handle_err(struct hbg_priv *priv,
  9			       const struct hbg_irq_info *irq_info)
 10{
 11	if (irq_info->need_print)
 12		dev_err(&priv->pdev->dev,
 13			"receive error interrupt: %s\n", irq_info->name);
 14
 15	if (irq_info->need_reset)
 16		hbg_err_reset_task_schedule(priv);
 17}
 18
 19static void hbg_irq_handle_tx(struct hbg_priv *priv,
 20			      const struct hbg_irq_info *irq_info)
 21{
 22	napi_schedule(&priv->tx_ring.napi);
 23}
 24
 25static void hbg_irq_handle_rx(struct hbg_priv *priv,
 26			      const struct hbg_irq_info *irq_info)
 27{
 28	napi_schedule(&priv->rx_ring.napi);
 29}
 30
 31static void hbg_irq_handle_rx_buf_val(struct hbg_priv *priv,
 32				      const struct hbg_irq_info *irq_info)
 33{
 34	priv->stats.rx_fifo_less_empty_thrsld_cnt++;
 35	hbg_hw_irq_enable(priv, irq_info->mask, true);
 36}
 37
 38#define HBG_IRQ_I(name, handle) \
 39	{#name, HBG_INT_MSK_##name##_B, false, false, false, handle}
 40#define HBG_ERR_IRQ_I(name, need_print, ndde_reset) \
 41	{#name, HBG_INT_MSK_##name##_B, true, need_print, \
 42	ndde_reset, hbg_irq_handle_err}
 43
 44static const struct hbg_irq_info hbg_irqs[] = {
 45	HBG_IRQ_I(RX, hbg_irq_handle_rx),
 46	HBG_IRQ_I(TX, hbg_irq_handle_tx),
 47	HBG_ERR_IRQ_I(TX_PKT_CPL, true, true),
 48	HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true, true),
 49	HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true, true),
 50	HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true, true),
 51	HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true, true),
 52	HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true, true),
 53	HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true, false),
 54	HBG_ERR_IRQ_I(TX_AHB_ERR, true, true),
 55	HBG_IRQ_I(RX_BUF_AVL, hbg_irq_handle_rx_buf_val),
 56	HBG_ERR_IRQ_I(REL_BUF_ERR, true, false),
 57	HBG_ERR_IRQ_I(TXCFG_AVL, false, false),
 58	HBG_ERR_IRQ_I(TX_DROP, false, false),
 59	HBG_ERR_IRQ_I(RX_DROP, false, false),
 60	HBG_ERR_IRQ_I(RX_AHB_ERR, true, false),
 61	HBG_ERR_IRQ_I(MAC_FIFO_ERR, true, true),
 62	HBG_ERR_IRQ_I(RBREQ_ERR, true, true),
 63	HBG_ERR_IRQ_I(WE_ERR, true, true),
 64};
 65
 66static irqreturn_t hbg_irq_handle(int irq_num, void *p)
 67{
 68	const struct hbg_irq_info *info;
 69	struct hbg_priv *priv = p;
 70	u32 status;
 71	u32 i;
 72
 73	status = hbg_hw_get_irq_status(priv);
 74	for (i = 0; i < priv->vectors.info_array_len; i++) {
 75		info = &priv->vectors.info_array[i];
 76		if (status & info->mask) {
 77			if (!hbg_hw_irq_is_enabled(priv, info->mask))
 78				continue;
 79
 80			hbg_hw_irq_enable(priv, info->mask, false);
 81			hbg_hw_irq_clear(priv, info->mask);
 82
 83			priv->vectors.stats_array[i]++;
 84			if (info->irq_handle)
 85				info->irq_handle(priv, info);
 86
 87			if (info->re_enable)
 88				hbg_hw_irq_enable(priv, info->mask, true);
 89		}
 90	}
 91
 92	return IRQ_HANDLED;
 93}
 94
 95static const char *irq_names_map[HBG_VECTOR_NUM] = { "tx", "rx",
 96						     "err", "mdio" };
 97
 98int hbg_irq_init(struct hbg_priv *priv)
 99{
100	struct hbg_vector *vectors = &priv->vectors;
101	struct device *dev = &priv->pdev->dev;
102	int ret, id;
103	u32 i;
104
105	/* used pcim_enable_device(),  so the vectors become device managed */
106	ret = pci_alloc_irq_vectors(priv->pdev, HBG_VECTOR_NUM, HBG_VECTOR_NUM,
107				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
108	if (ret < 0)
109		return dev_err_probe(dev, ret, "failed to allocate vectors\n");
110
111	if (ret != HBG_VECTOR_NUM)
112		return dev_err_probe(dev, -EINVAL,
113				     "requested %u MSI, but allocated %d MSI\n",
114				     HBG_VECTOR_NUM, ret);
115
116	/* mdio irq not requested, so the number of requested interrupts
117	 * is HBG_VECTOR_NUM - 1.
118	 */
119	for (i = 0; i < HBG_VECTOR_NUM - 1; i++) {
120		id = pci_irq_vector(priv->pdev, i);
121		if (id < 0)
122			return dev_err_probe(dev, id, "failed to get irq id\n");
123
124		snprintf(vectors->name[i], sizeof(vectors->name[i]), "%s-%s-%s",
125			 dev_driver_string(dev), pci_name(priv->pdev),
126			 irq_names_map[i]);
127
128		ret = devm_request_irq(dev, id, hbg_irq_handle, 0,
129				       vectors->name[i], priv);
130		if (ret)
131			return dev_err_probe(dev, ret,
132					     "failed to request irq: %s\n",
133					     irq_names_map[i]);
134	}
135
136	vectors->stats_array = devm_kcalloc(&priv->pdev->dev,
137					    ARRAY_SIZE(hbg_irqs),
138					    sizeof(u64), GFP_KERNEL);
139	if (!vectors->stats_array)
140		return -ENOMEM;
141
142	vectors->info_array = hbg_irqs;
143	vectors->info_array_len = ARRAY_SIZE(hbg_irqs);
144	return 0;
145}
~/ Read-only file preview.