Re: [PATCH] PCI ASPM: more detailed ASPM configuration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Shaohua Li wrote:
> On Fri, Jun 19, 2009 at 05:28:41AM +0800, Jesse Barnes wrote:
>> On Thu, 21 May 2009 11:10:06 +0900
>> Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> wrote:
>>
>>> Hi,
>>>
>>> This patch changes ASPM driver to enable more detailed ASPM
>>> configuration. With this patch,
>>>
>>> - ASPM can be enabled partially in the hierarchy.
>>> - L0s can be managed for each direction (upstream direction and
>>>   downstream direction) of the link.
> Well, these are nice features, but what kind of machine does you test?
> Does it have several level hierarchy? The most powerful system I saw
> just has two levels, which sounds not worth adding partial aspm.

Thank you very much for comments.

I think it is useful also for the system that doesn't have so
many levels of hierarchy, such as mobile systems. Here is "lspci -t"
output on my environment with some comments. My system also has
just two levels, but with the patch, upstream L0s is enabled on the
link 0000:15.00.0 (switch downstream port) to 0000:16:00.0 (endpoint)
in powersave mode. 

[kanesige@localhost develop]$ /sbin/lspci -t
-[0000:00]-+-00.0
           +-01.0-[0000:04-13]--
                                                                     L0s(UP) enabled
                                                                     L0s(DW) enabled(*)
           +-02.0-[0000:14-29]--+-00.0-[0000:15-28]--+-00.0-[0000:16]----00.0
           |                    |                    +-01.0-[0000:18-27]--
           											       
                                                                     L0s(DW) enabled(*)
           |                    |                    \-02.0-[0000:28]--+-00.0
           |                    |                                      \-00.1
           |                    \-00.3-[0000:29]--
           +-03.0-[0000:2a-2d]----00.0-[0000:2b-2d]--+-02.0-[0000:2c]--+-00.0
           |                                         |                 \-00.1
           											  	                                                                     L0s(DW) enabled(*)
           |                                         \-04.0-[0000:2d]----00.0
           +-04.0-[0000:2e-4f]----00.0-[0000:2f-4f]--+-02.0-[0000:30-3f]--+-00.0
           |                                         |                    \-00.1
           |                                         \-04.0-[0000:40-4f]--+-00.0
           |                                                              \-00.1
           +-06.0-[0000:51-73]----00.0-[0000:52-73]--+-02.0-[0000:54-63]--+-00.0
           |                                         |                    \-00.1
           |                                         \-04.0-[0000:64-73]----00.0-[0000:65]--+-08.0
           |                                                                                \-08.1
           +-10.0
           +-10.1
           +-10.2
           +-10.3
           +-11.0
           +-11.3
           +-13.0
           +-15.0
           +-16.0
           +-1c.0-[0000:75-83]--
           +-1d.0
           +-1d.1
           +-1d.2
           +-1d.3
           +-1d.7
           +-1e.0-[0000:84]--
           +-1f.0
           +-1f.2
           \-1f.3

(*) Downstream direction L0s is enabled but it has no effect because
    Downstream direction L0s is disabled on its upstream links.

> The second feature seems more reasonable.

I think I should have implement those features as separate patches.
I'll do it if needed.

> ASPM is still broken in a lot of devices, before we go far, we need to make
> sure the feature is really required.

I tested that pci_disable_link_state() first, actually :)

By the way, I've tested the patches with debugging patch that give us
the information like below through /proc. I'm attaching it for your
information.

LINK (addr: ffff88083c5fc840, pdev: ffff88083c604240, name: 0000:00:02.0)
  root: ffff88083c5fc840, parent (null)
  ASPM enabled: L0sUP-, L0sDW-, L1-
  ASPM capable: L0sUP-, L0sDW+, L1-
  ASPM support: L0sUP+, L0sDW+, L1-
  ASPM disable: L0sUP+, L0sDW+, L1+
  ASPM default: L0sUP-, L0sDW-, L1-
  ASPM latency: L0sUP 5000, L0sDW 256, L1 65000
  ClockPM: capable 0, enabled 0, default 0

    LINK (addr: ffff88083c5fcb58, pdev: ffff88083c572968, name: 0000:15:02.0)
      root: ffff88083c5fc840, parent ffff88083c5fc840
      ASPM enabled: L0sUP-, L0sDW+, L1-
      ASPM capable: L0sUP-, L0sDW+, L1-
      ASPM support: L0sUP-, L0sDW+, L1-
      ASPM disable: L0sUP-, L0sDW-, L1-
      ASPM default: L0sUP-, L0sDW-, L1-
      ASPM latency: L0sUP 256, L0sDW 128, L1 65000
      ClockPM: capable 0, enabled 0, default 0
      EP[0000:28:00.0] accept l0s 512, l1 64000
      EP[0000:28:00.1] accept l0s 512, l1 64000

    LINK (addr: ffff88083c5fca50, pdev: ffff88083c5718d8, name: 0000:15:00.0)
      root: ffff88083c5fc840, parent ffff88083c5fc840
      ASPM enabled: L0sUP+, L0sDW+, L1-
      ASPM capable: L0sUP+, L0sDW+, L1-
      ASPM support: L0sUP+, L0sDW+, L1-
      ASPM disable: L0sUP-, L0sDW-, L1-
      ASPM default: L0sUP-, L0sDW-, L1-
      ASPM latency: L0sUP 5000, L0sDW 2048, L1 65000
      ClockPM: capable 0, enabled 0, default 0
      EP[0000:16:00.0] accept l0s 4294967295, l1 4294967295

Thanks,
Kenji Kaneshige


 drivers/pci/pcie/aspm.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

Index: 20090521/drivers/pci/pcie/aspm.c
===================================================================
--- 20090521.orig/drivers/pci/pcie/aspm.c
+++ 20090521/drivers/pci/pcie/aspm.c
@@ -19,6 +19,8 @@
 #include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/pci-aspm.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "../pci.h"
 
 #ifdef MODULE_PARAM_PREFIX
@@ -859,6 +861,117 @@ void pcie_aspm_remove_sysfs_dev_files(st
 		sysfs_remove_file_from_group(&pdev->dev.kobj,
 			&dev_attr_clk_ctl.attr, power_group);
 }
+
+static void show_link(struct seq_file *p,
+		      struct pcie_link_state *link, int depth)
+{
+	struct pci_dev *child, *parent = link->pdev;
+	struct pci_bus *linkbus = parent->subordinate;
+	struct pcie_link_state *childlink;
+	int indent = depth * 4;
+
+	seq_printf(p,
+		   "%*sLINK (addr: %p, pdev: %p, name: %s)\n"
+		   "%*s  root: %p, parent %p\n"
+		   "%*s  ASPM enabled: L0sUP%c, L0sDW%c, L1%c\n"
+		   "%*s  ASPM capable: L0sUP%c, L0sDW%c, L1%c\n"
+		   "%*s  ASPM support: L0sUP%c, L0sDW%c, L1%c\n"
+		   "%*s  ASPM disable: L0sUP%c, L0sDW%c, L1%c\n"
+		   "%*s  ASPM default: L0sUP%c, L0sDW%c, L1%c\n"
+		   "%*s  ASPM latency: L0sUP %u, L0sDW %u, L1 %u\n"
+		   "%*s  ClockPM: capable %u, enabled %u, default %u\n",
+		   indent, "", link, parent, pci_name(parent),
+		   indent, "", link->root, link->parent,
+		   indent, "",
+		   (link->aspm_enabled & ASPM_STATE_L0S_UP) ? '+' : '-',
+		   (link->aspm_enabled & ASPM_STATE_L0S_DW) ? '+' : '-',
+		   (link->aspm_enabled & ASPM_STATE_L1)     ? '+' : '-',
+		   indent, "",
+		   (link->aspm_capable & ASPM_STATE_L0S_UP) ? '+' : '-',
+		   (link->aspm_capable & ASPM_STATE_L0S_DW) ? '+' : '-',
+		   (link->aspm_capable & ASPM_STATE_L1)     ? '+' : '-',
+		   indent, "",
+		   (link->aspm_support & ASPM_STATE_L0S_UP) ? '+' : '-',
+		   (link->aspm_support & ASPM_STATE_L0S_DW) ? '+' : '-',
+		   (link->aspm_support & ASPM_STATE_L1)     ? '+' : '-',
+		   indent, "",
+		   (link->aspm_disable & ASPM_STATE_L0S_UP) ? '+' : '-',
+		   (link->aspm_disable & ASPM_STATE_L0S_DW) ? '+' : '-',
+		   (link->aspm_disable & ASPM_STATE_L1)     ? '+' : '-',
+		   indent, "",
+		   (link->aspm_default & ASPM_STATE_L0S_UP) ? '+' : '-',
+		   (link->aspm_default & ASPM_STATE_L0S_DW) ? '+' : '-',
+		   (link->aspm_default & ASPM_STATE_L1)     ? '+' : '-',
+		   indent, "",
+		   link->latency_up.l0s, link->latency_dw.l0s,
+		   max_t(u32, link->latency_up.l1, link->latency_dw.l1),
+		   indent, "", link->clkpm_capable,
+		   link->clkpm_enabled, link->clkpm_default);
+	list_for_each_entry(child, &linkbus->devices, bus_list) {
+		int func = PCI_FUNC(child->devfn);
+		if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) &&
+		    (child->pcie_type != PCI_EXP_TYPE_LEG_END))
+			continue;
+		seq_printf(p, "%*s  EP[%s] accept l0s %u, l1 %u\n",
+			   indent, "", pci_name(child),
+			   link->acceptable[func].l0s,
+			   link->acceptable[func].l1);
+	}
+	seq_printf(p, "\n");
+
+	list_for_each_entry(childlink, &link->children, link)
+		show_link(p, childlink, (depth + 1));
+}
+
+static int show_pcie_link_state(struct seq_file *p, void *v)
+{
+	struct pcie_link_state *link;
+
+	mutex_lock(&aspm_lock);
+	list_for_each_entry(link, &link_list, sibling) {
+		if (!link->parent)
+			show_link(p, link, 0);
+	}
+	mutex_unlock(&aspm_lock);
+	return 0;
+}
+
+static int pcie_link_state_open(struct inode *inode, struct file *file)
+{
+	size_t size = 128 * 1024;
+	char *buf;
+	int res;
+	struct seq_file *m;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	res = single_open(file, show_pcie_link_state, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+
+static const struct file_operations pcie_link_state_operations = {
+	.open		= pcie_link_state_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int pcie_aspm_init_proc(void)
+{
+	if (aspm_disabled)
+		return 0;
+	proc_create("pcie_link_state", 0, NULL, &pcie_link_state_operations);
+	return 0;
+}
+late_initcall(pcie_aspm_init_proc);
 #endif
 
 static int __init pcie_aspm_disable(char *str)


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux