1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2024 Hisilicon Limited.
4 #include <linux/interrupt.h>
8 static void hbg_irq_handle_err(struct hbg_priv
*priv
,
9 struct hbg_irq_info
*irq_info
)
11 if (irq_info
->need_print
)
12 dev_err(&priv
->pdev
->dev
,
13 "receive error interrupt: %s\n", irq_info
->name
);
16 static void hbg_irq_handle_tx(struct hbg_priv
*priv
,
17 struct hbg_irq_info
*irq_info
)
19 napi_schedule(&priv
->tx_ring
.napi
);
22 static void hbg_irq_handle_rx(struct hbg_priv
*priv
,
23 struct hbg_irq_info
*irq_info
)
25 napi_schedule(&priv
->rx_ring
.napi
);
28 #define HBG_TXRX_IRQ_I(name, handle) \
29 {#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
30 #define HBG_ERR_IRQ_I(name, need_print) \
31 {#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
33 static struct hbg_irq_info hbg_irqs
[] = {
34 HBG_TXRX_IRQ_I(RX
, hbg_irq_handle_rx
),
35 HBG_TXRX_IRQ_I(TX
, hbg_irq_handle_tx
),
36 HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR
, true),
37 HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR
, true),
38 HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR
, true),
39 HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR
, true),
40 HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR
, true),
41 HBG_ERR_IRQ_I(SRAM_PARITY_ERR
, true),
42 HBG_ERR_IRQ_I(TX_AHB_ERR
, true),
43 HBG_ERR_IRQ_I(RX_BUF_AVL
, false),
44 HBG_ERR_IRQ_I(REL_BUF_ERR
, true),
45 HBG_ERR_IRQ_I(TXCFG_AVL
, false),
46 HBG_ERR_IRQ_I(TX_DROP
, false),
47 HBG_ERR_IRQ_I(RX_DROP
, false),
48 HBG_ERR_IRQ_I(RX_AHB_ERR
, true),
49 HBG_ERR_IRQ_I(MAC_FIFO_ERR
, false),
50 HBG_ERR_IRQ_I(RBREQ_ERR
, false),
51 HBG_ERR_IRQ_I(WE_ERR
, false),
54 static irqreturn_t
hbg_irq_handle(int irq_num
, void *p
)
56 struct hbg_irq_info
*info
;
57 struct hbg_priv
*priv
= p
;
61 status
= hbg_hw_get_irq_status(priv
);
62 for (i
= 0; i
< priv
->vectors
.info_array_len
; i
++) {
63 info
= &priv
->vectors
.info_array
[i
];
64 if (status
& info
->mask
) {
65 if (!hbg_hw_irq_is_enabled(priv
, info
->mask
))
68 hbg_hw_irq_enable(priv
, info
->mask
, false);
69 hbg_hw_irq_clear(priv
, info
->mask
);
73 info
->irq_handle(priv
, info
);
76 hbg_hw_irq_enable(priv
, info
->mask
, true);
83 static const char *irq_names_map
[HBG_VECTOR_NUM
] = { "tx", "rx",
86 int hbg_irq_init(struct hbg_priv
*priv
)
88 struct hbg_vector
*vectors
= &priv
->vectors
;
89 struct device
*dev
= &priv
->pdev
->dev
;
93 /* used pcim_enable_device(), so the vectors become device managed */
94 ret
= pci_alloc_irq_vectors(priv
->pdev
, HBG_VECTOR_NUM
, HBG_VECTOR_NUM
,
95 PCI_IRQ_MSI
| PCI_IRQ_MSIX
);
97 return dev_err_probe(dev
, ret
, "failed to allocate vectors\n");
99 if (ret
!= HBG_VECTOR_NUM
)
100 return dev_err_probe(dev
, -EINVAL
,
101 "requested %u MSI, but allocated %d MSI\n",
102 HBG_VECTOR_NUM
, ret
);
104 /* mdio irq not requested, so the number of requested interrupts
105 * is HBG_VECTOR_NUM - 1.
107 for (i
= 0; i
< HBG_VECTOR_NUM
- 1; i
++) {
108 id
= pci_irq_vector(priv
->pdev
, i
);
110 return dev_err_probe(dev
, id
, "failed to get irq id\n");
112 snprintf(vectors
->name
[i
], sizeof(vectors
->name
[i
]), "%s-%s-%s",
113 dev_driver_string(dev
), pci_name(priv
->pdev
),
116 ret
= devm_request_irq(dev
, id
, hbg_irq_handle
, 0,
117 vectors
->name
[i
], priv
);
119 return dev_err_probe(dev
, ret
,
120 "failed to request irq: %s\n",
124 vectors
->info_array
= hbg_irqs
;
125 vectors
->info_array_len
= ARRAY_SIZE(hbg_irqs
);