diff mbox series

[RFC,3/3] Implement a function to get a RCRB Base address

Message ID 20231220050738.178481-4-kobayashi.da-06@fujitsu.com (mailing list archive)
State Handled Elsewhere
Headers show
Series lspci: Display cxl1.1 device link status | expand

Commit Message

Daisuke Kobayashi (Fujitsu) Dec. 20, 2023, 5:07 a.m. UTC
This patch adds a function to obtain the RCRB base address corresponding to
the uid. 

In the case of a CXL1.1 device, the RCRB base address is included in the CHBS
in the CEDT (cxl3.0 specification 9.17.1). In this function, the ACPI's CEDT 
is explored, and the RCRB base address is obtained from the CHBS corresponding
to the uid.


Signed-off-by: KobayashiDaisuke <kobayashi.da-06@fujitsu.com>
---
 ls-caps.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
diff mbox series

Patch

diff --git a/ls-caps.c b/ls-caps.c
index 077e8ea..cccd775 100644
--- a/ls-caps.c
+++ b/ls-caps.c
@@ -1438,6 +1438,51 @@  static int get_device_uid(struct device *d){
 }
 
 static off_t get_rcrb_base(int device_uid){
+  FILE *cedt_file = fopen("/sys/firmware/acpi/tables/CEDT", "rb");
+  if (cedt_file == NULL)
+    return -1;
+
+  struct CEDT_Header header;
+  fread(&header, sizeof(header), 1, cedt_file);
+  
+  struct CHBS_Structure chbs;
+  chbs.base = 0;
+  size_t total_bytes_read = 0;
+  while (total_bytes_read < header.length)
+  {
+    struct CEDT_Structure cedt;
+    size_t bytes_read = fread(&cedt, sizeof(cedt), 1, cedt_file);
+    if (bytes_read != 1)
+    {
+      fclose(cedt_file);
+      return -1;
+    }
+    total_bytes_read += sizeof(cedt);
+    if (cedt.type == CHBS_TYPE)
+    {
+      bytes_read = fread(&chbs, sizeof(chbs), 1, cedt_file);
+      if(bytes_read != 1){
+        fclose(cedt_file);
+        return -1;
+      }
+      total_bytes_read += sizeof(chbs);
+      if ((int)chbs.uid == device_uid){
+        if(chbs.cxl_version == 0){
+          fclose(cedt_file);
+          return chbs.base;
+        }else{
+          fclose(cedt_file);
+          return -1;
+        }
+      } 
+    }
+    else
+    {
+      fseek(cedt_file, cedt.record_length - sizeof(cedt), SEEK_SET);
+      total_bytes_read += cedt.record_length;
+    }
+  }
+  fclose(cedt_file);
   return -1;
 }