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 8 static void hbg_irq_handle_err(struct hbg_priv *priv, 9 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 16 static void hbg_irq_handle_tx(struct hbg_priv *priv, 17 struct hbg_irq_info *irq_info) 18 { 19 napi_schedule(&priv->tx_ring.napi); 20 } 21 22 #define HBG_TXRX_IRQ_I(name, handle) \ 23 {#name, HBG_INT_MSK_##name##_B, false, false, 0, handle} 24 #define HBG_ERR_IRQ_I(name, need_print) \ 25 {#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err} 26 27 static struct hbg_irq_info hbg_irqs[] = { 28 HBG_TXRX_IRQ_I(RX, NULL), 29 HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx), 30 HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true), 31 HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true), 32 HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true), 33 HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true), 34 HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true), 35 HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true), 36 HBG_ERR_IRQ_I(TX_AHB_ERR, true), 37 HBG_ERR_IRQ_I(RX_BUF_AVL, false), 38 HBG_ERR_IRQ_I(REL_BUF_ERR, true), 39 HBG_ERR_IRQ_I(TXCFG_AVL, false), 40 HBG_ERR_IRQ_I(TX_DROP, false), 41 HBG_ERR_IRQ_I(RX_DROP, false), 42 HBG_ERR_IRQ_I(RX_AHB_ERR, true), 43 HBG_ERR_IRQ_I(MAC_FIFO_ERR, false), 44 HBG_ERR_IRQ_I(RBREQ_ERR, false), 45 HBG_ERR_IRQ_I(WE_ERR, false), 46 }; 47 48 static irqreturn_t hbg_irq_handle(int irq_num, void *p) 49 { 50 struct hbg_irq_info *info; 51 struct hbg_priv *priv = p; 52 u32 status; 53 u32 i; 54 55 status = hbg_hw_get_irq_status(priv); 56 for (i = 0; i < priv->vectors.info_array_len; i++) { 57 info = &priv->vectors.info_array[i]; 58 if (status & info->mask) { 59 if (!hbg_hw_irq_is_enabled(priv, info->mask)) 60 continue; 61 62 hbg_hw_irq_enable(priv, info->mask, false); 63 hbg_hw_irq_clear(priv, info->mask); 64 65 info->count++; 66 if (info->irq_handle) 67 info->irq_handle(priv, info); 68 69 if (info->re_enable) 70 hbg_hw_irq_enable(priv, info->mask, true); 71 } 72 } 73 74 return IRQ_HANDLED; 75 } 76 77 static const char *irq_names_map[HBG_VECTOR_NUM] = { "tx", "rx", 78 "err", "mdio" }; 79 80 int hbg_irq_init(struct hbg_priv *priv) 81 { 82 struct hbg_vector *vectors = &priv->vectors; 83 struct device *dev = &priv->pdev->dev; 84 int ret, id; 85 u32 i; 86 87 /* used pcim_enable_device(), so the vectors become device managed */ 88 ret = pci_alloc_irq_vectors(priv->pdev, HBG_VECTOR_NUM, HBG_VECTOR_NUM, 89 PCI_IRQ_MSI | PCI_IRQ_MSIX); 90 if (ret < 0) 91 return dev_err_probe(dev, ret, "failed to allocate vectors\n"); 92 93 if (ret != HBG_VECTOR_NUM) 94 return dev_err_probe(dev, -EINVAL, 95 "requested %u MSI, but allocated %d MSI\n", 96 HBG_VECTOR_NUM, ret); 97 98 /* mdio irq not requested, so the number of requested interrupts 99 * is HBG_VECTOR_NUM - 1. 100 */ 101 for (i = 0; i < HBG_VECTOR_NUM - 1; i++) { 102 id = pci_irq_vector(priv->pdev, i); 103 if (id < 0) 104 return dev_err_probe(dev, id, "failed to get irq id\n"); 105 106 snprintf(vectors->name[i], sizeof(vectors->name[i]), "%s-%s-%s", 107 dev_driver_string(dev), pci_name(priv->pdev), 108 irq_names_map[i]); 109 110 ret = devm_request_irq(dev, id, hbg_irq_handle, 0, 111 vectors->name[i], priv); 112 if (ret) 113 return dev_err_probe(dev, ret, 114 "failed to request irq: %s\n", 115 irq_names_map[i]); 116 } 117 118 vectors->info_array = hbg_irqs; 119 vectors->info_array_len = ARRAY_SIZE(hbg_irqs); 120 return 0; 121 } 122