net/sfc: implement MCDI logging callback
authorAndrew Rybchenko <arybchenko@solarflare.com>
Thu, 15 Dec 2016 12:50:52 +0000 (12:50 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:40:50 +0000 (19:40 +0100)
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andrew Lee <alee@solarflare.com>
Reviewed-by: Robert Stonehouse <rstonehouse@solarflare.com>
doc/guides/nics/sfc_efx.rst
drivers/net/sfc/efsys.h
drivers/net/sfc/sfc.h
drivers/net/sfc/sfc_ethdev.c
drivers/net/sfc/sfc_kvargs.c
drivers/net/sfc/sfc_kvargs.h
drivers/net/sfc/sfc_mcdi.c

index aadd775..2cca287 100644 (file)
@@ -155,3 +155,9 @@ boolean parameters value.
 - ``debug_init`` [bool] (default **n**)
 
   Enable extra logging during device intialization and startup.
+
+- ``mcdi_logging`` [bool] (default **n**)
+
+  Enable extra logging of the communication with the NIC's management CPU.
+  The logging is done using RTE_LOG() with INFO level and PMD type.
+  The format is consumed by the Solarflare netlogdecode cross-platform tool.
index e4d5035..d48eb4c 100644 (file)
@@ -175,7 +175,7 @@ prefetch_read_once(const volatile void *addr)
 
 /* MCDI is required for SFN7xxx and SFN8xx */
 #define EFSYS_OPT_MCDI 1
-#define EFSYS_OPT_MCDI_LOGGING 0
+#define EFSYS_OPT_MCDI_LOGGING 1
 #define EFSYS_OPT_MCDI_PROXY_AUTH 0
 
 #define EFSYS_OPT_MAC_STATS 0
index c6bb5e8..568a40e 100644 (file)
@@ -110,6 +110,7 @@ struct sfc_mcdi {
        efsys_mem_t                     mem;
        enum sfc_mcdi_state             state;
        efx_mcdi_transport_t            transport;
+       bool                            logging;
 };
 
 struct sfc_intr {
index 68717a6..bb79c9c 100644 (file)
@@ -463,4 +463,5 @@ static struct eth_driver sfc_efx_pmd = {
 RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv);
 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map);
 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx,
+       SFC_KVARG_MCDI_LOGGING "=" SFC_KVARG_VALUES_BOOL " "
        SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL);
index fe8a1fe..5496b12 100644 (file)
@@ -43,6 +43,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa)
        struct rte_devargs *devargs = eth_dev->device->devargs;
        const char **params = (const char *[]){
                SFC_KVARG_DEBUG_INIT,
+               SFC_KVARG_MCDI_LOGGING,
                NULL,
        };
 
index 0b53963..ffce851 100644 (file)
@@ -40,6 +40,8 @@ extern "C" {
 
 #define SFC_KVARG_DEBUG_INIT           "debug_init"
 
+#define SFC_KVARG_MCDI_LOGGING         "mcdi_logging"
+
 struct sfc_adapter;
 
 int sfc_kvargs_parse(struct sfc_adapter *sa);
index 9ba28e1..3bed2e0 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "sfc.h"
 #include "sfc_log.h"
+#include "sfc_kvargs.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 */
@@ -125,6 +126,65 @@ sfc_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
        sfc_panic(sa, "MCDI exceptions handling is not implemented\n");
 }
 
+#define SFC_MCDI_LOG_BUF_SIZE  128
+
+static size_t
+sfc_mcdi_do_log(const struct sfc_adapter *sa,
+               char *buffer, void *data, size_t data_size,
+               size_t pfxsize, size_t position)
+{
+       uint32_t *words = data;
+       /* Space separator plus 2 characters per byte */
+       const size_t word_str_space = 1 + 2 * sizeof(*words);
+       size_t i;
+
+       for (i = 0; i < data_size; i += sizeof(*words)) {
+               if (position + word_str_space >=
+                   SFC_MCDI_LOG_BUF_SIZE) {
+                       /* Flush at SFC_MCDI_LOG_BUF_SIZE with backslash
+                        * at the end which is required by netlogdecode.
+                        */
+                       buffer[position] = '\0';
+                       sfc_info(sa, "%s \\", buffer);
+                       /* Preserve prefix for the next log message */
+                       position = pfxsize;
+               }
+               position += snprintf(buffer + position,
+                                    SFC_MCDI_LOG_BUF_SIZE - position,
+                                    " %08x", *words);
+               words++;
+       }
+       return position;
+}
+
+static void
+sfc_mcdi_logger(void *arg, efx_log_msg_t type,
+               void *header, size_t header_size,
+               void *data, size_t data_size)
+{
+       struct sfc_adapter *sa = (struct sfc_adapter *)arg;
+       char buffer[SFC_MCDI_LOG_BUF_SIZE];
+       size_t pfxsize;
+       size_t start;
+
+       if (!sa->mcdi.logging)
+               return;
+
+       /* The format including prefix added by sfc_info() is the format
+        * consumed by the Solarflare netlogdecode tool.
+        */
+       pfxsize = snprintf(buffer, sizeof(buffer), "MCDI RPC %s:",
+                          type == EFX_LOG_MCDI_REQUEST ? "REQ" :
+                          type == EFX_LOG_MCDI_RESPONSE ? "RESP" : "???");
+       start = sfc_mcdi_do_log(sa, buffer, header, header_size,
+                               pfxsize, pfxsize);
+       start = sfc_mcdi_do_log(sa, buffer, data, data_size, pfxsize, start);
+       if (start != pfxsize) {
+               buffer[start] = '\0';
+               sfc_info(sa, "%s", buffer);
+       }
+}
+
 int
 sfc_mcdi_init(struct sfc_adapter *sa)
 {
@@ -149,12 +209,19 @@ 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;
+
        emtp = &mcdi->transport;
        emtp->emt_context = sa;
        emtp->emt_dma_mem = &mcdi->mem;
        emtp->emt_execute = sfc_mcdi_execute;
        emtp->emt_ev_cpl = sfc_mcdi_ev_cpl;
        emtp->emt_exception = sfc_mcdi_exception;
+       emtp->emt_logger = sfc_mcdi_logger;
 
        sfc_log_init(sa, "init MCDI");
        rc = efx_mcdi_init(sa->nic, emtp);
@@ -165,6 +232,8 @@ 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: