svn commit: r345103 - head/sys/compat/linuxkpi/common/include/linux

Conrad Meyer cem at freebsd.org
Wed Mar 13 20:37:03 UTC 2019


Hi,

A lot of the information about PCIe devices is read by PCI probe and
cached on the (BSD) device.  You could access it out of
device_get_ivars(bsddev)->cfg.pcie and avoid the MMIO latency.

On Wed, Mar 13, 2019 at 12:15 PM Hans Petter Selasky
<hselasky at freebsd.org> wrote:
> +static inline enum pci_bus_speed
> +pcie_get_speed_cap(struct pci_dev *dev)
> +{
> +       device_t root;
> +       uint32_t lnkcap, lnkcap2;
> +       int error, pos;
> +
> +       root = device_get_parent(dev->dev.bsddev);
> +       if (root == NULL)
> +               return (PCI_SPEED_UNKNOWN);
> +       root = device_get_parent(root);
> +       if (root == NULL)
> +               return (PCI_SPEED_UNKNOWN);
> +       root = device_get_parent(root);
> +       if (root == NULL)
> +               return (PCI_SPEED_UNKNOWN);

What is this mechanism trying to accomplish?  It seems incredibly
fragile.  Looking for pci0? pcib0?

> +       if ((error = pci_find_cap(root, PCIY_EXPRESS, &pos)) != 0)
> +               return (PCI_SPEED_UNKNOWN);

Cached as non-zero cfg.pcie.pcie_location value in ivars.

> +       lnkcap2 = pci_read_config(root, pos + PCIER_LINK_CAP2, 4);

This one we don't cache, unfortunately, but could.  Ditto LINK_CAP
below.  Usually "pos + PCIEfoo" is spelled "pcie_read_config(...,
PCIEfoo...)."

> +
> +       if (lnkcap2) {  /* PCIe r3.0-compliant */
> +               if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
> +                       return (PCIE_SPEED_2_5GT);

Seems like these definitions would be better suited as native
PCIEM_LINK_CAP2_foo definitions in pcireg.h

> +               if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
> +                       return (PCIE_SPEED_5_0GT);
> +               if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
> +                       return (PCIE_SPEED_8_0GT);
> +               if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
> +                       return (PCIE_SPEED_16_0GT);
> +       } else {        /* pre-r3.0 */
> +               lnkcap = pci_read_config(root, pos + PCIER_LINK_CAP, 4);
> +               if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
> +                       return (PCIE_SPEED_2_5GT);
> +               if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
> +                       return (PCIE_SPEED_5_0GT);
> +               if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
> +                       return (PCIE_SPEED_8_0GT);
> +               if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
> +                       return (PCIE_SPEED_16_0GT);
> +       }
> +       return (PCI_SPEED_UNKNOWN);
> +}
> +
> +static inline enum pcie_link_width
> +pcie_get_width_cap(struct pci_dev *dev)
> +{
> +       uint32_t lnkcap;
> +
> +       pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);

Better spelled as PCIER_LINK_CAP.

> +       if (lnkcap)
> +               return ((lnkcap & PCI_EXP_LNKCAP_MLW) >> 4);

And PCIEM_LINK_CAP_MAX_WIDTH.

> +
> +       return (PCIE_LNK_WIDTH_UNKNOWN);
>  }
>
>  #endif /* _LINUX_PCI_H_ */
>

Best,
Conrad


More information about the svn-src-all mailing list