diff mbox series

lspci: Slot Power Limit values above EFh

Message ID 20210403114857.n3h2wr3e3bpdsgnl@pali
State New
Headers show
Series lspci: Slot Power Limit values above EFh | expand

Commit Message

Pali Rohár April 3, 2021, 11:48 a.m. UTC
Hello!

PCI Express Base Specification rev. 3.0 has the following definition for
the Slot Power Limit Value:

=======================================================================
When the Slot Power Limit Scale field equals 00b (1.0x) and Slot Power
Limit Value exceeds EFh, the following alternative encodings are used:
  F0h = 250 W Slot Power Limit
  F1h = 275 W Slot Power Limit
  F2h = 300 W Slot Power Limit
  F3h to FFh = Reserved for Slot Power Limit values above 300 W
=======================================================================

But the function power_limit() in ls-caps.c does not handle value above
EFh according to this definition.

Here is a simple patch which fixes it for values F0h..F2h. But I'm not
sure how (reserved) values above F2h should be handled.

Comments

Matthew Wilcox (Oracle) April 3, 2021, 3:48 p.m. UTC | #1
On Sat, Apr 03, 2021 at 01:48:57PM +0200, Pali Rohár wrote:
> Hello!
> 
> PCI Express Base Specification rev. 3.0 has the following definition for
> the Slot Power Limit Value:

FWIW, it's the same in rev 5.  I had thought they might add even more
power encodings, but no.

> But the function power_limit() in ls-caps.c does not handle value above
> EFh according to this definition.
> 
> Here is a simple patch which fixes it for values F0h..F2h. But I'm not
> sure how (reserved) values above F2h should be handled.
> 
> diff --git a/ls-caps.c b/ls-caps.c
> index db56556971cb..bc1eaa15017d 100644
> --- a/ls-caps.c
> +++ b/ls-caps.c
> @@ -659,6 +659,9 @@ static int exp_downstream_port(int type)
>  static float power_limit(int value, int scale)
>  {
>    static const float scales[4] = { 1.0, 0.1, 0.01, 0.001 };
> +  static const int scale0_values[3] = { 250, 275, 300 }; /* F3h to FFh = Reserved for Slot Power Limit values above 300 W */
> +  if (scale == 0 && value >= 0xF0)
> +    value = scale0_values[(value > 0xF2 ? 0xF2 : value) & 0xF];
>    return value * scales[scale];
>  }

How about ...

  if (scale == 0)
    {
      if (value > 0xf2)
        return 0.0f/0;
      if (value >= 0xf0)
        return scale0_values[value - 0xf0];
    }

(btw, a float is the same size as an int -- 32 bits, so there's no
benefit to storing the values as an int and doing the conversion at runtime.
may as well have the compiler put the right set of bits in the binary)

in the caller:

  if ((type == PCI_EXP_TYPE_ENDPOINT) || (type == PCI_EXP_TYPE_UPSTREAM) ||
      (type == PCI_EXP_TYPE_PCI_BRIDGE))
    {
      float power = power_limit((t & PCI_EXP_DEVCAP_PWR_VAL) >> 18,
				(t & PCI_EXP_DEVCAP_PWR_SCL) >> 26));
      if (isnan(power))
        printf(" SlotPowerLimit >300W");
      else
	printf(" SlotPowerLimit %.3fW", power);
    }
diff mbox series

Patch

diff --git a/ls-caps.c b/ls-caps.c
index db56556971cb..bc1eaa15017d 100644
--- a/ls-caps.c
+++ b/ls-caps.c
@@ -659,6 +659,9 @@  static int exp_downstream_port(int type)
 static float power_limit(int value, int scale)
 {
   static const float scales[4] = { 1.0, 0.1, 0.01, 0.001 };
+  static const int scale0_values[3] = { 250, 275, 300 }; /* F3h to FFh = Reserved for Slot Power Limit values above 300 W */
+  if (scale == 0 && value >= 0xF0)
+    value = scale0_values[(value > 0xF2 ? 0xF2 : value) & 0xF];
   return value * scales[scale];
 }