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.
30 #include <rte_cycles.h>
34 #include "efx_regs_mcdi.h"
39 #define SFC_MCDI_POLL_INTERVAL_MIN_US 10 /* 10us in 1us units */
40 #define SFC_MCDI_POLL_INTERVAL_MAX_US (US_PER_S / 10) /* 100ms in 1us units */
41 #define SFC_MCDI_WATCHDOG_INTERVAL_US (10 * US_PER_S) /* 10s in 1us units */
44 sfc_mcdi_timeout(struct sfc_adapter *sa)
46 sfc_warn(sa, "MC TIMEOUT");
48 sfc_panic(sa, "MCDI timeout handling is not implemented\n");
52 sfc_mcdi_poll(struct sfc_adapter *sa)
55 unsigned int delay_total;
56 unsigned int delay_us;
57 boolean_t aborted __rte_unused;
60 delay_us = SFC_MCDI_POLL_INTERVAL_MIN_US;
64 if (efx_mcdi_request_poll(enp))
67 if (delay_total > SFC_MCDI_WATCHDOG_INTERVAL_US) {
68 aborted = efx_mcdi_request_abort(enp);
74 rte_delay_us(delay_us);
76 delay_total += delay_us;
78 /* Exponentially back off the poll frequency */
79 RTE_BUILD_BUG_ON(SFC_MCDI_POLL_INTERVAL_MAX_US > UINT_MAX / 2);
81 if (delay_us > SFC_MCDI_POLL_INTERVAL_MAX_US)
82 delay_us = SFC_MCDI_POLL_INTERVAL_MAX_US;
88 sfc_mcdi_execute(void *arg, efx_mcdi_req_t *emrp)
90 struct sfc_adapter *sa = (struct sfc_adapter *)arg;
91 struct sfc_mcdi *mcdi = &sa->mcdi;
93 rte_spinlock_lock(&mcdi->lock);
95 SFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);
97 efx_mcdi_request_start(sa->nic, emrp, B_FALSE);
100 rte_spinlock_unlock(&mcdi->lock);
104 sfc_mcdi_ev_cpl(void *arg)
106 struct sfc_adapter *sa = (struct sfc_adapter *)arg;
107 struct sfc_mcdi *mcdi __rte_unused;
110 SFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);
112 /* MCDI is polled, completions are not expected */
117 sfc_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
119 struct sfc_adapter *sa = (struct sfc_adapter *)arg;
121 sfc_warn(sa, "MC %s",
122 (eme == EFX_MCDI_EXCEPTION_MC_REBOOT) ? "REBOOT" :
123 (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT) ? "BADASSERT" : "UNKNOWN");
125 sfc_panic(sa, "MCDI exceptions handling is not implemented\n");
129 sfc_mcdi_init(struct sfc_adapter *sa)
131 struct sfc_mcdi *mcdi;
133 efx_mcdi_transport_t *emtp;
136 sfc_log_init(sa, "entry");
140 SFC_ASSERT(mcdi->state == SFC_MCDI_UNINITIALIZED);
142 rte_spinlock_init(&mcdi->lock);
144 mcdi->state = SFC_MCDI_INITIALIZED;
146 max_msg_size = sizeof(uint32_t) + MCDI_CTL_SDU_LEN_MAX_V2;
147 rc = sfc_dma_alloc(sa, "mcdi", 0, max_msg_size, sa->socket_id,
152 emtp = &mcdi->transport;
153 emtp->emt_context = sa;
154 emtp->emt_dma_mem = &mcdi->mem;
155 emtp->emt_execute = sfc_mcdi_execute;
156 emtp->emt_ev_cpl = sfc_mcdi_ev_cpl;
157 emtp->emt_exception = sfc_mcdi_exception;
159 sfc_log_init(sa, "init MCDI");
160 rc = efx_mcdi_init(sa->nic, emtp);
167 memset(emtp, 0, sizeof(*emtp));
168 sfc_dma_free(sa, &mcdi->mem);
171 mcdi->state = SFC_MCDI_UNINITIALIZED;
176 sfc_mcdi_fini(struct sfc_adapter *sa)
178 struct sfc_mcdi *mcdi;
179 efx_mcdi_transport_t *emtp;
181 sfc_log_init(sa, "entry");
184 emtp = &mcdi->transport;
186 rte_spinlock_lock(&mcdi->lock);
188 SFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);
189 mcdi->state = SFC_MCDI_UNINITIALIZED;
191 sfc_log_init(sa, "fini MCDI");
192 efx_mcdi_fini(sa->nic);
193 memset(emtp, 0, sizeof(*emtp));
195 rte_spinlock_unlock(&mcdi->lock);
197 sfc_dma_free(sa, &mcdi->mem);