Merge branch 'pci/err'
authorBjorn Helgaas <bhelgaas@google.com>
Tue, 15 Dec 2020 21:11:06 +0000 (15:11 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 15 Dec 2020 21:11:06 +0000 (15:11 -0600)
- Stop writing AER Capability when we don't own it (Sean V Kelley)

- Bind RCEC devices to the Port driver (Qiuxu Zhuo)

- Cache the RCEC RA Capability offset (Sean V Kelley)

- Add pci_walk_bridge() (Sean V Kelley)

- Clear AER status only when we control AER (Sean V Kelley)

- Recover from RCEC AER errors (Sean V Kelley)

- Add pcie_link_rcec() to associate RCiEPs with RCECs (Sean V Kelley)

- Recover from RCiEP AER errors (Sean V Kelley)

- Add pcie_walk_rcec() for RCEC AER handling (Sean V Kelley)

- Add pcie_walk_rcec() for RCEC PME handling (Sean V Kelley)

- Add RCEC AER error injection support (Qiuxu Zhuo)

* pci/err:
  PCI/AER: Add RCEC AER error injection support
  PCI/PME: Add pcie_walk_rcec() to RCEC PME handling
  PCI/AER: Add pcie_walk_rcec() to RCEC AER handling
  PCI/ERR: Recover from RCiEP AER errors
  PCI/ERR: Add pcie_link_rcec() to associate RCiEPs
  PCI/ERR: Recover from RCEC AER errors
  PCI/ERR: Clear AER status only when we control AER
  PCI/ERR: Add pci_walk_bridge() to pcie_do_recovery()
  PCI/ERR: Avoid negated conditional for clarity
  PCI/ERR: Use "bridge" for clarity in pcie_do_recovery()
  PCI/ERR: Simplify by computing pci_pcie_type() once
  PCI/ERR: Simplify by using pci_upstream_bridge()
  PCI/ERR: Rename reset_link() to reset_subordinates()
  PCI/ERR: Cache RCEC EA Capability offset in pci_init_capabilities()
  PCI/ERR: Bind RCEC devices to the Root Port driver
  PCI/AER: Write AER Capability only when we control it

1  2 
drivers/pci/pci.h
drivers/pci/probe.c
include/linux/pci.h
include/uapi/linux/pci_regs.h

diff --combined drivers/pci/pci.h
@@@ -294,8 -294,7 +294,8 @@@ void pci_bus_put(struct pci_bus *bus)
  
  /* PCIe link information from Link Capabilities 2 */
  #define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
 -      ((lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
 +      ((lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
 +       (lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
         (lnkcap2) & PCI_EXP_LNKCAP2_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
         (lnkcap2) & PCI_EXP_LNKCAP2_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
         (lnkcap2) & PCI_EXP_LNKCAP2_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
  
  /* PCIe speed to Mb/s reduced by encoding overhead */
  #define PCIE_SPEED2MBS_ENC(speed) \
 -      ((speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \
 +      ((speed) == PCIE_SPEED_64_0GT ? 64000*128/130 : \
 +       (speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \
         (speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \
         (speed) == PCIE_SPEED_8_0GT  ?  8000*128/130 : \
         (speed) == PCIE_SPEED_5_0GT  ?  5000*8/10 : \
@@@ -450,6 -448,15 +450,15 @@@ int aer_get_device_error_info(struct pc
  void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
  #endif        /* CONFIG_PCIEAER */
  
+ #ifdef CONFIG_PCIEPORTBUS
+ /* Cached RCEC Endpoint Association */
+ struct rcec_ea {
+       u8              nextbusn;
+       u8              lastbusn;
+       u32             bitmap;
+ };
+ #endif
  #ifdef CONFIG_PCIE_DPC
  void pci_save_dpc_state(struct pci_dev *dev);
  void pci_restore_dpc_state(struct pci_dev *dev);
@@@ -462,6 -469,22 +471,22 @@@ static inline void pci_restore_dpc_stat
  static inline void pci_dpc_init(struct pci_dev *pdev) {}
  #endif
  
+ #ifdef CONFIG_PCIEPORTBUS
+ void pci_rcec_init(struct pci_dev *dev);
+ void pci_rcec_exit(struct pci_dev *dev);
+ void pcie_link_rcec(struct pci_dev *rcec);
+ void pcie_walk_rcec(struct pci_dev *rcec,
+                   int (*cb)(struct pci_dev *, void *),
+                   void *userdata);
+ #else
+ static inline void pci_rcec_init(struct pci_dev *dev) {}
+ static inline void pci_rcec_exit(struct pci_dev *dev) {}
+ static inline void pcie_link_rcec(struct pci_dev *rcec) {}
+ static inline void pcie_walk_rcec(struct pci_dev *rcec,
+                                 int (*cb)(struct pci_dev *, void *),
+                                 void *userdata) {}
+ #endif
  #ifdef CONFIG_PCI_ATS
  /* Address Translation Service */
  void pci_ats_init(struct pci_dev *dev);
@@@ -557,8 -580,8 +582,8 @@@ static inline int pci_dev_specific_disa
  
  /* PCI error reporting and recovery */
  pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
-                       pci_channel_state_t state,
-                       pci_ers_result_t (*reset_link)(struct pci_dev *pdev));
+               pci_channel_state_t state,
+               pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
  
  bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
  #ifdef CONFIG_PCIEASPM
@@@ -566,15 -589,11 +591,15 @@@ void pcie_aspm_init_link_state(struct p
  void pcie_aspm_exit_link_state(struct pci_dev *pdev);
  void pcie_aspm_pm_state_change(struct pci_dev *pdev);
  void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
 +void pci_save_aspm_l1ss_state(struct pci_dev *dev);
 +void pci_restore_aspm_l1ss_state(struct pci_dev *dev);
  #else
  static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { }
  static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { }
  static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { }
  static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { }
 +static inline void pci_save_aspm_l1ss_state(struct pci_dev *dev) { }
 +static inline void pci_restore_aspm_l1ss_state(struct pci_dev *dev) { }
  #endif
  
  #ifdef CONFIG_PCIE_ECRC
diff --combined drivers/pci/probe.c
@@@ -677,7 -677,7 +677,7 @@@ const unsigned char pcie_link_speed[] 
        PCIE_SPEED_8_0GT,               /* 3 */
        PCIE_SPEED_16_0GT,              /* 4 */
        PCIE_SPEED_32_0GT,              /* 5 */
 -      PCI_SPEED_UNKNOWN,              /* 6 */
 +      PCIE_SPEED_64_0GT,              /* 6 */
        PCI_SPEED_UNKNOWN,              /* 7 */
        PCI_SPEED_UNKNOWN,              /* 8 */
        PCI_SPEED_UNKNOWN,              /* 9 */
@@@ -719,7 -719,6 +719,7 @@@ const char *pci_speed_string(enum pci_b
            "8.0 GT/s PCIe",            /* 0x16 */
            "16.0 GT/s PCIe",           /* 0x17 */
            "32.0 GT/s PCIe",           /* 0x18 */
 +          "64.0 GT/s PCIe",           /* 0x19 */
        };
  
        if (speed < ARRAY_SIZE(speed_strings))
@@@ -2217,6 -2216,7 +2217,7 @@@ static void pci_configure_device(struc
  static void pci_release_capabilities(struct pci_dev *dev)
  {
        pci_aer_exit(dev);
+       pci_rcec_exit(dev);
        pci_vpd_release(dev);
        pci_iov_release(dev);
        pci_free_cap_save_buffers(dev);
@@@ -2416,6 -2416,7 +2417,7 @@@ static void pci_init_capabilities(struc
        pci_ptm_init(dev);              /* Precision Time Measurement */
        pci_aer_init(dev);              /* Advanced Error Reporting */
        pci_dpc_init(dev);              /* Downstream Port Containment */
+       pci_rcec_init(dev);             /* Root Complex Event Collector */
  
        pcie_report_downtraining(dev);
  
diff --combined include/linux/pci.h
@@@ -281,7 -281,6 +281,7 @@@ enum pci_bus_speed 
        PCIE_SPEED_8_0GT                = 0x16,
        PCIE_SPEED_16_0GT               = 0x17,
        PCIE_SPEED_32_0GT               = 0x18,
 +      PCIE_SPEED_64_0GT               = 0x19,
        PCI_SPEED_UNKNOWN               = 0xff,
  };
  
@@@ -305,6 -304,7 +305,7 @@@ struct pcie_link_state
  struct pci_vpd;
  struct pci_sriov;
  struct pci_p2pdma;
+ struct rcec_ea;
  
  /* The pci_dev structure describes PCI devices */
  struct pci_dev {
  #ifdef CONFIG_PCIEAER
        u16             aer_cap;        /* AER capability offset */
        struct aer_stats *aer_stats;    /* AER stats for this device */
+ #endif
+ #ifdef CONFIG_PCIEPORTBUS
+       struct rcec_ea  *rcec_ea;       /* RCEC cached endpoint association */
+       struct pci_dev  *rcec;          /* Associated RCEC device */
  #endif
        u8              pcie_cap;       /* PCIe capability offset */
        u8              msi_cap;        /* MSI capability offset */
        struct pcie_link_state  *link_state;    /* ASPM link state */
        unsigned int    ltr_path:1;     /* Latency Tolerance Reporting
                                           supported from root to here */
 -      int             l1ss;           /* L1SS Capability pointer */
 +      u16             l1ss;           /* L1SS Capability pointer */
  #endif
        unsigned int    eetlp_prefix_path:1;    /* End-to-End TLP Prefix */
  
@@@ -1064,13 -1068,12 +1069,13 @@@ void pci_sort_breadthfirst(void)
  
  /* Generic PCI functions exported to card drivers */
  
 -int pci_find_capability(struct pci_dev *dev, int cap);
 -int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
 -int pci_find_ext_capability(struct pci_dev *dev, int cap);
 -int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
 -int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
 -int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 +u8 pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
 +u8 pci_find_capability(struct pci_dev *dev, int cap);
 +u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
 +u8 pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
 +u8 pci_find_next_ht_capability(struct pci_dev *dev, u8 pos, int ht_cap);
 +u16 pci_find_ext_capability(struct pci_dev *dev, int cap);
 +u16 pci_find_next_ext_capability(struct pci_dev *dev, u16 pos, int cap);
  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
  
  u64 pci_get_dsn(struct pci_dev *dev);
@@@ -1281,6 -1284,7 +1286,6 @@@ void set_pcie_port_type(struct pci_dev 
  void set_pcie_hotplug_bridge(struct pci_dev *pdev);
  
  /* Functions for PCI Hotplug drivers to use */
 -int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
  unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
  unsigned int pci_rescan_bus(struct pci_bus *bus);
  void pci_lock_rescan_remove(void);
@@@ -1720,7 -1724,7 +1725,7 @@@ static inline int __pci_register_driver
  static inline int pci_register_driver(struct pci_driver *drv)
  { return 0; }
  static inline void pci_unregister_driver(struct pci_driver *drv) { }
 -static inline int pci_find_capability(struct pci_dev *dev, int cap)
 +static inline u8 pci_find_capability(struct pci_dev *dev, int cap)
  { return 0; }
  static inline int pci_find_next_capability(struct pci_dev *dev, u8 post,
                                           int cap)
  #define  PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */
  #define  PCI_EXP_LNKCAP_SLS_16_0GB 0x00000004 /* LNKCAP2 SLS Vector bit 3 */
  #define  PCI_EXP_LNKCAP_SLS_32_0GB 0x00000005 /* LNKCAP2 SLS Vector bit 4 */
 +#define  PCI_EXP_LNKCAP_SLS_64_0GB 0x00000006 /* LNKCAP2 SLS Vector bit 5 */
  #define  PCI_EXP_LNKCAP_MLW   0x000003f0 /* Maximum Link Width */
  #define  PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
  #define  PCI_EXP_LNKCAP_ASPM_L0S 0x00000400 /* ASPM L0s Support */
  #define  PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
  #define  PCI_EXP_LNKSTA_CLS_16_0GB 0x0004 /* Current Link Speed 16.0GT/s */
  #define  PCI_EXP_LNKSTA_CLS_32_0GB 0x0005 /* Current Link Speed 32.0GT/s */
 +#define  PCI_EXP_LNKSTA_CLS_64_0GB 0x0006 /* Current Link Speed 64.0GT/s */
  #define  PCI_EXP_LNKSTA_NLW   0x03f0  /* Negotiated Link Width */
  #define  PCI_EXP_LNKSTA_NLW_X1        0x0010  /* Current Link Width x1 */
  #define  PCI_EXP_LNKSTA_NLW_X2        0x0020  /* Current Link Width x2 */
  #define  PCI_EXP_LNKCAP2_SLS_8_0GB    0x00000008 /* Supported Speed 8GT/s */
  #define  PCI_EXP_LNKCAP2_SLS_16_0GB   0x00000010 /* Supported Speed 16GT/s */
  #define  PCI_EXP_LNKCAP2_SLS_32_0GB   0x00000020 /* Supported Speed 32GT/s */
 +#define  PCI_EXP_LNKCAP2_SLS_64_0GB   0x00000040 /* Supported Speed 64GT/s */
  #define  PCI_EXP_LNKCAP2_CROSSLINK    0x00000100 /* Crosslink supported */
  #define PCI_EXP_LNKCTL2               48      /* Link Control 2 */
  #define  PCI_EXP_LNKCTL2_TLS          0x000f
  #define  PCI_EXP_LNKCTL2_TLS_8_0GT    0x0003 /* Supported Speed 8GT/s */
  #define  PCI_EXP_LNKCTL2_TLS_16_0GT   0x0004 /* Supported Speed 16GT/s */
  #define  PCI_EXP_LNKCTL2_TLS_32_0GT   0x0005 /* Supported Speed 32GT/s */
 +#define  PCI_EXP_LNKCTL2_TLS_64_0GT   0x0006 /* Supported Speed 64GT/s */
  #define  PCI_EXP_LNKCTL2_ENTER_COMP   0x0010 /* Enter Compliance */
  #define  PCI_EXP_LNKCTL2_TX_MARGIN    0x0380 /* Transmit Margin */
  #define  PCI_EXP_LNKCTL2_HASD         0x0020 /* HW Autonomous Speed Disable */
  #define  PCI_PWR_CAP_BUDGET(x)        ((x) & 1)       /* Included in system budget */
  #define PCI_EXT_CAP_PWR_SIZEOF        16
  
+ /* Root Complex Event Collector Endpoint Association  */
+ #define PCI_RCEC_RCIEP_BITMAP 4       /* Associated Bitmap for RCiEPs */
+ #define PCI_RCEC_BUSN         8       /* RCEC Associated Bus Numbers */
+ #define  PCI_RCEC_BUSN_REG_VER        0x02    /* Least version with BUSN present */
+ #define  PCI_RCEC_BUSN_NEXT(x)        (((x) >> 8) & 0xff)
+ #define  PCI_RCEC_BUSN_LAST(x)        (((x) >> 16) & 0xff)
  /* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
  #define PCI_VNDR_HEADER               4       /* Vendor-Specific Header */
  #define  PCI_VNDR_HEADER_ID(x)        ((x) & 0xffff)