1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2016-2018 Solarflare Communications Inc.
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
11 * At the momemt of writing DPDK v16.07 has notion of two types of
12 * interrupts: LSC (link status change) and RXQ (receive indication).
13 * It allows to register interrupt callback for entire device which is
14 * not intended to be used for receive indication (i.e. link status
15 * change indication only). The handler has no information which HW
16 * interrupt has triggered it, so we don't know which event queue should
17 * be polled/reprimed (except qmask in the case of legacy line interrupt).
20 #include <rte_common.h>
21 #include <rte_interrupts.h>
30 sfc_intr_handle_mgmt_evq(struct sfc_adapter
*sa
)
34 rte_spinlock_lock(&sa
->mgmt_evq_lock
);
38 if (!sa
->mgmt_evq_running
) {
39 sfc_log_init(sa
, "interrupt on not running management EVQ %u",
44 if (sfc_ev_qprime(evq
) != 0)
45 sfc_err(sa
, "cannot prime EVQ %u", evq
->evq_index
);
48 rte_spinlock_unlock(&sa
->mgmt_evq_lock
);
52 sfc_intr_line_handler(void *cb_arg
)
54 struct sfc_adapter
*sa
= (struct sfc_adapter
*)cb_arg
;
55 efx_nic_t
*enp
= sa
->nic
;
58 unsigned int lsc_seq
= sa
->port
.lsc_seq
;
59 struct rte_pci_device
*pci_dev
= RTE_ETH_DEV_TO_PCI(sa
->eth_dev
);
61 sfc_log_init(sa
, "entry");
63 if (sa
->state
!= SFC_ADAPTER_STARTED
&&
64 sa
->state
!= SFC_ADAPTER_STARTING
&&
65 sa
->state
!= SFC_ADAPTER_STOPPING
) {
67 "interrupt on stopped adapter, don't reenable");
71 efx_intr_status_line(enp
, &fatal
, &qmask
);
73 (void)efx_intr_disable(enp
);
74 (void)efx_intr_fatal(enp
);
75 sfc_err(sa
, "fatal, interrupts disabled");
79 if (qmask
& (1 << sa
->mgmt_evq_index
))
80 sfc_intr_handle_mgmt_evq(sa
);
82 if (rte_intr_enable(&pci_dev
->intr_handle
) != 0)
83 sfc_err(sa
, "cannot reenable interrupts");
85 sfc_log_init(sa
, "done");
88 if (lsc_seq
!= sa
->port
.lsc_seq
) {
89 sfc_notice(sa
, "link status change event: link %s",
90 sa
->eth_dev
->data
->dev_link
.link_status
?
92 _rte_eth_dev_callback_process(sa
->eth_dev
,
93 RTE_ETH_EVENT_INTR_LSC
,
99 sfc_intr_message_handler(void *cb_arg
)
101 struct sfc_adapter
*sa
= (struct sfc_adapter
*)cb_arg
;
102 efx_nic_t
*enp
= sa
->nic
;
104 unsigned int lsc_seq
= sa
->port
.lsc_seq
;
105 struct rte_pci_device
*pci_dev
= RTE_ETH_DEV_TO_PCI(sa
->eth_dev
);
107 sfc_log_init(sa
, "entry");
109 if (sa
->state
!= SFC_ADAPTER_STARTED
&&
110 sa
->state
!= SFC_ADAPTER_STARTING
&&
111 sa
->state
!= SFC_ADAPTER_STOPPING
) {
112 sfc_log_init(sa
, "adapter not-started, don't reenable");
116 efx_intr_status_message(enp
, sa
->mgmt_evq_index
, &fatal
);
118 (void)efx_intr_disable(enp
);
119 (void)efx_intr_fatal(enp
);
120 sfc_err(sa
, "fatal, interrupts disabled");
124 sfc_intr_handle_mgmt_evq(sa
);
126 if (rte_intr_enable(&pci_dev
->intr_handle
) != 0)
127 sfc_err(sa
, "cannot reenable interrupts");
129 sfc_log_init(sa
, "done");
132 if (lsc_seq
!= sa
->port
.lsc_seq
) {
133 sfc_notice(sa
, "link status change event");
134 _rte_eth_dev_callback_process(sa
->eth_dev
,
135 RTE_ETH_EVENT_INTR_LSC
,
141 sfc_intr_start(struct sfc_adapter
*sa
)
143 struct sfc_intr
*intr
= &sa
->intr
;
144 struct rte_intr_handle
*intr_handle
;
145 struct rte_pci_device
*pci_dev
;
148 sfc_log_init(sa
, "entry");
151 * The EFX common code event queue module depends on the interrupt
152 * module. Ensure that the interrupt module is always initialized
153 * (even if interrupts are not used). Status memory is required
154 * for Siena only and may be NULL for EF10.
156 sfc_log_init(sa
, "efx_intr_init");
157 rc
= efx_intr_init(sa
->nic
, intr
->type
, NULL
);
161 pci_dev
= RTE_ETH_DEV_TO_PCI(sa
->eth_dev
);
162 intr_handle
= &pci_dev
->intr_handle
;
164 if (intr
->handler
!= NULL
) {
165 sfc_log_init(sa
, "rte_intr_callback_register");
166 rc
= rte_intr_callback_register(intr_handle
, intr
->handler
,
170 "cannot register interrupt handler (rc=%d)",
173 * Convert error code from negative returned by RTE API
174 * to positive used in the driver.
177 goto fail_rte_intr_cb_reg
;
180 sfc_log_init(sa
, "rte_intr_enable");
181 rc
= rte_intr_enable(intr_handle
);
183 sfc_err(sa
, "cannot enable interrupts (rc=%d)", rc
);
185 * Convert error code from negative returned by RTE API
186 * to positive used in the driver.
189 goto fail_rte_intr_enable
;
192 sfc_log_init(sa
, "efx_intr_enable");
193 efx_intr_enable(sa
->nic
);
196 sfc_log_init(sa
, "done type=%u max_intr=%d nb_efd=%u vec=%p",
197 intr_handle
->type
, intr_handle
->max_intr
,
198 intr_handle
->nb_efd
, intr_handle
->intr_vec
);
201 fail_rte_intr_enable
:
202 rte_intr_callback_unregister(intr_handle
, intr
->handler
, (void *)sa
);
204 fail_rte_intr_cb_reg
:
205 efx_intr_fini(sa
->nic
);
208 sfc_log_init(sa
, "failed %d", rc
);
213 sfc_intr_stop(struct sfc_adapter
*sa
)
215 struct sfc_intr
*intr
= &sa
->intr
;
216 struct rte_pci_device
*pci_dev
= RTE_ETH_DEV_TO_PCI(sa
->eth_dev
);
218 sfc_log_init(sa
, "entry");
220 if (intr
->handler
!= NULL
) {
221 struct rte_intr_handle
*intr_handle
;
224 efx_intr_disable(sa
->nic
);
226 intr_handle
= &pci_dev
->intr_handle
;
227 if (rte_intr_disable(intr_handle
) != 0)
228 sfc_err(sa
, "cannot disable interrupts");
230 while ((rc
= rte_intr_callback_unregister(intr_handle
,
231 intr
->handler
, (void *)sa
)) == -EAGAIN
)
235 "cannot unregister interrupt handler %d",
239 efx_intr_fini(sa
->nic
);
241 sfc_log_init(sa
, "done");
245 sfc_intr_configure(struct sfc_adapter
*sa
)
247 struct sfc_intr
*intr
= &sa
->intr
;
249 sfc_log_init(sa
, "entry");
251 intr
->handler
= NULL
;
252 intr
->lsc_intr
= (sa
->eth_dev
->data
->dev_conf
.intr_conf
.lsc
!= 0);
253 if (!intr
->lsc_intr
) {
254 sfc_notice(sa
, "LSC tracking using interrupts is disabled");
258 switch (intr
->type
) {
259 case EFX_INTR_MESSAGE
:
260 intr
->handler
= sfc_intr_message_handler
;
263 intr
->handler
= sfc_intr_line_handler
;
265 case EFX_INTR_INVALID
:
266 sfc_warn(sa
, "interrupts are not supported");
269 sfc_panic(sa
, "unexpected EFX interrupt type %u\n", intr
->type
);
274 sfc_log_init(sa
, "done");
279 sfc_intr_close(struct sfc_adapter
*sa
)
281 sfc_log_init(sa
, "entry");
283 sfc_log_init(sa
, "done");
287 sfc_intr_attach(struct sfc_adapter
*sa
)
289 struct sfc_intr
*intr
= &sa
->intr
;
290 struct rte_pci_device
*pci_dev
= RTE_ETH_DEV_TO_PCI(sa
->eth_dev
);
292 sfc_log_init(sa
, "entry");
294 switch (pci_dev
->intr_handle
.type
) {
295 #ifdef RTE_EXEC_ENV_LINUX
296 case RTE_INTR_HANDLE_UIO_INTX
:
297 case RTE_INTR_HANDLE_VFIO_LEGACY
:
298 intr
->type
= EFX_INTR_LINE
;
300 case RTE_INTR_HANDLE_UIO
:
301 case RTE_INTR_HANDLE_VFIO_MSI
:
302 case RTE_INTR_HANDLE_VFIO_MSIX
:
303 intr
->type
= EFX_INTR_MESSAGE
;
307 intr
->type
= EFX_INTR_INVALID
;
311 sfc_log_init(sa
, "done");
316 sfc_intr_detach(struct sfc_adapter
*sa
)
318 sfc_log_init(sa
, "entry");
320 sa
->intr
.type
= EFX_INTR_INVALID
;
322 sfc_log_init(sa
, "done");