13caa85daSAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
23caa85daSAndrew Rybchenko *
3*672386c1SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
43caa85daSAndrew Rybchenko * Copyright(c) 2016-2019 Solarflare Communications Inc.
53caa85daSAndrew Rybchenko *
63caa85daSAndrew Rybchenko * This software was jointly developed between OKTET Labs (under contract
73caa85daSAndrew Rybchenko * for Solarflare) and Solarflare Communications, Inc.
83caa85daSAndrew Rybchenko */
93caa85daSAndrew Rybchenko
103caa85daSAndrew Rybchenko #include <rte_cycles.h>
113caa85daSAndrew Rybchenko
123caa85daSAndrew Rybchenko #include "efx.h"
133caa85daSAndrew Rybchenko #include "efx_mcdi.h"
143caa85daSAndrew Rybchenko #include "efx_regs_mcdi.h"
153caa85daSAndrew Rybchenko
163caa85daSAndrew Rybchenko #include "sfc_efx_mcdi.h"
173caa85daSAndrew Rybchenko #include "sfc_efx_debug.h"
183caa85daSAndrew Rybchenko
193caa85daSAndrew Rybchenko #define SFC_EFX_MCDI_POLL_INTERVAL_MIN_US 10 /* 10us */
203caa85daSAndrew Rybchenko #define SFC_EFX_MCDI_POLL_INTERVAL_MAX_US (US_PER_S / 10) /* 100ms */
213caa85daSAndrew Rybchenko #define SFC_EFX_MCDI_WATCHDOG_INTERVAL_US (10 * US_PER_S) /* 10s */
223caa85daSAndrew Rybchenko
233caa85daSAndrew Rybchenko #define sfc_efx_mcdi_log(mcdi, level, ...) \
243caa85daSAndrew Rybchenko do { \
253caa85daSAndrew Rybchenko const struct sfc_efx_mcdi *_mcdi = (mcdi); \
263caa85daSAndrew Rybchenko \
273caa85daSAndrew Rybchenko rte_log(level, _mcdi->logtype, \
283caa85daSAndrew Rybchenko RTE_FMT("%s" RTE_FMT_HEAD(__VA_ARGS__ ,) "\n", \
293caa85daSAndrew Rybchenko _mcdi->log_prefix, \
303caa85daSAndrew Rybchenko RTE_FMT_TAIL(__VA_ARGS__,))); \
313caa85daSAndrew Rybchenko } while (0)
323caa85daSAndrew Rybchenko
333caa85daSAndrew Rybchenko #define sfc_efx_mcdi_crit(mcdi, ...) \
343caa85daSAndrew Rybchenko sfc_efx_mcdi_log(mcdi, RTE_LOG_CRIT, __VA_ARGS__)
353caa85daSAndrew Rybchenko
363caa85daSAndrew Rybchenko #define sfc_efx_mcdi_err(mcdi, ...) \
373caa85daSAndrew Rybchenko sfc_efx_mcdi_log(mcdi, RTE_LOG_ERR, __VA_ARGS__)
383caa85daSAndrew Rybchenko
393caa85daSAndrew Rybchenko #define sfc_efx_mcdi_warn(mcdi, ...) \
403caa85daSAndrew Rybchenko sfc_efx_mcdi_log(mcdi, RTE_LOG_WARNING, __VA_ARGS__)
413caa85daSAndrew Rybchenko
423caa85daSAndrew Rybchenko #define sfc_efx_mcdi_info(mcdi, ...) \
433caa85daSAndrew Rybchenko sfc_efx_mcdi_log(mcdi, RTE_LOG_INFO, __VA_ARGS__)
443caa85daSAndrew Rybchenko
453caa85daSAndrew Rybchenko /** Level value used by MCDI log statements */
463caa85daSAndrew Rybchenko #define SFC_EFX_LOG_LEVEL_MCDI RTE_LOG_INFO
473caa85daSAndrew Rybchenko
483caa85daSAndrew Rybchenko #define sfc_efx_log_mcdi(mcdi, ...) \
493caa85daSAndrew Rybchenko sfc_efx_mcdi_log(mcdi, SFC_EFX_LOG_LEVEL_MCDI, __VA_ARGS__)
503caa85daSAndrew Rybchenko
513caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_timeout(struct sfc_efx_mcdi * mcdi)523caa85daSAndrew Rybchenko sfc_efx_mcdi_timeout(struct sfc_efx_mcdi *mcdi)
533caa85daSAndrew Rybchenko {
543caa85daSAndrew Rybchenko sfc_efx_mcdi_warn(mcdi, "MC TIMEOUT");
553caa85daSAndrew Rybchenko
563caa85daSAndrew Rybchenko sfc_efx_mcdi_crit(mcdi, "MCDI timeout handling is not implemented");
573caa85daSAndrew Rybchenko sfc_efx_mcdi_crit(mcdi, "NIC is unusable");
583caa85daSAndrew Rybchenko mcdi->state = SFC_EFX_MCDI_DEAD;
593caa85daSAndrew Rybchenko }
603caa85daSAndrew Rybchenko
613caa85daSAndrew Rybchenko static inline boolean_t
sfc_efx_mcdi_proxy_event_available(struct sfc_efx_mcdi * mcdi)623caa85daSAndrew Rybchenko sfc_efx_mcdi_proxy_event_available(struct sfc_efx_mcdi *mcdi)
633caa85daSAndrew Rybchenko {
643caa85daSAndrew Rybchenko mcdi->proxy_handle = 0;
653caa85daSAndrew Rybchenko mcdi->proxy_result = ETIMEDOUT;
663caa85daSAndrew Rybchenko mcdi->ops->mgmt_evq_poll(mcdi->ops_cookie);
673caa85daSAndrew Rybchenko if (mcdi->proxy_result != ETIMEDOUT)
683caa85daSAndrew Rybchenko return B_TRUE;
693caa85daSAndrew Rybchenko
703caa85daSAndrew Rybchenko return B_FALSE;
713caa85daSAndrew Rybchenko }
723caa85daSAndrew Rybchenko
733caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_poll(struct sfc_efx_mcdi * mcdi,boolean_t proxy)743caa85daSAndrew Rybchenko sfc_efx_mcdi_poll(struct sfc_efx_mcdi *mcdi, boolean_t proxy)
753caa85daSAndrew Rybchenko {
763caa85daSAndrew Rybchenko efx_nic_t *enp;
773caa85daSAndrew Rybchenko unsigned int delay_total;
783caa85daSAndrew Rybchenko unsigned int delay_us;
793caa85daSAndrew Rybchenko boolean_t aborted __rte_unused;
803caa85daSAndrew Rybchenko
813caa85daSAndrew Rybchenko delay_total = 0;
823caa85daSAndrew Rybchenko delay_us = SFC_EFX_MCDI_POLL_INTERVAL_MIN_US;
833caa85daSAndrew Rybchenko enp = mcdi->nic;
843caa85daSAndrew Rybchenko
853caa85daSAndrew Rybchenko do {
863caa85daSAndrew Rybchenko boolean_t poll_completed;
873caa85daSAndrew Rybchenko
883caa85daSAndrew Rybchenko poll_completed = (proxy) ?
893caa85daSAndrew Rybchenko sfc_efx_mcdi_proxy_event_available(mcdi) :
903caa85daSAndrew Rybchenko efx_mcdi_request_poll(enp);
913caa85daSAndrew Rybchenko if (poll_completed)
923caa85daSAndrew Rybchenko return;
933caa85daSAndrew Rybchenko
943caa85daSAndrew Rybchenko if (delay_total > SFC_EFX_MCDI_WATCHDOG_INTERVAL_US) {
953caa85daSAndrew Rybchenko if (!proxy) {
963caa85daSAndrew Rybchenko aborted = efx_mcdi_request_abort(enp);
973caa85daSAndrew Rybchenko SFC_EFX_ASSERT(aborted);
983caa85daSAndrew Rybchenko sfc_efx_mcdi_timeout(mcdi);
993caa85daSAndrew Rybchenko }
1003caa85daSAndrew Rybchenko
1013caa85daSAndrew Rybchenko return;
1023caa85daSAndrew Rybchenko }
1033caa85daSAndrew Rybchenko
1043caa85daSAndrew Rybchenko rte_delay_us(delay_us);
1053caa85daSAndrew Rybchenko
1063caa85daSAndrew Rybchenko delay_total += delay_us;
1073caa85daSAndrew Rybchenko
1083caa85daSAndrew Rybchenko /* Exponentially back off the poll frequency */
1093caa85daSAndrew Rybchenko RTE_BUILD_BUG_ON(SFC_EFX_MCDI_POLL_INTERVAL_MAX_US >
1103caa85daSAndrew Rybchenko UINT_MAX / 2);
1113caa85daSAndrew Rybchenko delay_us *= 2;
1123caa85daSAndrew Rybchenko if (delay_us > SFC_EFX_MCDI_POLL_INTERVAL_MAX_US)
1133caa85daSAndrew Rybchenko delay_us = SFC_EFX_MCDI_POLL_INTERVAL_MAX_US;
1143caa85daSAndrew Rybchenko
1153caa85daSAndrew Rybchenko } while (1);
1163caa85daSAndrew Rybchenko }
1173caa85daSAndrew Rybchenko
1183caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_execute(void * arg,efx_mcdi_req_t * emrp)1193caa85daSAndrew Rybchenko sfc_efx_mcdi_execute(void *arg, efx_mcdi_req_t *emrp)
1203caa85daSAndrew Rybchenko {
1213caa85daSAndrew Rybchenko struct sfc_efx_mcdi *mcdi = (struct sfc_efx_mcdi *)arg;
1223caa85daSAndrew Rybchenko uint32_t proxy_handle;
1233caa85daSAndrew Rybchenko
1243caa85daSAndrew Rybchenko if (mcdi->state == SFC_EFX_MCDI_DEAD) {
1253caa85daSAndrew Rybchenko emrp->emr_rc = ENOEXEC;
1263caa85daSAndrew Rybchenko return;
1273caa85daSAndrew Rybchenko }
1283caa85daSAndrew Rybchenko
1293caa85daSAndrew Rybchenko rte_spinlock_lock(&mcdi->lock);
1303caa85daSAndrew Rybchenko
1313caa85daSAndrew Rybchenko SFC_EFX_ASSERT(mcdi->state == SFC_EFX_MCDI_INITIALIZED);
1323caa85daSAndrew Rybchenko
1333caa85daSAndrew Rybchenko efx_mcdi_request_start(mcdi->nic, emrp, B_FALSE);
1343caa85daSAndrew Rybchenko sfc_efx_mcdi_poll(mcdi, B_FALSE);
1353caa85daSAndrew Rybchenko
1363caa85daSAndrew Rybchenko if (efx_mcdi_get_proxy_handle(mcdi->nic, emrp, &proxy_handle) == 0) {
1373caa85daSAndrew Rybchenko /*
1383caa85daSAndrew Rybchenko * Authorization is required for the MCDI request;
1393caa85daSAndrew Rybchenko * wait for an MCDI proxy response event to bring
1403caa85daSAndrew Rybchenko * a non-zero proxy handle (should be the same as
1413caa85daSAndrew Rybchenko * the value obtained above) and operation status
1423caa85daSAndrew Rybchenko */
1433caa85daSAndrew Rybchenko sfc_efx_mcdi_poll(mcdi, B_TRUE);
1443caa85daSAndrew Rybchenko
1453caa85daSAndrew Rybchenko if ((mcdi->proxy_handle != 0) &&
1463caa85daSAndrew Rybchenko (mcdi->proxy_handle != proxy_handle)) {
1473caa85daSAndrew Rybchenko sfc_efx_mcdi_err(mcdi, "Unexpected MCDI proxy event");
1483caa85daSAndrew Rybchenko emrp->emr_rc = EFAULT;
1493caa85daSAndrew Rybchenko } else if (mcdi->proxy_result == 0) {
1503caa85daSAndrew Rybchenko /*
1513caa85daSAndrew Rybchenko * Authorization succeeded; re-issue the original
1523caa85daSAndrew Rybchenko * request and poll for an ordinary MCDI response
1533caa85daSAndrew Rybchenko */
1543caa85daSAndrew Rybchenko efx_mcdi_request_start(mcdi->nic, emrp, B_FALSE);
1553caa85daSAndrew Rybchenko sfc_efx_mcdi_poll(mcdi, B_FALSE);
1563caa85daSAndrew Rybchenko } else {
1573caa85daSAndrew Rybchenko emrp->emr_rc = mcdi->proxy_result;
1583caa85daSAndrew Rybchenko sfc_efx_mcdi_err(mcdi,
1593caa85daSAndrew Rybchenko "MCDI proxy authorization failed (handle=%08x, result=%d)",
1603caa85daSAndrew Rybchenko proxy_handle, mcdi->proxy_result);
1613caa85daSAndrew Rybchenko }
1623caa85daSAndrew Rybchenko }
1633caa85daSAndrew Rybchenko
1643caa85daSAndrew Rybchenko rte_spinlock_unlock(&mcdi->lock);
1653caa85daSAndrew Rybchenko }
1663caa85daSAndrew Rybchenko
1673caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_ev_cpl(void * arg)1683caa85daSAndrew Rybchenko sfc_efx_mcdi_ev_cpl(void *arg)
1693caa85daSAndrew Rybchenko {
1703caa85daSAndrew Rybchenko struct sfc_efx_mcdi *mcdi = (struct sfc_efx_mcdi *)arg;
1713caa85daSAndrew Rybchenko
1723caa85daSAndrew Rybchenko RTE_SET_USED(mcdi);
1733caa85daSAndrew Rybchenko SFC_EFX_ASSERT(mcdi->state == SFC_EFX_MCDI_INITIALIZED);
1743caa85daSAndrew Rybchenko
1753caa85daSAndrew Rybchenko /* MCDI is polled, completions are not expected */
1763caa85daSAndrew Rybchenko SFC_EFX_ASSERT(0);
1773caa85daSAndrew Rybchenko }
1783caa85daSAndrew Rybchenko
1793caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_exception(void * arg,efx_mcdi_exception_t eme)1803caa85daSAndrew Rybchenko sfc_efx_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
1813caa85daSAndrew Rybchenko {
1823caa85daSAndrew Rybchenko struct sfc_efx_mcdi *mcdi = (struct sfc_efx_mcdi *)arg;
1833caa85daSAndrew Rybchenko
1843caa85daSAndrew Rybchenko sfc_efx_mcdi_warn(mcdi, "MC %s",
1853caa85daSAndrew Rybchenko (eme == EFX_MCDI_EXCEPTION_MC_REBOOT) ? "REBOOT" :
1863caa85daSAndrew Rybchenko (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT) ? "BADASSERT" : "UNKNOWN");
1873caa85daSAndrew Rybchenko
1883caa85daSAndrew Rybchenko mcdi->ops->sched_restart(mcdi->ops_cookie);
1893caa85daSAndrew Rybchenko }
1903caa85daSAndrew Rybchenko
1913caa85daSAndrew Rybchenko #define SFC_MCDI_LOG_BUF_SIZE 128
1923caa85daSAndrew Rybchenko
1933caa85daSAndrew Rybchenko static size_t
sfc_efx_mcdi_do_log(const struct sfc_efx_mcdi * mcdi,char * buffer,void * data,size_t data_size,size_t pfxsize,size_t position)1943caa85daSAndrew Rybchenko sfc_efx_mcdi_do_log(const struct sfc_efx_mcdi *mcdi,
1953caa85daSAndrew Rybchenko char *buffer, void *data, size_t data_size,
1963caa85daSAndrew Rybchenko size_t pfxsize, size_t position)
1973caa85daSAndrew Rybchenko {
1983caa85daSAndrew Rybchenko uint32_t *words = data;
1993caa85daSAndrew Rybchenko /* Space separator plus 2 characters per byte */
2003caa85daSAndrew Rybchenko const size_t word_str_space = 1 + 2 * sizeof(*words);
2013caa85daSAndrew Rybchenko size_t i;
2023caa85daSAndrew Rybchenko
2033caa85daSAndrew Rybchenko for (i = 0; i < data_size; i += sizeof(*words)) {
2043caa85daSAndrew Rybchenko if (position + word_str_space >=
2053caa85daSAndrew Rybchenko SFC_MCDI_LOG_BUF_SIZE) {
2063caa85daSAndrew Rybchenko /* Flush at SFC_MCDI_LOG_BUF_SIZE with backslash
2073caa85daSAndrew Rybchenko * at the end which is required by netlogdecode.
2083caa85daSAndrew Rybchenko */
2093caa85daSAndrew Rybchenko buffer[position] = '\0';
2103caa85daSAndrew Rybchenko sfc_efx_log_mcdi(mcdi, "%s \\", buffer);
2113caa85daSAndrew Rybchenko /* Preserve prefix for the next log message */
2123caa85daSAndrew Rybchenko position = pfxsize;
2133caa85daSAndrew Rybchenko }
2143caa85daSAndrew Rybchenko position += snprintf(buffer + position,
2153caa85daSAndrew Rybchenko SFC_MCDI_LOG_BUF_SIZE - position,
2163caa85daSAndrew Rybchenko " %08x", *words);
2173caa85daSAndrew Rybchenko words++;
2183caa85daSAndrew Rybchenko }
2193caa85daSAndrew Rybchenko return position;
2203caa85daSAndrew Rybchenko }
2213caa85daSAndrew Rybchenko
2223caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_logger(void * arg,efx_log_msg_t type,void * header,size_t header_size,void * data,size_t data_size)2233caa85daSAndrew Rybchenko sfc_efx_mcdi_logger(void *arg, efx_log_msg_t type,
2243caa85daSAndrew Rybchenko void *header, size_t header_size,
2253caa85daSAndrew Rybchenko void *data, size_t data_size)
2263caa85daSAndrew Rybchenko {
2273caa85daSAndrew Rybchenko struct sfc_efx_mcdi *mcdi = (struct sfc_efx_mcdi *)arg;
2283caa85daSAndrew Rybchenko char buffer[SFC_MCDI_LOG_BUF_SIZE];
2293caa85daSAndrew Rybchenko size_t pfxsize;
2303caa85daSAndrew Rybchenko size_t start;
2313caa85daSAndrew Rybchenko
2323caa85daSAndrew Rybchenko /*
2333caa85daSAndrew Rybchenko * Unlike the other cases, MCDI logging implies more onerous work
2343caa85daSAndrew Rybchenko * needed to produce a message. If the dynamic log level prevents
2353caa85daSAndrew Rybchenko * the end result from being printed, the CPU time will be wasted.
2363caa85daSAndrew Rybchenko *
2373caa85daSAndrew Rybchenko * To avoid wasting time, the actual level is examined in advance.
2383caa85daSAndrew Rybchenko */
2393caa85daSAndrew Rybchenko if (rte_log_get_level(mcdi->logtype) < (int)SFC_EFX_LOG_LEVEL_MCDI)
2403caa85daSAndrew Rybchenko return;
2413caa85daSAndrew Rybchenko
2423caa85daSAndrew Rybchenko /* The format including prefix added by sfc_efx_log_mcdi() is the
2433caa85daSAndrew Rybchenko * format consumed by the Solarflare netlogdecode tool.
2443caa85daSAndrew Rybchenko */
2453caa85daSAndrew Rybchenko pfxsize = snprintf(buffer, sizeof(buffer), "MCDI RPC %s:",
2463caa85daSAndrew Rybchenko type == EFX_LOG_MCDI_REQUEST ? "REQ" :
2473caa85daSAndrew Rybchenko type == EFX_LOG_MCDI_RESPONSE ? "RESP" : "???");
2483caa85daSAndrew Rybchenko start = sfc_efx_mcdi_do_log(mcdi, buffer, header, header_size,
2493caa85daSAndrew Rybchenko pfxsize, pfxsize);
2503caa85daSAndrew Rybchenko start = sfc_efx_mcdi_do_log(mcdi, buffer, data, data_size,
2513caa85daSAndrew Rybchenko pfxsize, start);
2523caa85daSAndrew Rybchenko if (start != pfxsize) {
2533caa85daSAndrew Rybchenko buffer[start] = '\0';
2543caa85daSAndrew Rybchenko sfc_efx_log_mcdi(mcdi, "%s", buffer);
2553caa85daSAndrew Rybchenko }
2563caa85daSAndrew Rybchenko }
2573caa85daSAndrew Rybchenko
2583caa85daSAndrew Rybchenko static void
sfc_efx_mcdi_ev_proxy_response(void * arg,uint32_t handle,efx_rc_t result)2593caa85daSAndrew Rybchenko sfc_efx_mcdi_ev_proxy_response(void *arg, uint32_t handle, efx_rc_t result)
2603caa85daSAndrew Rybchenko {
2613caa85daSAndrew Rybchenko struct sfc_efx_mcdi *mcdi = (struct sfc_efx_mcdi *)arg;
2623caa85daSAndrew Rybchenko
2633caa85daSAndrew Rybchenko mcdi->proxy_handle = handle;
2643caa85daSAndrew Rybchenko mcdi->proxy_result = result;
2653caa85daSAndrew Rybchenko }
2663caa85daSAndrew Rybchenko
2673caa85daSAndrew Rybchenko int
sfc_efx_mcdi_init(struct sfc_efx_mcdi * mcdi,uint32_t logtype,const char * log_prefix,efx_nic_t * nic,const struct sfc_efx_mcdi_ops * ops,void * ops_cookie)2683caa85daSAndrew Rybchenko sfc_efx_mcdi_init(struct sfc_efx_mcdi *mcdi,
2693caa85daSAndrew Rybchenko uint32_t logtype, const char *log_prefix, efx_nic_t *nic,
2703caa85daSAndrew Rybchenko const struct sfc_efx_mcdi_ops *ops, void *ops_cookie)
2713caa85daSAndrew Rybchenko {
2723caa85daSAndrew Rybchenko size_t max_msg_size;
2733caa85daSAndrew Rybchenko efx_mcdi_transport_t *emtp;
2743caa85daSAndrew Rybchenko int rc;
2753caa85daSAndrew Rybchenko
2763caa85daSAndrew Rybchenko if (ops->dma_alloc == NULL || ops->dma_free == NULL ||
2773caa85daSAndrew Rybchenko ops->sched_restart == NULL || ops->mgmt_evq_poll == NULL)
2783caa85daSAndrew Rybchenko return EINVAL;
2793caa85daSAndrew Rybchenko
2803caa85daSAndrew Rybchenko SFC_EFX_ASSERT(mcdi->state == SFC_EFX_MCDI_UNINITIALIZED);
2813caa85daSAndrew Rybchenko
2823caa85daSAndrew Rybchenko rte_spinlock_init(&mcdi->lock);
2833caa85daSAndrew Rybchenko
2843caa85daSAndrew Rybchenko mcdi->ops = ops;
2853caa85daSAndrew Rybchenko mcdi->ops_cookie = ops_cookie;
2863caa85daSAndrew Rybchenko mcdi->nic = nic;
2873caa85daSAndrew Rybchenko
2883caa85daSAndrew Rybchenko mcdi->state = SFC_EFX_MCDI_INITIALIZED;
2893caa85daSAndrew Rybchenko
2903caa85daSAndrew Rybchenko mcdi->logtype = logtype;
2913caa85daSAndrew Rybchenko mcdi->log_prefix = log_prefix;
2923caa85daSAndrew Rybchenko
2933caa85daSAndrew Rybchenko max_msg_size = sizeof(uint32_t) + MCDI_CTL_SDU_LEN_MAX_V2;
2943caa85daSAndrew Rybchenko rc = ops->dma_alloc(ops_cookie, "mcdi", max_msg_size, &mcdi->mem);
2953caa85daSAndrew Rybchenko if (rc != 0)
2963caa85daSAndrew Rybchenko goto fail_dma_alloc;
2973caa85daSAndrew Rybchenko
2983caa85daSAndrew Rybchenko emtp = &mcdi->transport;
2993caa85daSAndrew Rybchenko emtp->emt_context = mcdi;
3003caa85daSAndrew Rybchenko emtp->emt_dma_mem = &mcdi->mem;
3013caa85daSAndrew Rybchenko emtp->emt_execute = sfc_efx_mcdi_execute;
3023caa85daSAndrew Rybchenko emtp->emt_ev_cpl = sfc_efx_mcdi_ev_cpl;
3033caa85daSAndrew Rybchenko emtp->emt_exception = sfc_efx_mcdi_exception;
3043caa85daSAndrew Rybchenko emtp->emt_logger = sfc_efx_mcdi_logger;
3053caa85daSAndrew Rybchenko emtp->emt_ev_proxy_response = sfc_efx_mcdi_ev_proxy_response;
3063caa85daSAndrew Rybchenko
3073caa85daSAndrew Rybchenko sfc_efx_mcdi_info(mcdi, "init MCDI");
3083caa85daSAndrew Rybchenko rc = efx_mcdi_init(mcdi->nic, emtp);
3093caa85daSAndrew Rybchenko if (rc != 0)
3103caa85daSAndrew Rybchenko goto fail_mcdi_init;
3113caa85daSAndrew Rybchenko
3123caa85daSAndrew Rybchenko return 0;
3133caa85daSAndrew Rybchenko
3143caa85daSAndrew Rybchenko fail_mcdi_init:
3153caa85daSAndrew Rybchenko memset(emtp, 0, sizeof(*emtp));
3163caa85daSAndrew Rybchenko ops->dma_free(ops_cookie, &mcdi->mem);
3173caa85daSAndrew Rybchenko
3183caa85daSAndrew Rybchenko fail_dma_alloc:
3193caa85daSAndrew Rybchenko mcdi->state = SFC_EFX_MCDI_UNINITIALIZED;
3203caa85daSAndrew Rybchenko return rc;
3213caa85daSAndrew Rybchenko }
3223caa85daSAndrew Rybchenko
3233caa85daSAndrew Rybchenko void
sfc_efx_mcdi_fini(struct sfc_efx_mcdi * mcdi)3243caa85daSAndrew Rybchenko sfc_efx_mcdi_fini(struct sfc_efx_mcdi *mcdi)
3253caa85daSAndrew Rybchenko {
3263caa85daSAndrew Rybchenko efx_mcdi_transport_t *emtp;
3273caa85daSAndrew Rybchenko
3283caa85daSAndrew Rybchenko emtp = &mcdi->transport;
3293caa85daSAndrew Rybchenko
3303caa85daSAndrew Rybchenko rte_spinlock_lock(&mcdi->lock);
3313caa85daSAndrew Rybchenko
3323caa85daSAndrew Rybchenko SFC_EFX_ASSERT(mcdi->state == SFC_EFX_MCDI_INITIALIZED ||
3333caa85daSAndrew Rybchenko mcdi->state == SFC_EFX_MCDI_DEAD);
3343caa85daSAndrew Rybchenko mcdi->state = SFC_EFX_MCDI_UNINITIALIZED;
3353caa85daSAndrew Rybchenko
3363caa85daSAndrew Rybchenko sfc_efx_mcdi_info(mcdi, "fini MCDI");
3373caa85daSAndrew Rybchenko efx_mcdi_fini(mcdi->nic);
3383caa85daSAndrew Rybchenko memset(emtp, 0, sizeof(*emtp));
3393caa85daSAndrew Rybchenko
3403caa85daSAndrew Rybchenko rte_spinlock_unlock(&mcdi->lock);
3413caa85daSAndrew Rybchenko
3423caa85daSAndrew Rybchenko mcdi->ops->dma_free(mcdi->ops_cookie, &mcdi->mem);
3433caa85daSAndrew Rybchenko }
344