Blame SOURCES/github_27a6ebd0_dev-p.patch

608733
commit 27a6ebd0cda386b1dfb7b0fffb4d8b489b391ccf
608733
Author: Dave Anderson <anderson@redhat.com>
608733
Date:   Mon Sep 24 16:33:57 2018 -0400
608733
608733
    Resurrection of the the "dev -p" option for displaying PCI device
608733
    data on Linux 2.6.26 and later kernels.  The option was deprecated
608733
    as of Linux 2.6.26, and without the patch, the option would indicate
608733
    "dev: -p option not supported or applicable on this architecture
608733
    or kernel" when running against the newer kernel versions.  PCI Bus
608733
    information will also be displayed with this patch.
608733
    (m.mizuma@jp.fujitsu.com)
608733
608733
diff --git a/defs.h b/defs.h
608733
index d6492c5..80c61ef 100644
608733
--- a/defs.h
608733
+++ b/defs.h
608733
@@ -2032,6 +2032,17 @@ struct offset_table {
608733
 	long bpf_prog_aux_user;
608733
 	long user_struct_uid;
608733
 	long idr_cur;
608733
+        long pci_dev_dev;
608733
+        long pci_dev_hdr_type;
608733
+        long pci_dev_pcie_flags_reg;
608733
+        long pci_bus_node;
608733
+        long pci_bus_devices;
608733
+        long pci_bus_dev;
608733
+        long pci_bus_children;
608733
+        long pci_bus_parent;
608733
+        long pci_bus_self;
608733
+        long device_kobj;
608733
+        long kobject_name;
608733
 };
608733
 
608733
 struct size_table {         /* stash of commonly-used sizes */
608733
diff --git a/dev.c b/dev.c
608733
index 3db898a..7ce2422 100644
608733
--- a/dev.c
608733
+++ b/dev.c
608733
@@ -24,6 +24,7 @@ static void dump_blkdevs_v3(ulong);
608733
 static ulong search_cdev_map_probes(char *, int, int, ulong *);
608733
 static ulong search_bdev_map_probes(char *, int, int, ulong *);
608733
 static void do_pci(void); 
608733
+static void do_pci2(void);
608733
 static void do_io(void);
608733
 static void do_resource_list(ulong, char *, int);
608733
 
608733
@@ -51,11 +52,23 @@ dev_init(void)
608733
         MEMBER_OFFSET_INIT(pci_dev_global_list, "pci_dev", "global_list");
608733
         MEMBER_OFFSET_INIT(pci_dev_next, "pci_dev", "next");
608733
         MEMBER_OFFSET_INIT(pci_dev_bus, "pci_dev", "bus");
608733
+	MEMBER_OFFSET_INIT(pci_dev_dev, "pci_dev", "dev");
608733
         MEMBER_OFFSET_INIT(pci_dev_devfn, "pci_dev", "devfn");
608733
         MEMBER_OFFSET_INIT(pci_dev_class, "pci_dev", "class");
608733
         MEMBER_OFFSET_INIT(pci_dev_device, "pci_dev", "device");
608733
+	MEMBER_OFFSET_INIT(pci_dev_hdr_type, "pci_dev", "hdr_type");
608733
+	MEMBER_OFFSET_INIT(pci_dev_pcie_flags_reg, "pci_dev", "pcie_flags_reg");
608733
         MEMBER_OFFSET_INIT(pci_dev_vendor, "pci_dev", "vendor");
608733
 	MEMBER_OFFSET_INIT(pci_bus_number, "pci_bus", "number");
608733
+	MEMBER_OFFSET_INIT(pci_bus_node, "pci_bus", "node");
608733
+	MEMBER_OFFSET_INIT(pci_bus_devices, "pci_bus", "devices");
608733
+	MEMBER_OFFSET_INIT(pci_bus_dev, "pci_bus", "dev");
608733
+	MEMBER_OFFSET_INIT(pci_bus_children, "pci_bus", "children");
608733
+	MEMBER_OFFSET_INIT(pci_bus_parent, "pci_bus", "parent");
608733
+	MEMBER_OFFSET_INIT(pci_bus_self, "pci_bus", "self");
608733
+
608733
+	MEMBER_OFFSET_INIT(device_kobj, "device", "kobj");
608733
+	MEMBER_OFFSET_INIT(kobject_name, "kobject", "name");
608733
 
608733
         STRUCT_SIZE_INIT(resource, "resource");
608733
 	if ((VALID_STRUCT(resource) && symbol_exists("do_resource_list")) ||
608733
@@ -114,10 +127,14 @@ cmd_dev(void)
608733
 			return;
608733
 
608733
 		case 'p':
608733
-			if (machine_type("S390X") ||
608733
-			    (THIS_KERNEL_VERSION >= LINUX(2,6,26)))
608733
+			if (machine_type("S390X"))
608733
+				option_not_supported(c);
608733
+			if (symbol_exists("pci_devices"))
608733
+				do_pci();
608733
+			else if (symbol_exists("pci_root_buses"))
608733
+				do_pci2();
608733
+			else
608733
 				option_not_supported(c);
608733
-			do_pci();
608733
 			return;
608733
 
608733
                 default:
608733
@@ -2217,6 +2234,313 @@ do_resource_list(ulong first_entry, char *resource_buf, int size)
608733
 
608733
 #endif /* USE_2_2_17_PCI_H */
608733
 
608733
+#define PCI_EXP_FLAGS_TYPE      0x00f0  /* Device/Port type */
608733
+#define  PCI_EXP_TYPE_ENDPOINT  0x0     /* Express Endpoint */
608733
+#define  PCI_EXP_TYPE_LEG_END   0x1     /* Legacy Endpoint */
608733
+#define  PCI_EXP_TYPE_ROOT_PORT 0x4     /* Root Port */
608733
+#define  PCI_EXP_TYPE_UPSTREAM  0x5     /* Upstream Port */
608733
+#define  PCI_EXP_TYPE_DOWNSTREAM 0x6    /* Downstream Port */
608733
+#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7    /* PCIe to PCI/PCI-X Bridge */
608733
+#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8   /* PCI/PCI-X to PCIe Bridge */
608733
+#define  PCI_EXP_TYPE_RC_END    0x9     /* Root Complex Integrated Endpoint */
608733
+#define  PCI_EXP_TYPE_RC_EC     0xa     /* Root Complex Event Collector */
608733
+
608733
+static void
608733
+fill_dev_name(ulong pci_dev, char *name)
608733
+{
608733
+	ulong kobj, value;
608733
+
608733
+	memset(name, 0, sizeof(*name) * BUFSIZE);
608733
+
608733
+	kobj = pci_dev + OFFSET(pci_dev_dev) + OFFSET(device_kobj);
608733
+
608733
+	readmem(kobj + OFFSET(kobject_name),
608733
+		KVADDR, &value, sizeof(void *), "kobject name",
608733
+		FAULT_ON_ERROR);
608733
+
608733
+	read_string(value, name, BUFSIZE-1);
608733
+}
608733
+
608733
+static void
608733
+fill_bus_name(ulong pci_bus, char *name)
608733
+{
608733
+	ulong kobj, value;
608733
+
608733
+	memset(name, 0, sizeof(*name) * BUFSIZE);
608733
+
608733
+	kobj = pci_bus + OFFSET(pci_bus_dev) + OFFSET(device_kobj);
608733
+
608733
+	readmem(kobj + OFFSET(kobject_name),
608733
+		KVADDR, &value, sizeof(void *), "kobject name",
608733
+		FAULT_ON_ERROR);
608733
+
608733
+	read_string(value, name, BUFSIZE-1);
608733
+}
608733
+
608733
+static void
608733
+fill_dev_id(ulong pci_dev, char *id)
608733
+{
608733
+	unsigned short device, vendor;
608733
+
608733
+	memset(id, 0, sizeof(*id) * BUFSIZE);
608733
+
608733
+	readmem(pci_dev + OFFSET(pci_dev_device),
608733
+		KVADDR, &device, sizeof(short), "pci dev device",
608733
+		FAULT_ON_ERROR);
608733
+	readmem(pci_dev + OFFSET(pci_dev_vendor), KVADDR,
608733
+		&vendor, sizeof(short), "pci dev vendor", FAULT_ON_ERROR);
608733
+
608733
+	sprintf(id, "%x:%x", vendor, device);
608733
+}
608733
+
608733
+static void
608733
+fill_dev_class(ulong pci_dev, char *c)
608733
+{
608733
+	unsigned int class;
608733
+
608733
+	memset(c, 0, sizeof(*c) * BUFSIZE);
608733
+	readmem(pci_dev + OFFSET(pci_dev_class), KVADDR,
608733
+		&class, sizeof(int), "pci class", FAULT_ON_ERROR);
608733
+
608733
+	class >>= 8;
608733
+
608733
+	sprintf(c, "%04x", class);
608733
+}
608733
+
608733
+static int
608733
+pci_pcie_type(ulong cap)
608733
+{
608733
+	return (cap & PCI_EXP_FLAGS_TYPE) >> 4;
608733
+}
608733
+
608733
+static int
608733
+pci_is_bridge(unsigned char hdr_type)
608733
+{
608733
+	return hdr_type == PCI_HEADER_TYPE_BRIDGE ||
608733
+		hdr_type == PCI_HEADER_TYPE_CARDBUS;
608733
+}
608733
+
608733
+static void
608733
+fill_pcie_type(ulong pcidev, char *t)
608733
+{
608733
+	int type, bufidx = 0;
608733
+	unsigned short pciecap;
608733
+	unsigned char hdr_type;
608733
+
608733
+	memset(t, 0, sizeof(*t) * BUFSIZE);
608733
+
608733
+	readmem(pcidev + OFFSET(pci_dev_hdr_type), KVADDR, &hdr_type,
608733
+		sizeof(char), "pci dev hdr_type", FAULT_ON_ERROR);
608733
+
608733
+	if (!VALID_MEMBER(pci_dev_pcie_flags_reg))
608733
+		goto bridge_chk;
608733
+
608733
+	readmem(pcidev + OFFSET(pci_dev_pcie_flags_reg), KVADDR, &pciecap,
608733
+		sizeof(unsigned short), "pci dev pcie_flags_reg", FAULT_ON_ERROR);
608733
+
608733
+	type = pci_pcie_type(pciecap);
608733
+
608733
+	if (type == PCI_EXP_TYPE_ENDPOINT)
608733
+		bufidx = sprintf(t, "ENDPOINT");
608733
+	else if (type == PCI_EXP_TYPE_LEG_END)
608733
+		bufidx = sprintf(t, "LEG_END");
608733
+	else if (type == PCI_EXP_TYPE_ROOT_PORT)
608733
+		bufidx = sprintf(t, "ROOT_PORT");
608733
+	else if (type == PCI_EXP_TYPE_UPSTREAM)
608733
+		bufidx = sprintf(t, "UPSTREAM");
608733
+	else if (type == PCI_EXP_TYPE_DOWNSTREAM)
608733
+		bufidx = sprintf(t, "DOWNSTREAM");
608733
+	else if (type == PCI_EXP_TYPE_PCI_BRIDGE)
608733
+		bufidx = sprintf(t, "PCI_BRIDGE");
608733
+	else if (type == PCI_EXP_TYPE_PCIE_BRIDGE)
608733
+		bufidx = sprintf(t, "PCIE_BRIDGE");
608733
+	else if (type == PCI_EXP_TYPE_RC_END)
608733
+		bufidx = sprintf(t, "RC_END");
608733
+	else if (type == PCI_EXP_TYPE_RC_EC)
608733
+		bufidx = sprintf(t, "RC_EC");
608733
+
608733
+bridge_chk:
608733
+	if (pci_is_bridge(hdr_type))
608733
+		sprintf(t + bufidx, " [BRIDGE]");
608733
+}
608733
+
608733
+static void
608733
+walk_devices(ulong pci_bus)
608733
+{
608733
+	struct list_data list_data, *ld;
608733
+	int devcnt, i;
608733
+	ulong *devlist, self;
608733
+	char name[BUFSIZE], class[BUFSIZE], id[BUFSIZE], type[BUFSIZE];
608733
+	char pcidev_hdr[BUFSIZE];
608733
+	char buf1[BUFSIZE];
608733
+	char buf2[BUFSIZE];
608733
+	char buf3[BUFSIZE];
608733
+	char buf4[BUFSIZE];
608733
+	char buf5[BUFSIZE];
608733
+
608733
+	ld = &list_data;
608733
+
608733
+	BZERO(ld, sizeof(struct list_data));
608733
+
608733
+	readmem(pci_bus + OFFSET(pci_bus_devices), KVADDR,
608733
+		&ld->start, sizeof(void *), "pci bus devices",
608733
+		FAULT_ON_ERROR);
608733
+
608733
+	if (VALID_MEMBER(pci_dev_pcie_flags_reg))
608733
+		snprintf(pcidev_hdr, sizeof(pcidev_hdr), "%s %s %s %s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, CENTER, "PCI DEV"),
608733
+			mkstring(buf2, strlen("0000:00:00.0"), CENTER, "DO:BU:SL.FN"),
608733
+			mkstring(buf3, strlen("0000") + 2, CENTER, "CLASS"),
608733
+			mkstring(buf4, strlen("0000:0000"), CENTER, "PCI_ID"),
608733
+			mkstring(buf5, 10, CENTER, "TYPE"));
608733
+	else
608733
+		snprintf(pcidev_hdr, sizeof(pcidev_hdr), "%s %s %s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, CENTER, "PCI DEV"),
608733
+			mkstring(buf2, strlen("0000:00:00.0"), CENTER, "DO:BU:SL.FN"),
608733
+			mkstring(buf3, strlen("0000") + 2, CENTER, "CLASS"),
608733
+			mkstring(buf4, strlen("0000:0000"), CENTER, "PCI_ID"));
608733
+
608733
+	fprintf(fp, "  %s", pcidev_hdr);
608733
+
608733
+	readmem(pci_bus + OFFSET(pci_bus_self), KVADDR, &self,
608733
+		sizeof(void *), "pci bus self", FAULT_ON_ERROR);
608733
+	if (self) {
608733
+		fill_dev_name(self, name);
608733
+		fill_dev_class(self, class);
608733
+		fill_dev_id(self, id);
608733
+		fill_pcie_type(self, type);
608733
+		fprintf(fp, "  %s %s %s %s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
608733
+			MKSTR(self)),
608733
+			mkstring(buf2, strlen("0000:00:00.0"), CENTER, name),
608733
+			mkstring(buf3, strlen("0000") + 2, CENTER, class),
608733
+			mkstring(buf4, strlen("0000:0000"), CENTER, id),
608733
+			mkstring(buf5, 10, CENTER, type));
608733
+	}
608733
+
608733
+	if (ld->start == (pci_bus + OFFSET(pci_bus_devices)))
608733
+		return;
608733
+
608733
+	ld->end = pci_bus + OFFSET(pci_bus_devices);
608733
+	hq_open();
608733
+	devcnt = do_list(ld);
608733
+	devlist = (ulong *)GETBUF(devcnt * sizeof(ulong));
608733
+	devcnt = retrieve_list(devlist, devcnt);
608733
+	hq_close();
608733
+
608733
+	for (i = 0; i < devcnt; i++) {
608733
+		fill_dev_name(devlist[i], name);
608733
+		fill_dev_class(devlist[i], class);
608733
+		fill_dev_id(devlist[i], id);
608733
+		fill_pcie_type(devlist[i], type);
608733
+		fprintf(fp, "  %s %s %s %s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
608733
+			MKSTR(devlist[i])),
608733
+			mkstring(buf2, strlen("0000:00:00.0"), CENTER, name),
608733
+			mkstring(buf3, strlen("0000") + 2, CENTER, class),
608733
+			mkstring(buf4, strlen("0000:0000"), CENTER, id),
608733
+			mkstring(buf5, 10, CENTER, type));
608733
+	}
608733
+	FREEBUF(devlist);
608733
+}
608733
+
608733
+static void
608733
+walk_buses(ulong pci_bus)
608733
+{
608733
+	struct list_data list_data, *ld;
608733
+	int buscnt, i;
608733
+	ulong *buslist, parent;
608733
+	char pcibus_hdr[BUFSIZE];
608733
+	char buf1[BUFSIZE];
608733
+	char buf2[BUFSIZE];
608733
+
608733
+	ld = &list_data;
608733
+
608733
+	BZERO(ld, sizeof(struct list_data));
608733
+
608733
+	readmem(pci_bus + OFFSET(pci_bus_children), KVADDR,
608733
+		&ld->start, sizeof(void *), "pci bus children",
608733
+		FAULT_ON_ERROR);
608733
+
608733
+	if (ld->start == (pci_bus + OFFSET(pci_bus_children)))
608733
+		return;
608733
+
608733
+	ld->end = pci_bus + OFFSET(pci_bus_children);
608733
+	hq_open();
608733
+	buscnt = do_list(ld);
608733
+	buslist = (ulong *)GETBUF(buscnt * sizeof(ulong));
608733
+	buscnt = retrieve_list(buslist, buscnt);
608733
+	hq_close();
608733
+
608733
+	snprintf(pcibus_hdr, sizeof(pcibus_hdr), "%s %s\n",
608733
+		mkstring(buf1, VADDR_PRLEN, CENTER, "PCI BUS"),
608733
+		mkstring(buf2, VADDR_PRLEN, CENTER, "PARENT BUS"));
608733
+
608733
+	for (i = 0; i < buscnt; i++) {
608733
+		readmem(buslist[i] + OFFSET(pci_bus_parent), KVADDR, &parent,
608733
+			sizeof(void *), "pci bus parent", FAULT_ON_ERROR);
608733
+
608733
+		fprintf(fp, "  %s", pcibus_hdr);
608733
+
608733
+		fprintf(fp, "  %s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
608733
+			MKSTR(buslist[i])),
608733
+			mkstring(buf2, VADDR_PRLEN, LJUST|LONG_HEX,
608733
+			MKSTR(parent)));
608733
+		walk_devices(buslist[i]);
608733
+		fprintf(fp, "\n");
608733
+		walk_buses(buslist[i]);
608733
+	}
608733
+	FREEBUF(buslist);
608733
+}
608733
+
608733
+static void
608733
+do_pci2(void)
608733
+{
608733
+	struct list_data list_data, *ld;
608733
+	int rootbuscnt, i;
608733
+	ulong *rootbuslist;
608733
+	unsigned long pci_root_bus_addr = symbol_value("pci_root_buses");
608733
+	char name[BUFSIZE];
608733
+	char pcirootbus_hdr[BUFSIZE];
608733
+	char buf1[BUFSIZE];
608733
+	char buf2[BUFSIZE];
608733
+
608733
+	ld = &list_data;
608733
+	BZERO(ld, sizeof(struct list_data));
608733
+
608733
+	get_symbol_data("pci_root_buses", sizeof(void *), &ld->start);
608733
+
608733
+	if (ld->start == pci_root_bus_addr)
608733
+		error(FATAL, "no PCI devices found on this system.\n");
608733
+
608733
+	ld->end = pci_root_bus_addr;
608733
+
608733
+	hq_open();
608733
+	rootbuscnt = do_list(ld);
608733
+	rootbuslist = (ulong *)GETBUF(rootbuscnt * sizeof(ulong));
608733
+	rootbuscnt = retrieve_list(rootbuslist, rootbuscnt);
608733
+	hq_close();
608733
+
608733
+	snprintf(pcirootbus_hdr, sizeof(pcirootbus_hdr), "%s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, CENTER, "ROOT BUS"),
608733
+			mkstring(buf2, strlen("0000:00"), CENTER, "BUSNAME"));
608733
+
608733
+	for (i = 0; i < rootbuscnt; i++) {
608733
+		fprintf(fp, "%s", pcirootbus_hdr);
608733
+		fill_bus_name(rootbuslist[i], name);
608733
+		fprintf(fp, "%s %s\n",
608733
+			mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
608733
+			MKSTR(rootbuslist[i])),
608733
+			mkstring(buf2, strlen("0000:00"), CENTER, name));
608733
+		 walk_devices(rootbuslist[i]);
608733
+		 walk_buses(rootbuslist[i]);
608733
+
608733
+		fprintf(fp, "\n");
608733
+	}
608733
+	FREEBUF(rootbuslist);
608733
+}
608733
+
608733
 static void
608733
 do_pci(void)
608733
 {
608733
@@ -2230,9 +2554,6 @@ do_pci(void)
608733
 	char 		  buf2[BUFSIZE];
608733
 	char 		  buf3[BUFSIZE];
608733
 
608733
-	if (!symbol_exists("pci_devices"))
608733
-		error(FATAL, "no PCI devices found on this system.\n");
608733
-
608733
 	BZERO(&pcilist_data, sizeof(struct list_data));
608733
 
608733
 	if (VALID_MEMBER(pci_dev_global_list)) {