]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
s390/pci: Add pci_msg debug view to PCI report
authorNiklas Schnelle <schnelle@linux.ibm.com>
Fri, 13 Dec 2024 13:47:33 +0000 (14:47 +0100)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Mon, 16 Dec 2024 15:14:27 +0000 (16:14 +0100)
Using the newly introduced debug_dump() mechanism add formatted content
of pci_debug_msg_id to the PCI report. The formatting is based on the
existing sprintf format but removes caller pointer and area index and
adds an column header. This will allow the platform to collect this log
data together with hardware errors. This sets the reverse flag such that
the newest log entries get added to the PCI report even if not all debug
log entries fit.

Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Co-developed-by: Halil Pasic <pasic@linux.ibm.com>
Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/debug.h
arch/s390/kernel/debug.c
arch/s390/pci/pci_report.c

index aa0995780c1049551dc0020a8f8f1fb0dd2699a3..6375276d94eaaeac05ef59d3083604a9a1133caa 100644 (file)
@@ -85,6 +85,10 @@ int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
                         int area, debug_entry_t *entry,
                         char *out_buf, size_t out_buf_size);
 
+#define DEBUG_SPRINTF_MAX_ARGS 10
+int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
+                           char *out_buf, size_t out_buf_size,
+                           const char *inbuf);
 struct debug_view {
        char name[DEBUG_MAX_NAME_LEN];
        debug_prolog_proc_t *prolog_proc;
index 61c393e806b2d9975a0033a252f968ab39e0b2c1..ba6b7329a10e97c67218b3fd3936e30c2d16fdc5 100644 (file)
@@ -95,9 +95,6 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
 static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
                                     char *out_buf, size_t out_buf_size,
                                     const char *in_buf);
-static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
-                                  char *out_buf, size_t out_buf_size,
-                                  const char *inbuf);
 static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
 static void debug_events_append(debug_info_t *dest, debug_info_t *src);
 
@@ -1685,8 +1682,8 @@ EXPORT_SYMBOL(debug_dflt_header_fn);
 
 #define DEBUG_SPRINTF_MAX_ARGS 10
 
-static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
-                                  char *out_buf, size_t out_buf_size, const char *inbuf)
+int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
+                           char *out_buf, size_t out_buf_size, const char *inbuf)
 {
        debug_sprintf_entry_t *curr_event = (debug_sprintf_entry_t *)inbuf;
        int num_longs, num_used_args = 0, i, rc = 0;
@@ -1723,6 +1720,7 @@ static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
 out:
        return rc;
 }
+EXPORT_SYMBOL(debug_sprintf_format_fn);
 
 /*
  * debug_init:
index 2754c9c161f5bc61d0b4a94e375da375bbb98d6a..1b494e5ecc4d848a053193f3477829c4e003f4b5 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/pci.h>
 
 #include <asm/sclp.h>
+#include <asm/debug.h>
+#include <asm/pci_debug.h>
 
 #include "pci_report.h"
 
@@ -48,6 +50,44 @@ static const char *zpci_state_str(pci_channel_state_t state)
        };
 }
 
+static int debug_log_header_fn(debug_info_t *id, struct debug_view *view,
+                              int area, debug_entry_t *entry, char *out_buf,
+                              size_t out_buf_size)
+{
+       unsigned long sec, usec;
+       unsigned int level;
+       char *except_str;
+       int rc = 0;
+
+       level = entry->level;
+       sec = entry->clock;
+       usec = do_div(sec, USEC_PER_SEC);
+
+       if (entry->exception)
+               except_str = "*";
+       else
+               except_str = "-";
+       rc += scnprintf(out_buf, out_buf_size, "%011ld:%06lu %1u %1s %04u  ",
+                       sec, usec, level, except_str,
+                       entry->cpu);
+       return rc;
+}
+
+static int debug_prolog_header(debug_info_t *id, struct debug_view *view,
+                              char *out_buf, size_t out_buf_size)
+{
+       return scnprintf(out_buf, out_buf_size, "sec:usec level except cpu  msg\n");
+}
+
+static struct debug_view debug_log_view = {
+       "pci_msg_log",
+       &debug_prolog_header,
+       &debug_log_header_fn,
+       &debug_sprintf_format_fn,
+       NULL,
+       NULL
+};
+
 /**
  * zpci_report_status - Report the status of operations on a PCI device
  * @zdev:      The PCI device for which to report status
@@ -59,6 +99,8 @@ static const char *zpci_state_str(pci_channel_state_t state)
  * Event Data mechanism. Besides the operation and status strings the report
  * also contains additional information about the device deemed useful for
  * debug such as the currently bound device driver, if any, and error state.
+ * Additionally a string representation of pci_debug_msg_id, or as much as fits,
+ * is also included.
  *
  * Return: 0 on success an error code < 0 otherwise.
  */
@@ -92,6 +134,11 @@ int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char
        buf += scnprintf(buf, end - buf, "state: %s\n",
                         (pdev) ? zpci_state_str(pdev->error_state) : "n/a");
        buf += scnprintf(buf, end - buf, "driver: %s\n", (driver) ? driver->name : "n/a");
+       ret = debug_dump(pci_debug_msg_id, &debug_log_view, buf, end - buf, true);
+       if (ret < 0)
+               pr_err("Reading PCI debug messages failed with code %d\n", ret);
+       else
+               buf += ret;
 
        report->header.version = 1;
        report->header.action = SCLP_ERRNOTIFY_AQ_INFO_LOG;