X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_mcdi.c;h=dede33688a2422bd372f30021d67d43e07da0167;hb=c696cc659337c682f1055e646600ab3dca733b0e;hp=3bed2e0b13241b7712924c8a24394c08cfcb6d78;hpb=3e3b2e4ceaed54071a0113812a54e28ca0634ee3;p=dpdk.git diff --git a/drivers/net/sfc/sfc_mcdi.c b/drivers/net/sfc/sfc_mcdi.c index 3bed2e0b13..dede33688a 100644 --- a/drivers/net/sfc/sfc_mcdi.c +++ b/drivers/net/sfc/sfc_mcdi.c @@ -1,30 +1,10 @@ -/*- - * Copyright (c) 2016 Solarflare Communications Inc. +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2016-2018 Solarflare Communications Inc. * All rights reserved. * * This software was jointly developed between OKTET Labs (under contract * for Solarflare) and Solarflare Communications, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include @@ -35,7 +15,7 @@ #include "sfc.h" #include "sfc_log.h" -#include "sfc_kvargs.h" +#include "sfc_ev.h" #define SFC_MCDI_POLL_INTERVAL_MIN_US 10 /* 10us in 1us units */ #define SFC_MCDI_POLL_INTERVAL_MAX_US (US_PER_S / 10) /* 100ms in 1us units */ @@ -49,8 +29,22 @@ sfc_mcdi_timeout(struct sfc_adapter *sa) sfc_panic(sa, "MCDI timeout handling is not implemented\n"); } +static inline boolean_t +sfc_mcdi_proxy_event_available(struct sfc_adapter *sa) +{ + struct sfc_mcdi *mcdi = &sa->mcdi; + + mcdi->proxy_handle = 0; + mcdi->proxy_result = ETIMEDOUT; + sfc_ev_mgmt_qpoll(sa); + if (mcdi->proxy_result != ETIMEDOUT) + return B_TRUE; + + return B_FALSE; +} + static void -sfc_mcdi_poll(struct sfc_adapter *sa) +sfc_mcdi_poll(struct sfc_adapter *sa, boolean_t proxy) { efx_nic_t *enp; unsigned int delay_total; @@ -62,13 +56,20 @@ sfc_mcdi_poll(struct sfc_adapter *sa) enp = sa->nic; do { - if (efx_mcdi_request_poll(enp)) + boolean_t poll_completed; + + poll_completed = (proxy) ? sfc_mcdi_proxy_event_available(sa) : + efx_mcdi_request_poll(enp); + if (poll_completed) return; if (delay_total > SFC_MCDI_WATCHDOG_INTERVAL_US) { - aborted = efx_mcdi_request_abort(enp); - SFC_ASSERT(aborted); - sfc_mcdi_timeout(sa); + if (!proxy) { + aborted = efx_mcdi_request_abort(enp); + SFC_ASSERT(aborted); + sfc_mcdi_timeout(sa); + } + return; } @@ -90,13 +91,42 @@ sfc_mcdi_execute(void *arg, efx_mcdi_req_t *emrp) { struct sfc_adapter *sa = (struct sfc_adapter *)arg; struct sfc_mcdi *mcdi = &sa->mcdi; + uint32_t proxy_handle; rte_spinlock_lock(&mcdi->lock); SFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED); efx_mcdi_request_start(sa->nic, emrp, B_FALSE); - sfc_mcdi_poll(sa); + sfc_mcdi_poll(sa, B_FALSE); + + if (efx_mcdi_get_proxy_handle(sa->nic, emrp, &proxy_handle) == 0) { + /* + * Authorization is required for the MCDI request; + * wait for an MCDI proxy response event to bring + * a non-zero proxy handle (should be the same as + * the value obtained above) and operation status + */ + sfc_mcdi_poll(sa, B_TRUE); + + if ((mcdi->proxy_handle != 0) && + (mcdi->proxy_handle != proxy_handle)) { + sfc_err(sa, "Unexpected MCDI proxy event"); + emrp->emr_rc = EFAULT; + } else if (mcdi->proxy_result == 0) { + /* + * Authorization succeeded; re-issue the original + * request and poll for an ordinary MCDI response + */ + efx_mcdi_request_start(sa->nic, emrp, B_FALSE); + sfc_mcdi_poll(sa, B_FALSE); + } else { + emrp->emr_rc = mcdi->proxy_result; + sfc_err(sa, "MCDI proxy authorization failed " + "(handle=%08x, result=%d)", + proxy_handle, mcdi->proxy_result); + } + } rte_spinlock_unlock(&mcdi->lock); } @@ -123,7 +153,7 @@ sfc_mcdi_exception(void *arg, efx_mcdi_exception_t eme) (eme == EFX_MCDI_EXCEPTION_MC_REBOOT) ? "REBOOT" : (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT) ? "BADASSERT" : "UNKNOWN"); - sfc_panic(sa, "MCDI exceptions handling is not implemented\n"); + sfc_schedule_restart(sa); } #define SFC_MCDI_LOG_BUF_SIZE 128 @@ -145,7 +175,7 @@ sfc_mcdi_do_log(const struct sfc_adapter *sa, * at the end which is required by netlogdecode. */ buffer[position] = '\0'; - sfc_info(sa, "%s \\", buffer); + sfc_log_mcdi(sa, "%s \\", buffer); /* Preserve prefix for the next log message */ position = pfxsize; } @@ -167,10 +197,17 @@ sfc_mcdi_logger(void *arg, efx_log_msg_t type, size_t pfxsize; size_t start; - if (!sa->mcdi.logging) + /* + * Unlike the other cases, MCDI logging implies more onerous work + * needed to produce a message. If the dynamic log level prevents + * the end result from being printed, the CPU time will be wasted. + * + * To avoid wasting time, the actual level is examined in advance. + */ + if (rte_log_get_level(sa->mcdi.logtype) < (int)SFC_LOG_LEVEL_MCDI) return; - /* The format including prefix added by sfc_info() is the format + /* The format including prefix added by sfc_log_mcdi() is the format * consumed by the Solarflare netlogdecode tool. */ pfxsize = snprintf(buffer, sizeof(buffer), "MCDI RPC %s:", @@ -181,10 +218,20 @@ sfc_mcdi_logger(void *arg, efx_log_msg_t type, start = sfc_mcdi_do_log(sa, buffer, data, data_size, pfxsize, start); if (start != pfxsize) { buffer[start] = '\0'; - sfc_info(sa, "%s", buffer); + sfc_log_mcdi(sa, "%s", buffer); } } +static void +sfc_mcdi_ev_proxy_response(void *arg, uint32_t handle, efx_rc_t result) +{ + struct sfc_adapter *sa = (struct sfc_adapter *)arg; + struct sfc_mcdi *mcdi = &sa->mcdi; + + mcdi->proxy_handle = handle; + mcdi->proxy_result = result; +} + int sfc_mcdi_init(struct sfc_adapter *sa) { @@ -209,11 +256,9 @@ sfc_mcdi_init(struct sfc_adapter *sa) if (rc != 0) goto fail_dma_alloc; - /* Convert negative error to positive used in the driver */ - rc = sfc_kvargs_process(sa, SFC_KVARG_MCDI_LOGGING, - sfc_kvarg_bool_handler, &mcdi->logging); - if (rc != 0) - goto fail_kvargs_process; + mcdi->logtype = sfc_register_logtype(&sa->priv.shared->pci_addr, + SFC_LOGTYPE_MCDI_STR, + RTE_LOG_NOTICE); emtp = &mcdi->transport; emtp->emt_context = sa; @@ -222,6 +267,7 @@ sfc_mcdi_init(struct sfc_adapter *sa) emtp->emt_ev_cpl = sfc_mcdi_ev_cpl; emtp->emt_exception = sfc_mcdi_exception; emtp->emt_logger = sfc_mcdi_logger; + emtp->emt_ev_proxy_response = sfc_mcdi_ev_proxy_response; sfc_log_init(sa, "init MCDI"); rc = efx_mcdi_init(sa->nic, emtp); @@ -232,8 +278,6 @@ sfc_mcdi_init(struct sfc_adapter *sa) fail_mcdi_init: memset(emtp, 0, sizeof(*emtp)); - -fail_kvargs_process: sfc_dma_free(sa, &mcdi->mem); fail_dma_alloc: