* decode-tlp.c
@ 2018-05-06 12:03 Matthew Wilcox
0 siblings, 0 replies; only message in thread
From: Matthew Wilcox @ 2018-05-06 12:03 UTC (permalink / raw)
To: linux-pci; +Cc: Martin Mares
A friend recently had his kernel spit out a message:
pcieport 0000:00:1d.0: AER: Multiple Uncorrected (Non-Fatal) error received: id=00e8
pcieport 0000:00:1d.0: PCIe Bus Error: severity=Uncorrected (Non-Fatal), type=Transaction Layer, id=00e8(Requester ID)
pcieport 0000:00:1d.0: device [8086:a298] error status/mask=00100000/00010000
pcieport 0000:00:1d.0: [20] Unsupported Request (First)
pcieport 0000:00:1d.0: TLP Header: 34000000 70000010 00000000 88468846
pcieport 0000:00:1d.0: broadcast error_detected message
pcieport 0000:00:1d.0: broadcast mmio_enabled message
pcieport 0000:00:1d.0: broadcast resume message
pcieport 0000:00:1d.0: AER: Device recovery successful
and that wasn't really quite enough information to go on. I decoded
this TLP by hand into a Latency Tolerance Reporting message, but this
is really something we should have a program for.
This solves my immediate needs; I'm sure it can be extended to be more
useful for other people. Martin, do you want to include it in pciutils?
/*
* Decode TLPs as reported by Linux's AER support
*
* Copyright (c) Matthew Wilcox 2018
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* The format of the report looks like this:
*
* TLP Header: 34000000 70000010 00000000 88468846
*
* That's a stream of bytes, *not* 32-bit words. In that example, the
* byte 0x34 is byte 0, not byte 3.
*/
#define _GNU_SOURCE
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
bool debug = false;
static int parse_header(unsigned char *header)
{
char s[256];
char *p;
int i;
p = fgets(s, 256, stdin);
if (p)
p = strstr(p, "TLP Header: ");
if (!p) {
fprintf(stderr, "Can\'t find \"TLP Header: \"\n");
return 1;
}
p += 12;
for (i = 0; i < 4; i++) {
unsigned long val = strtoul(p, NULL, 16);
header[0] = val >> 24;
header[1] = val >> 16;
header[2] = val >> 8;
header[3] = val;
p += 9;
header += 4;
}
return 0;
}
static void decode_msg(unsigned char *header)
{
unsigned char code = header[7];
if (code == 0x00)
printf("Unlock Message\n");
if (code == 0x10)
printf("Latency Tolerance Reporting Message\n");
if (code == 0x12)
printf("Optimised Buffer Flush/Fill Message\n");
if (code == 0x14)
printf("PM NAK Message\n");
if (code == 0x18)
printf("PM PME Message\n");
if (code == 0x19)
printf("PM Turn Off Message\n");
if (code == 0x1b)
printf("PM Ack Turn Off Message\n");
if (code >= 0x20 && code <= 0x27)
printf("Legacy Interrupt Message (%d)\n", code & 7);
if (code == 0x30)
printf("Error Detected (Correctable) Message\n");
if (code == 0x31)
printf("Error Detected (NonFatal) Message\n");
if (code == 0x33)
printf("Error Detected (Fatal) Message\n");
if (code >= 0x40 && code <= 0x48)
printf("Hotplug Signalling Message\n");
if (code == 0x7e || code == 0x7f)
printf("Vendor Defined (Type %d) Message\n", code - 0x7e);
if (code == 0x90)
printf("Set Slot Power Limit Message\n");
}
static void decode_type(unsigned char *header)
{
unsigned char type = *header;
if (type == 0x00 || type == 0x20)
printf("Memory Read Request\n");
if (type == 0x01 || type == 0x21)
printf("Memory Read Request Locked\n");
if (type == 0x40 || type == 0x60)
printf("Memory Write Request\n");
if (type == 0x02)
printf("I/O Read Request\n");
if (type == 0x42)
printf("I/O Write Request\n");
if (type == 0x04)
printf("Cfg0 Read Request\n");
if (type == 0x44)
printf("Cfg0 Write Request\n");
if (type == 0x05)
printf("Cfg1 Read Request\n");
if (type == 0x45)
printf("Cfg1 Write Request\n");
if (type == 0x1b)
printf("TCfg Read Request\n");
if (type == 0x5b)
printf("TCfg Write Request\n");
if (type >= 0x30 && type <= 0x37)
return decode_msg(header);
if (type >= 0x70 && type <= 0x77)
printf("Msg with Data Request\n");
if (type == 0x0a)
printf("Completion\n");
if (type == 0x4a)
printf("Completion with Data\n");
if (type == 0x0b)
printf("Completion of Locked Read without Data\n");
if (type == 0x4b)
printf("Completion of Locked Read with Data\n");
if (type == 0x4c || type == 0x6c)
printf("FetchAdd Request\n");
if (type == 0x4d || type == 0x6d)
printf("Swap Request\n");
if (type == 0x4e || type == 0x6e)
printf("CAS Request\n");
if (type >= 0x80 && type <= 0x8f) {
printf("Local TLP Prefix %d\n", type & 0xf);
return decode_type(header + 1);
}
if (type >= 0x90 && type <= 0x9f) {
printf("End-End TLP Prefix %d\n", type & 0xf);
return decode_type(header + 1);
}
}
static int usage(char **argv)
{
fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
return 1;
}
int main(int argc, char **argv)
{
unsigned char header[16];
int opt;
while ((opt = getopt(argc, argv, "d")) != -1) {
switch (opt) {
case 'd':
debug = true;
break;
default:
return usage(argv);
}
}
if (argc > optind)
return usage(argv);
if (parse_header(header))
return 1;
if (debug)
printf("TLP Header: %02x%02x%02x%02x %02x%02x%02x%02x "
"%02x%02x%02x%02x %02x%02x%02x%02x\n",
header[0], header[1], header[2], header[3],
header[4], header[5], header[6], header[7],
header[8], header[9], header[10], header[11],
header[12], header[13], header[14], header[15]);
decode_type(header);
return 0;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2018-05-06 12:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-06 12:03 decode-tlp.c Matthew Wilcox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).