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