xref: /linux/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
14d089035SJijie Shao // SPDX-License-Identifier: GPL-2.0+
24d089035SJijie Shao // Copyright (c) 2024 Hisilicon Limited.
34d089035SJijie Shao 
44d089035SJijie Shao #include <linux/interrupt.h>
54d089035SJijie Shao #include "hbg_irq.h"
64d089035SJijie Shao #include "hbg_hw.h"
74d089035SJijie Shao 
84d089035SJijie Shao static void hbg_irq_handle_err(struct hbg_priv *priv,
94d089035SJijie Shao 			       struct hbg_irq_info *irq_info)
104d089035SJijie Shao {
114d089035SJijie Shao 	if (irq_info->need_print)
124d089035SJijie Shao 		dev_err(&priv->pdev->dev,
134d089035SJijie Shao 			"receive error interrupt: %s\n", irq_info->name);
144d089035SJijie Shao }
154d089035SJijie Shao 
1640735e75SJijie Shao static void hbg_irq_handle_tx(struct hbg_priv *priv,
1740735e75SJijie Shao 			      struct hbg_irq_info *irq_info)
1840735e75SJijie Shao {
1940735e75SJijie Shao 	napi_schedule(&priv->tx_ring.napi);
2040735e75SJijie Shao }
2140735e75SJijie Shao 
22*f72e2559SJijie Shao static void hbg_irq_handle_rx(struct hbg_priv *priv,
23*f72e2559SJijie Shao 			      struct hbg_irq_info *irq_info)
24*f72e2559SJijie Shao {
25*f72e2559SJijie Shao 	napi_schedule(&priv->rx_ring.napi);
26*f72e2559SJijie Shao }
27*f72e2559SJijie Shao 
284d089035SJijie Shao #define HBG_TXRX_IRQ_I(name, handle) \
294d089035SJijie Shao 	{#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
304d089035SJijie Shao #define HBG_ERR_IRQ_I(name, need_print) \
314d089035SJijie Shao 	{#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
324d089035SJijie Shao 
334d089035SJijie Shao static struct hbg_irq_info hbg_irqs[] = {
34*f72e2559SJijie Shao 	HBG_TXRX_IRQ_I(RX, hbg_irq_handle_rx),
3540735e75SJijie Shao 	HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx),
364d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true),
374d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true),
384d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true),
394d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true),
404d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true),
414d089035SJijie Shao 	HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true),
424d089035SJijie Shao 	HBG_ERR_IRQ_I(TX_AHB_ERR, true),
434d089035SJijie Shao 	HBG_ERR_IRQ_I(RX_BUF_AVL, false),
444d089035SJijie Shao 	HBG_ERR_IRQ_I(REL_BUF_ERR, true),
454d089035SJijie Shao 	HBG_ERR_IRQ_I(TXCFG_AVL, false),
464d089035SJijie Shao 	HBG_ERR_IRQ_I(TX_DROP, false),
474d089035SJijie Shao 	HBG_ERR_IRQ_I(RX_DROP, false),
484d089035SJijie Shao 	HBG_ERR_IRQ_I(RX_AHB_ERR, true),
494d089035SJijie Shao 	HBG_ERR_IRQ_I(MAC_FIFO_ERR, false),
504d089035SJijie Shao 	HBG_ERR_IRQ_I(RBREQ_ERR, false),
514d089035SJijie Shao 	HBG_ERR_IRQ_I(WE_ERR, false),
524d089035SJijie Shao };
534d089035SJijie Shao 
544d089035SJijie Shao static irqreturn_t hbg_irq_handle(int irq_num, void *p)
554d089035SJijie Shao {
564d089035SJijie Shao 	struct hbg_irq_info *info;
574d089035SJijie Shao 	struct hbg_priv *priv = p;
584d089035SJijie Shao 	u32 status;
594d089035SJijie Shao 	u32 i;
604d089035SJijie Shao 
614d089035SJijie Shao 	status = hbg_hw_get_irq_status(priv);
624d089035SJijie Shao 	for (i = 0; i < priv->vectors.info_array_len; i++) {
634d089035SJijie Shao 		info = &priv->vectors.info_array[i];
644d089035SJijie Shao 		if (status & info->mask) {
654d089035SJijie Shao 			if (!hbg_hw_irq_is_enabled(priv, info->mask))
664d089035SJijie Shao 				continue;
674d089035SJijie Shao 
684d089035SJijie Shao 			hbg_hw_irq_enable(priv, info->mask, false);
694d089035SJijie Shao 			hbg_hw_irq_clear(priv, info->mask);
704d089035SJijie Shao 
714d089035SJijie Shao 			info->count++;
724d089035SJijie Shao 			if (info->irq_handle)
734d089035SJijie Shao 				info->irq_handle(priv, info);
744d089035SJijie Shao 
754d089035SJijie Shao 			if (info->re_enable)
764d089035SJijie Shao 				hbg_hw_irq_enable(priv, info->mask, true);
774d089035SJijie Shao 		}
784d089035SJijie Shao 	}
794d089035SJijie Shao 
804d089035SJijie Shao 	return IRQ_HANDLED;
814d089035SJijie Shao }
824d089035SJijie Shao 
834d089035SJijie Shao static const char *irq_names_map[HBG_VECTOR_NUM] = { "tx", "rx",
844d089035SJijie Shao 						     "err", "mdio" };
854d089035SJijie Shao 
864d089035SJijie Shao int hbg_irq_init(struct hbg_priv *priv)
874d089035SJijie Shao {
884d089035SJijie Shao 	struct hbg_vector *vectors = &priv->vectors;
894d089035SJijie Shao 	struct device *dev = &priv->pdev->dev;
904d089035SJijie Shao 	int ret, id;
914d089035SJijie Shao 	u32 i;
924d089035SJijie Shao 
934d089035SJijie Shao 	/* used pcim_enable_device(),  so the vectors become device managed */
944d089035SJijie Shao 	ret = pci_alloc_irq_vectors(priv->pdev, HBG_VECTOR_NUM, HBG_VECTOR_NUM,
954d089035SJijie Shao 				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
964d089035SJijie Shao 	if (ret < 0)
974d089035SJijie Shao 		return dev_err_probe(dev, ret, "failed to allocate vectors\n");
984d089035SJijie Shao 
994d089035SJijie Shao 	if (ret != HBG_VECTOR_NUM)
1004d089035SJijie Shao 		return dev_err_probe(dev, -EINVAL,
1014d089035SJijie Shao 				     "requested %u MSI, but allocated %d MSI\n",
1024d089035SJijie Shao 				     HBG_VECTOR_NUM, ret);
1034d089035SJijie Shao 
1044d089035SJijie Shao 	/* mdio irq not requested, so the number of requested interrupts
1054d089035SJijie Shao 	 * is HBG_VECTOR_NUM - 1.
1064d089035SJijie Shao 	 */
1074d089035SJijie Shao 	for (i = 0; i < HBG_VECTOR_NUM - 1; i++) {
1084d089035SJijie Shao 		id = pci_irq_vector(priv->pdev, i);
1094d089035SJijie Shao 		if (id < 0)
1104d089035SJijie Shao 			return dev_err_probe(dev, id, "failed to get irq id\n");
1114d089035SJijie Shao 
1124d089035SJijie Shao 		snprintf(vectors->name[i], sizeof(vectors->name[i]), "%s-%s-%s",
1134d089035SJijie Shao 			 dev_driver_string(dev), pci_name(priv->pdev),
1144d089035SJijie Shao 			 irq_names_map[i]);
1154d089035SJijie Shao 
1164d089035SJijie Shao 		ret = devm_request_irq(dev, id, hbg_irq_handle, 0,
1174d089035SJijie Shao 				       vectors->name[i], priv);
1184d089035SJijie Shao 		if (ret)
1194d089035SJijie Shao 			return dev_err_probe(dev, ret,
1204d089035SJijie Shao 					     "failed to request irq: %s\n",
1214d089035SJijie Shao 					     irq_names_map[i]);
1224d089035SJijie Shao 	}
1234d089035SJijie Shao 
1244d089035SJijie Shao 	vectors->info_array = hbg_irqs;
1254d089035SJijie Shao 	vectors->info_array_len = ARRAY_SIZE(hbg_irqs);
1264d089035SJijie Shao 	return 0;
1274d089035SJijie Shao }
128