2 * Copyright (c) 2016 Solarflare Communications Inc.
5 * This software was jointly developed between OKTET Labs (under contract
6 * for Solarflare) and Solarflare Communications, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * At the momemt of writing DPDK v16.07 has notion of two types of
32 * interrupts: LSC (link status change) and RXQ (receive indication).
33 * It allows to register interrupt callback for entire device which is
34 * not intended to be used for receive indication (i.e. link status
35 * change indication only). The handler has no information which HW
36 * interrupt has triggered it, so we don't know which event queue should
37 * be polled/reprimed (except qmask in the case of legacy line interrupt).
40 #include <rte_common.h>
41 #include <rte_interrupts.h>
50 sfc_intr_handle_mgmt_evq(struct sfc_adapter *sa)
54 rte_spinlock_lock(&sa->mgmt_evq_lock);
56 evq = sa->evq_info[sa->mgmt_evq_index].evq;
58 if (evq->init_state != SFC_EVQ_STARTED) {
59 sfc_log_init(sa, "interrupt on stopped EVQ %u", evq->evq_index);
63 if (sfc_ev_qprime(evq) != 0)
64 sfc_err(sa, "cannot prime EVQ %u", evq->evq_index);
67 rte_spinlock_unlock(&sa->mgmt_evq_lock);
71 sfc_intr_line_handler(struct rte_intr_handle *intr_handle, void *cb_arg)
73 struct sfc_adapter *sa = (struct sfc_adapter *)cb_arg;
74 efx_nic_t *enp = sa->nic;
77 unsigned int lsc_seq = sa->port.lsc_seq;
79 sfc_log_init(sa, "entry");
81 if (sa->state != SFC_ADAPTER_STARTED &&
82 sa->state != SFC_ADAPTER_STARTING &&
83 sa->state != SFC_ADAPTER_STOPPING) {
85 "interrupt on stopped adapter, don't reenable");
89 efx_intr_status_line(enp, &fatal, &qmask);
91 (void)efx_intr_disable(enp);
92 (void)efx_intr_fatal(enp);
93 sfc_err(sa, "fatal, interrupts disabled");
97 if (qmask & (1 << sa->mgmt_evq_index))
98 sfc_intr_handle_mgmt_evq(sa);
100 if (rte_intr_enable(intr_handle) != 0)
101 sfc_err(sa, "cannot reenable interrupts");
103 sfc_log_init(sa, "done");
106 if (lsc_seq != sa->port.lsc_seq) {
107 sfc_info(sa, "link status change event: link %s",
108 sa->eth_dev->data->dev_link.link_status ?
110 _rte_eth_dev_callback_process(sa->eth_dev,
111 RTE_ETH_EVENT_INTR_LSC, NULL);
116 sfc_intr_message_handler(struct rte_intr_handle *intr_handle, void *cb_arg)
118 struct sfc_adapter *sa = (struct sfc_adapter *)cb_arg;
119 efx_nic_t *enp = sa->nic;
121 unsigned int lsc_seq = sa->port.lsc_seq;
123 sfc_log_init(sa, "entry");
125 if (sa->state != SFC_ADAPTER_STARTED &&
126 sa->state != SFC_ADAPTER_STARTING &&
127 sa->state != SFC_ADAPTER_STOPPING) {
128 sfc_log_init(sa, "adapter not-started, don't reenable");
132 efx_intr_status_message(enp, sa->mgmt_evq_index, &fatal);
134 (void)efx_intr_disable(enp);
135 (void)efx_intr_fatal(enp);
136 sfc_err(sa, "fatal, interrupts disabled");
140 sfc_intr_handle_mgmt_evq(sa);
142 if (rte_intr_enable(intr_handle) != 0)
143 sfc_err(sa, "cannot reenable interrupts");
145 sfc_log_init(sa, "done");
148 if (lsc_seq != sa->port.lsc_seq) {
149 sfc_info(sa, "link status change event");
150 _rte_eth_dev_callback_process(sa->eth_dev,
151 RTE_ETH_EVENT_INTR_LSC, NULL);
156 sfc_intr_start(struct sfc_adapter *sa)
158 struct sfc_intr *intr = &sa->intr;
159 struct rte_intr_handle *intr_handle;
160 struct rte_pci_device *pci_dev;
163 sfc_log_init(sa, "entry");
166 * The EFX common code event queue module depends on the interrupt
167 * module. Ensure that the interrupt module is always initialized
168 * (even if interrupts are not used). Status memory is required
169 * for Siena only and may be NULL for EF10.
171 sfc_log_init(sa, "efx_intr_init");
172 rc = efx_intr_init(sa->nic, intr->type, NULL);
176 pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
177 intr_handle = &pci_dev->intr_handle;
179 if (intr->handler != NULL) {
180 sfc_log_init(sa, "rte_intr_callback_register");
181 rc = rte_intr_callback_register(intr_handle, intr->handler,
185 "cannot register interrupt handler (rc=%d)",
188 * Convert error code from negative returned by RTE API
189 * to positive used in the driver.
192 goto fail_rte_intr_cb_reg;
195 sfc_log_init(sa, "rte_intr_enable");
196 rc = rte_intr_enable(intr_handle);
198 sfc_err(sa, "cannot enable interrupts (rc=%d)", rc);
200 * Convert error code from negative returned by RTE API
201 * to positive used in the driver.
204 goto fail_rte_intr_enable;
207 sfc_log_init(sa, "efx_intr_enable");
208 efx_intr_enable(sa->nic);
211 sfc_log_init(sa, "done type=%u max_intr=%d nb_efd=%u vec=%p",
212 intr_handle->type, intr_handle->max_intr,
213 intr_handle->nb_efd, intr_handle->intr_vec);
216 fail_rte_intr_enable:
217 rte_intr_callback_unregister(intr_handle, intr->handler, (void *)sa);
219 fail_rte_intr_cb_reg:
220 efx_intr_fini(sa->nic);
223 sfc_log_init(sa, "failed %d", rc);
228 sfc_intr_stop(struct sfc_adapter *sa)
230 struct sfc_intr *intr = &sa->intr;
231 struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
233 sfc_log_init(sa, "entry");
235 if (intr->handler != NULL) {
236 struct rte_intr_handle *intr_handle;
239 efx_intr_disable(sa->nic);
241 intr_handle = &pci_dev->intr_handle;
242 if (rte_intr_disable(intr_handle) != 0)
243 sfc_err(sa, "cannot disable interrupts");
245 while ((rc = rte_intr_callback_unregister(intr_handle,
246 intr->handler, (void *)sa)) == -EAGAIN)
250 "cannot unregister interrupt handler %d",
254 efx_intr_fini(sa->nic);
256 sfc_log_init(sa, "done");
260 sfc_intr_init(struct sfc_adapter *sa)
262 struct sfc_intr *intr = &sa->intr;
264 sfc_log_init(sa, "entry");
266 intr->handler = NULL;
267 intr->lsc_intr = (sa->eth_dev->data->dev_conf.intr_conf.lsc != 0);
268 if (!intr->lsc_intr) {
269 sfc_info(sa, "LSC tracking using interrupts is disabled");
273 switch (intr->type) {
274 case EFX_INTR_MESSAGE:
275 intr->handler = sfc_intr_message_handler;
278 intr->handler = sfc_intr_line_handler;
280 case EFX_INTR_INVALID:
281 sfc_warn(sa, "interrupts are not supported");
284 sfc_panic(sa, "unexpected EFX interrupt type %u\n", intr->type);
289 sfc_log_init(sa, "done");
294 sfc_intr_fini(struct sfc_adapter *sa)
296 sfc_log_init(sa, "entry");
298 sfc_log_init(sa, "done");
302 sfc_intr_attach(struct sfc_adapter *sa)
304 struct sfc_intr *intr = &sa->intr;
305 struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev);
307 sfc_log_init(sa, "entry");
309 switch (pci_dev->intr_handle.type) {
310 #ifdef RTE_EXEC_ENV_LINUXAPP
311 case RTE_INTR_HANDLE_VFIO_LEGACY:
312 intr->type = EFX_INTR_LINE;
314 case RTE_INTR_HANDLE_VFIO_MSI:
315 case RTE_INTR_HANDLE_VFIO_MSIX:
316 intr->type = EFX_INTR_MESSAGE;
320 intr->type = EFX_INTR_INVALID;
324 sfc_log_init(sa, "done");
329 sfc_intr_detach(struct sfc_adapter *sa)
331 sfc_log_init(sa, "entry");
333 sa->intr.type = EFX_INTR_INVALID;
335 sfc_log_init(sa, "done");