pciutils: decoding extended capabilities with variable size based on lane count
diff mbox series

Message ID 917430A7-9813-4F54-A135-BB965950EE27@me.com
State Not Applicable
Headers show
Series
  • pciutils: decoding extended capabilities with variable size based on lane count
Related show

Commit Message

return.0 July 13, 2019, 10:39 a.m. UTC
I was working on providing a patch for decoding some of the 4.0 extended capabilities, but hit a snag.  The Lane Margining and the 16GT/S Physical Layer Extended Capabilities only have valid data for the number of lanes (up to 32) currently configured. It would be nice to know the width during decode without having to re-read and decode, but instead grab it from the device structure.  

Would you support making a change to the device structure like the following:



Is this the best way to handle this or would you prefer a different way?

Thank you,
John

Comments

Martin Mareš July 13, 2019, 12:58 p.m. UTC | #1
Hello!

> I was working on providing a patch for decoding some of the 4.0 extended
> capabilities, but hit a snag.  The Lane Margining and the 16GT/S Physical
> Layer Extended Capabilities only have valid data for the number of lanes (up
> to 32) currently configured. It would be nice to know the width during
> decode without having to re-read and decode, but instead grab it from the
> device structure.

Generally, I like this approach. It however introduces a dependency between
parsing of different capabilities – so far, we did not assume any concrete
order. I think that assuming that extended caps are parsed after all
non-extended ones is OK, but please document it somewhere. Perhaps you can
add a comment to the newly added struct fields explaining when are these set
and when they are used.

				Have a nice fortnight

Patch
diff mbox series

diff --git a/lspci.h b/lspci.h
index fefee52..69912fc 100644
--- a/lspci.h
+++ b/lspci.h
@@ -42,6 +42,10 @@  struct device {
  unsigned int config_cached, config_bufsize;
  byte *config;                                /* Cached configuration space data */
  byte *present;                       /* Maps which configuration bytes are present */
+  int cap_speed;
+  int cap_width;
+  int sta_speed;
+  int sta_width;
};

extern struct device *first_dev;


Then within cap_express_link, the value would be stored to the device structure rather than a local variable.

diff --git a/ls-caps.c b/ls-caps.c
index 88964ce..bf600e8 100644
--- a/ls-caps.c
+++ b/ls-caps.c
@@ -781,16 +781,16 @@  static const char *aspm_enabled(int code)

static void cap_express_link(struct device *d, int where, int type)
{
-  u32 t, aspm, cap_speed, cap_width, sta_speed, sta_width;
+  u32 t, aspm;
  u16 w;

  t = get_conf_long(d, where + PCI_EXP_LNKCAP);
  aspm = (t & PCI_EXP_LNKCAP_ASPM) >> 10;
-  cap_speed = t & PCI_EXP_LNKCAP_SPEED;
-  cap_width = (t & PCI_EXP_LNKCAP_WIDTH) >> 4;
+  d->cap_speed = t & PCI_EXP_LNKCAP_SPEED;
+  d->cap_width = (t & PCI_EXP_LNKCAP_WIDTH) >> 4;
  printf("\t\tLnkCap:\tPort #%d, Speed %s, Width x%d, ASPM %s",
	t >> 24,
-	link_speed(cap_speed), cap_width,
+	link_speed(d->cap_speed), d->cap_width,
	aspm_support(aspm));
  if (aspm)
    {
@@ -824,13 +824,13 @@  static void cap_express_link(struct device *d, int where, int type)
	FLAG(w, PCI_EXP_LNKCTL_AUTBWIE));

  w = get_conf_word(d, where + PCI_EXP_LNKSTA);
-  sta_speed = w & PCI_EXP_LNKSTA_SPEED;
-  sta_width = (w & PCI_EXP_LNKSTA_WIDTH) >> 4;
+  d->sta_speed = w & PCI_EXP_LNKSTA_SPEED;
+  d->sta_width = (w & PCI_EXP_LNKSTA_WIDTH) >> 4;
  printf("\t\tLnkSta:\tSpeed %s (%s), Width x%d (%s)\n",
-	link_speed(sta_speed),
-	link_compare(sta_speed, cap_speed),
-	sta_width,
-	link_compare(sta_width, cap_width));
+	link_speed(d->sta_speed),
+	link_compare(d->sta_speed, d->cap_speed),
+	d->sta_width,
+	link_compare(d->sta_width, d->cap_width));
  printf("\t\t\tTrErr%c Train%c SlotClk%c DLActive%c BWMgmt%c ABWMgmt%c\n",
	FLAG(w, PCI_EXP_LNKSTA_TR_ERR),
	FLAG(w, PCI_EXP_LNKSTA_TRAIN),