diff mbox

parse the power budgeting table

Message ID 1312619222-10093-1-git-send-email-martin.peres@ensi-bourges.fr
State New, archived
Headers show

Commit Message

martin.peres@ensi-bourges.fr Aug. 6, 2011, 8:27 a.m. UTC
From: Martin Peres <martin.peres@ensi-bourges.fr>

---
 Makefile   |    2 +-
 ls-ecaps.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 80 insertions(+), 2 deletions(-)

Comments

martin.peres@ensi-bourges.fr Aug. 6, 2011, 8:04 p.m. UTC | #1
Le 06/08/2011 12:55, Matthew Wilcox a écrit :
> On Sat, Aug 06, 2011 at 10:27:02AM +0200, martin.peres@ensi-bourges.fr wrote:
>> +  i = 0;
>> +  do {
>> +    pci_write_byte(d->dev, where + PCI_PWR_DSR, i);
>> +
>> +    w = pci_read_word(d->dev, where + PCI_PWR_DATA);
>
> The problem with this is that it's racy.  If a device driver is accessing
> the power budget capability at the same time lspci accesses it, the
> driver could get the wrong numbers.  (lspci could too, but that's way
> less important).
Right, this is racy.
>
> Now, we don't have any device drivers accessing this capability
> yet.  If we can persuade the first one who tries it to use some
> centralised API to access it, we can throw in the necessary calls to
> pci_block_user_cfg_access().
That's a good proposition. Another one, quite simple, is to read this 
table before the device's driver is loaded. Then, we would need to give 
this information back to the userspace and kernel.

What do you think about it?

>
> It'd be great if we can get started on that ... does anyone have
> a device driver in mind that could benefit from reading the power
> budgeting capability?
>
I'm working on Nouveau, on power management. I was reading some docs on 
power budgetting and decided to have a look at what my cards would 
advertise. This is why I wrote this patch for lspci.

I still need to make more sense of the values read by my card but this 
is another matter.

Anyway, I don't see any reason to read the PB table from the nouveau 
device driver. IMHO, I think this information is for end-users. This 
doesn't mean we shouldn't fix this issue.
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Makefile b/Makefile
index d67f7d6..4a82d0d 100644
--- a/Makefile
+++ b/Makefile
@@ -86,7 +86,7 @@  example: example.o lib/$(PCILIB)
 example.o: example.c $(PCIINC)
 
 %: %.o
-	$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
+	$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -lm -o $@
 
 %.8 %.7: %.man
 	M=`echo $(DATE) | sed 's/-01-/-January-/;s/-02-/-February-/;s/-03-/-March-/;s/-04-/-April-/;s/-05-/-May-/;s/-06-/-June-/;s/-07-/-July-/;s/-08-/-August-/;s/-09-/-September-/;s/-10-/-October-/;s/-11-/-November-/;s/-12-/-December-/;s/\(.*\)-\(.*\)-\(.*\)/\3 \2 \1/'` ; sed <$< >$@ "s/@TODAY@/$$M/;s/@VERSION@/pciutils-$(VERSION)/;s#@IDSDIR@#$(IDSDIR)#"
diff --git a/ls-ecaps.c b/ls-ecaps.c
index cd342aa..0eb4f82 100644
--- a/ls-ecaps.c
+++ b/ls-ecaps.c
@@ -8,6 +8,7 @@ 
 
 #include <stdio.h>
 #include <string.h>
+#include <math.h>
 
 #include "lspci.h"
 
@@ -448,6 +449,83 @@  cap_evendor(struct device *d, int where)
     BITS(hdr, 20, 12));
 }
 
+static void
+cap_pb(struct device *d, int where)
+{
+  u16 i, w;
+  u16 base, scale, pm_sub, pm_state, type, rail;
+  const char *type_s, *rail_s;
+
+  printf("Power Budgeting\n");
+  if (verbose < 2)
+    return;
+
+  i = 0;
+  do {
+    pci_write_byte(d->dev, where + PCI_PWR_DSR, i);
+
+    w = pci_read_word(d->dev, where + PCI_PWR_DATA);
+    
+    if (!w)
+      return;
+    
+    base = PCI_PWR_DATA_BASE(w);
+    scale = PCI_PWR_DATA_SCALE(w);
+    pm_sub = PCI_PWR_DATA_PM_SUB(w);
+    pm_state = PCI_PWR_DATA_PM_STATE(w);
+    type = PCI_PWR_DATA_TYPE(w);
+    rail = PCI_PWR_DATA_RAIL(w);
+
+    printf("\t\tPB%i: ", i);
+    printf("Power %.3fW, ", base / pow(10, scale));
+
+    printf("%s PM_Sub, ", pm_sub == 0 ? "Default":"Custom");
+    printf("D%i PM_State, ", pm_state);
+    switch(type) {
+      case 0:
+        type_s = "PME_Aux";
+        break;
+      case 1:
+        type_s = "Auxiliary";
+        break;
+      case 2:
+        type_s = "Idle";
+        break;
+      case 3:
+        type_s = "Sustained";
+        break;
+      case 7:
+        type_s = "Maximum";
+        break;
+      default:
+        type_s = "Reserved";
+        break;
+    }
+    printf("%s Type, ", type_s);
+
+    switch(rail) {
+      case 0:
+        rail_s = "12V";
+        break;
+      case 1:
+        rail_s = "3.3V";
+        break;
+      case 2:
+        rail_s = "1.8V";
+        break;
+      case 7:
+        rail_s = "Thermal";
+        break;
+      default:
+        rail_s = "Reserved";
+        break;
+    }
+    printf("%s Power Rail\n", rail_s);
+
+    i++;
+  } while(1);
+}
+
 void
 show_ext_caps(struct device *d)
 {
@@ -488,7 +566,7 @@  show_ext_caps(struct device *d)
 	    cap_dsn(d, where);
 	    break;
 	  case PCI_EXT_CAP_ID_PB:
-	    printf("Power Budgeting <?>\n");
+	    cap_pb(d, where);
 	    break;
 	  case PCI_EXT_CAP_ID_RCLINK:
 	    cap_rclink(d, where);