Re: [PATCH 1/3] ACPI/APEI: Add hest_parse_pcie_aer()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





在 2023/12/7 0:35, Rafael J. Wysocki 写道:
On Wed, Nov 15, 2023 at 10:16 AM LeoLiu-oc <LeoLiu-oc@xxxxxxxxxxx> wrote:

From: leoliu-oc <leoliu-oc@xxxxxxxxxxx>

The purpose of the function apei_hest_parse_aer() is used to parse and
extract register value from HEST PCIe AER structures.

Signed-off-by: leoliu-oc <leoliu-oc@xxxxxxxxxxx>
---
  drivers/acpi/apei/hest.c | 77 ++++++++++++++++++++++++++++++++++++++--
  include/acpi/actbl1.h    |  7 ++++
  include/acpi/apei.h      |  8 +++++
  3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 6aef1ee5e1bd..7fb797fdc1b1 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -22,6 +22,7 @@
  #include <linux/kdebug.h>
  #include <linux/highmem.h>
  #include <linux/io.h>
+#include <linux/pci.h>
  #include <linux/platform_device.h>
  #include <acpi/apei.h>
  #include <acpi/ghes.h>
@@ -86,9 +87,81 @@ static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
         return len;
  };

-typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data);
+#ifdef CONFIG_ACPI_APEI
+static bool hest_match_pci_devfn(struct acpi_hest_aer_common *p,
+                               struct pci_dev *dev)
+{
+       return ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(dev->bus) &&
+               ACPI_HEST_BUS(p->bus) == dev->bus->number &&
+               p->device == PCI_SLOT(dev->devfn) &&
+               p->function == PCI_FUNC(dev->devfn);
+}
+
+static bool hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr,
+                               struct pci_dev *dev)
+{
+       u16 hest_type = hest_hdr->type;
+       u8 pcie_type = pci_pcie_type(dev);
+       struct acpi_hest_aer_common *common;
+
+       common = (struct acpi_hest_aer_common *)(hest_hdr + 1);
+
+       switch (hest_type) {
+       case ACPI_HEST_TYPE_AER_ROOT_PORT:
+               if (pcie_type != PCI_EXP_TYPE_ROOT_PORT)
+                       return false;
+       break;
+       case ACPI_HEST_TYPE_AER_ENDPOINT:
+               if (pcie_type != PCI_EXP_TYPE_ENDPOINT)
+                       return false;
+       break;
+       case ACPI_HEST_TYPE_AER_BRIDGE:
+               if (pcie_type != PCI_EXP_TYPE_PCI_BRIDGE &&
+                   pcie_type != PCI_EXP_TYPE_PCIE_BRIDGE)
+                       return false;
+       break;
+       default:
+               return false;
+       break;
+       }
+
+       if (common->flags & ACPI_HEST_GLOBAL)
+               return true;
+
+       if (hest_match_pci_devfn(common, dev))
+               return true;
+
+       return false;
+}
+
+int hest_parse_pcie_aer(struct acpi_hest_header *hest_hdr, void *data)
+{
+       struct hest_parse_aer_info *info = data;
+
+       if (!hest_source_is_pcie_aer(hest_hdr, info->pci_dev))
+               return 0;
+
+       switch (hest_hdr->type) {
+       case ACPI_HEST_TYPE_AER_ROOT_PORT:
+               info->hest_aer_root_port = (struct acpi_hest_aer_root *)hest_hdr;
+               return 1;
+       break;
+       case ACPI_HEST_TYPE_AER_ENDPOINT:
+               info->hest_aer_endpoint = (struct acpi_hest_aer *)hest_hdr;
+               return 1;
+       break;
+       case ACPI_HEST_TYPE_AER_BRIDGE:
+               info->hest_aer_bridge = (struct acpi_hest_aer_bridge *)hest_hdr;
+               return 1;
+       break;
+       default:
+               return 0;
+       break;
+       }
+}
+#endif

-static int apei_hest_parse(apei_hest_func_t func, void *data)
+int apei_hest_parse(apei_hest_func_t func, void *data)
  {
         struct acpi_hest_header *hest_hdr;
         int i, rc, len;
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index a33375e055ad..90c27dc5325f 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h

This is an ACPICA header and it cannot be modified just like this.

The way to do that is to submit a pull request with the desired change
to the upstream ACPICA project on GitHub and add a Link tag pointing
to the upstream PR to the corresponding Linux patch.  Then, the Linux
patch can only be applied after the corresponding upstream PR has been
merged.

Thanks!

the data structure "hest_parse_aer_info" is added to file actbl1.h, it is not necessary to put this data structure in file actbl1.h. In the next version, I will move this data structure to another file.

Yours sincerely,
Leoliu-oc

@@ -1629,6 +1629,13 @@ struct acpi_hest_generic_status {
         u32 error_severity;
  };

+struct hest_parse_aer_info {
+       struct pci_dev *pci_dev;
+       struct acpi_hest_aer *hest_aer_endpoint;
+       struct acpi_hest_aer_root *hest_aer_root_port;
+       struct acpi_hest_aer_bridge *hest_aer_bridge;
+};
+
  /* Values for block_status flags above */

  #define ACPI_HEST_UNCORRECTABLE             (1)
diff --git a/include/acpi/apei.h b/include/acpi/apei.h
index dc60f7db5524..d12e6b6c4546 100644
--- a/include/acpi/apei.h
+++ b/include/acpi/apei.h
@@ -33,10 +33,18 @@ void __init acpi_ghes_init(void);
  static inline void acpi_ghes_init(void) { }
  #endif

+typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data);
+int apei_hest_parse(apei_hest_func_t func, void *data);
+
  #ifdef CONFIG_ACPI_APEI
  void __init acpi_hest_init(void);
+int hest_parse_pcie_aer(struct acpi_hest_header *hest_hdr, void *data);
  #else
  static inline void acpi_hest_init(void) { }
+static inline int hest_parse_pcie_aer(struct acpi_hest_header *hest_hdr, void *data)
+{
+       return 0;
+}
  #endif

  int erst_write(const struct cper_record_header *record);
--
2.34.1





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux