Author: np
Date: Tue May 31 23:49:13 2011
New Revision: 222551
URL: http://svn.freebsd.org/changeset/base/222551

Log:
  Firmware device log.
  
  # sysctl dev.t4nex.0.devlog
  
  MFC after:    mdf's sysctl+sbuf changes are MFC'd

Modified:
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c        Tue May 31 22:39:32 2011        
(r222550)
+++ head/sys/dev/cxgbe/t4_main.c        Tue May 31 23:49:13 2011        
(r222551)
@@ -271,6 +271,7 @@ static void setup_memwin(struct adapter 
 static int cfg_itype_and_nqueues(struct adapter *, int, int,
     struct intrs_and_queues *);
 static int prep_firmware(struct adapter *);
+static int get_devlog_params(struct adapter *, struct devlog_params *);
 static int get_capabilities(struct adapter *, struct fw_caps_config_cmd *);
 static int get_params(struct adapter *, struct fw_caps_config_cmd *);
 static void t4_set_desc(struct adapter *);
@@ -297,6 +298,7 @@ static int sysctl_holdoff_pktc_idx(SYSCT
 static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
 static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
 static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
+static int sysctl_devlog(SYSCTL_HANDLER_ARGS);
 static inline void txq_start(struct ifnet *, struct sge_txq *);
 static uint32_t fconf_to_mode(uint32_t);
 static uint32_t mode_to_fconf(uint32_t);
@@ -402,6 +404,9 @@ t4_attach(device_t dev)
        if (rc != 0)
                goto done; /* error message displayed already */
 
+       /* Read firmware devlog parameters */
+       (void) get_devlog_params(sc, &sc->params.devlog);
+
        /* Get device capabilities and select which ones we'll use */
        rc = get_capabilities(sc, &caps);
        if (rc != 0) {
@@ -1420,6 +1425,34 @@ prep_firmware(struct adapter *sc)
 }
 
 static int
+get_devlog_params(struct adapter *sc, struct devlog_params *dlog)
+{
+       struct fw_devlog_cmd devlog_cmd;
+       uint32_t meminfo;
+       int rc;
+
+       bzero(&devlog_cmd, sizeof(devlog_cmd));
+       devlog_cmd.op_to_write = htobe32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
+           F_FW_CMD_REQUEST | F_FW_CMD_READ);
+       devlog_cmd.retval_len16 = htobe32(FW_LEN16(devlog_cmd));
+       rc = -t4_wr_mbox(sc, sc->mbox, &devlog_cmd, sizeof(devlog_cmd),
+           &devlog_cmd);
+       if (rc != 0) {
+               device_printf(sc->dev,
+                   "failed to get devlog parameters: %d.\n", rc);
+               bzero(dlog, sizeof (*dlog));
+               return (rc);
+       }
+
+       meminfo = be32toh(devlog_cmd.memtype_devlog_memaddr16_devlog);
+       dlog->memtype = G_FW_DEVLOG_CMD_MEMTYPE_DEVLOG(meminfo);
+       dlog->start = G_FW_DEVLOG_CMD_MEMADDR16_DEVLOG(meminfo) << 4;
+       dlog->size = be32toh(devlog_cmd.memsize_devlog);
+
+       return (0);
+}
+
+static int
 get_capabilities(struct adapter *sc, struct fw_caps_config_cmd *caps)
 {
        int rc;
@@ -2387,6 +2420,10 @@ t4_sysctls(struct adapter *sc)
            CTLTYPE_STRING | CTLFLAG_RD, &intr_pktcount, sizeof(intr_pktcount),
            sysctl_int_array, "A", "interrupt holdoff packet counter values");
 
+       SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "devlog",
+           CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+           sysctl_devlog, "A", "device log");
+
        return (0);
 }
 
@@ -2730,6 +2767,120 @@ sysctl_handle_t4_reg64(SYSCTL_HANDLER_AR
        return (sysctl_handle_64(oidp, &val, 0, req));
 }
 
+const char *devlog_level_strings[] = {
+       [FW_DEVLOG_LEVEL_EMERG]         = "EMERG",
+       [FW_DEVLOG_LEVEL_CRIT]          = "CRIT",
+       [FW_DEVLOG_LEVEL_ERR]           = "ERR",
+       [FW_DEVLOG_LEVEL_NOTICE]        = "NOTICE",
+       [FW_DEVLOG_LEVEL_INFO]          = "INFO",
+       [FW_DEVLOG_LEVEL_DEBUG]         = "DEBUG"
+};
+
+const char *devlog_facility_strings[] = {
+       [FW_DEVLOG_FACILITY_CORE]       = "CORE",
+       [FW_DEVLOG_FACILITY_SCHED]      = "SCHED",
+       [FW_DEVLOG_FACILITY_TIMER]      = "TIMER",
+       [FW_DEVLOG_FACILITY_RES]        = "RES",
+       [FW_DEVLOG_FACILITY_HW]         = "HW",
+       [FW_DEVLOG_FACILITY_FLR]        = "FLR",
+       [FW_DEVLOG_FACILITY_DMAQ]       = "DMAQ",
+       [FW_DEVLOG_FACILITY_PHY]        = "PHY",
+       [FW_DEVLOG_FACILITY_MAC]        = "MAC",
+       [FW_DEVLOG_FACILITY_PORT]       = "PORT",
+       [FW_DEVLOG_FACILITY_VI]         = "VI",
+       [FW_DEVLOG_FACILITY_FILTER]     = "FILTER",
+       [FW_DEVLOG_FACILITY_ACL]        = "ACL",
+       [FW_DEVLOG_FACILITY_TM]         = "TM",
+       [FW_DEVLOG_FACILITY_QFC]        = "QFC",
+       [FW_DEVLOG_FACILITY_DCB]        = "DCB",
+       [FW_DEVLOG_FACILITY_ETH]        = "ETH",
+       [FW_DEVLOG_FACILITY_OFLD]       = "OFLD",
+       [FW_DEVLOG_FACILITY_RI]         = "RI",
+       [FW_DEVLOG_FACILITY_ISCSI]      = "ISCSI",
+       [FW_DEVLOG_FACILITY_FCOE]       = "FCOE",
+       [FW_DEVLOG_FACILITY_FOISCSI]    = "FOISCSI",
+       [FW_DEVLOG_FACILITY_FOFCOE]     = "FOFCOE"
+};
+
+static int
+sysctl_devlog(SYSCTL_HANDLER_ARGS)
+{
+       struct adapter *sc = arg1;
+       struct devlog_params *dparams = &sc->params.devlog;
+       struct fw_devlog_e *buf, *e;
+       int i, j, rc, nentries, first = 0;
+       struct sbuf *sb;
+       uint64_t ftstamp = UINT64_MAX;
+
+       if (dparams->start == 0)
+               return (ENXIO);
+
+       nentries = dparams->size / sizeof(struct fw_devlog_e);
+
+       buf = malloc(dparams->size, M_CXGBE, M_NOWAIT);
+       if (buf == NULL)
+               return (ENOMEM);
+
+       rc = -t4_mem_read(sc, dparams->memtype, dparams->start, dparams->size,
+           (void *)buf);
+       if (rc != 0)
+               goto done;
+
+       for (i = 0; i < nentries; i++) {
+               e = &buf[i];
+
+               if (e->timestamp == 0)
+                       break;  /* end */
+
+               e->timestamp = be64toh(e->timestamp);
+               e->seqno = be32toh(e->seqno);
+               for (j = 0; j < 8; j++)
+                       e->params[j] = be32toh(e->params[j]);
+
+               if (e->timestamp < ftstamp) {
+                       ftstamp = e->timestamp;
+                       first = i;
+               }
+       }
+
+       if (buf[first].timestamp == 0)
+               goto done;      /* nothing in the log */
+
+       rc = sysctl_wire_old_buffer(req, 0);
+       if (rc != 0)
+               goto done;
+
+       sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+       sbuf_printf(sb, "\n%10s  %15s  %8s  %8s  %s\n",
+           "Seq#", "Tstamp", "Level", "Facility", "Message");
+
+       i = first;
+       do {
+               e = &buf[i];
+               if (e->timestamp == 0)
+                       break;  /* end */
+
+               sbuf_printf(sb, "%10d  %15ju  %8s  %8s  ",
+                   e->seqno, e->timestamp,
+                   (e->level < ARRAY_SIZE(devlog_level_strings) ?
+                       devlog_level_strings[e->level] : "UNKNOWN"),
+                   (e->facility < ARRAY_SIZE(devlog_facility_strings) ?
+                       devlog_facility_strings[e->facility] : "UNKNOWN"));
+               sbuf_printf(sb, e->fmt, e->params[0], e->params[1],
+                   e->params[2], e->params[3], e->params[4],
+                   e->params[5], e->params[6], e->params[7]);
+
+               if (++i == nentries)
+                       i = 0;
+       } while (i != first);
+
+       rc = sbuf_finish(sb);
+       sbuf_delete(sb);
+done:
+       free(buf, M_CXGBE);
+       return (rc);
+}
+
 static inline void
 txq_start(struct ifnet *ifp, struct sge_txq *txq)
 {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to