From 5b2c241b57ce104405ce71732fae40b7c52b33cf Mon Sep 17 00:00:00 2001
From: Shashank Mittal <mittals@codeaurora.org>
Date: Wed, 27 May 2015 16:08:10 -0700
Subject: [PATCH] lrdpv2: Fix irq parsing support for 3.18 kernel

In 3.18 kernel there is a slight change in radix_tree_node structure.
Fix irq parser to read radix_tree_node according to kernel version.

Change-Id: Ib9e67d137994f4b7424acd2b44676dcdcdb2d0a4
---
 linux-ramdump-parser-v2/parsers/irqstate.py | 12 ++++++++++--
 linux-ramdump-parser-v2/ramdump.py          |  7 +++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/linux-ramdump-parser-v2/parsers/irqstate.py b/linux-ramdump-parser-v2/parsers/irqstate.py
index af1ef9d..fb94c9a 100755
--- a/linux-ramdump-parser-v2/parsers/irqstate.py
+++ b/linux-ramdump-parser-v2/parsers/irqstate.py
@@ -74,14 +74,19 @@ class IrqParse(RamParser):
 
     def radix_tree_lookup_element(self, ram_dump, root_addr, index):
         rnode_offset = ram_dump.field_offset('struct radix_tree_root', 'rnode')
-        rnode_height_offset = ram_dump.field_offset(
-            'struct radix_tree_node', 'height')
+        if (ram_dump.major[0], ram_dump.major[1]) >= (3, 18):
+            rnode_height_offset = ram_dump.field_offset(
+                'struct radix_tree_node', 'path')
+        else:
+            rnode_height_offset = ram_dump.field_offset(
+                'struct radix_tree_node', 'height')
         slots_offset = ram_dump.field_offset('struct radix_tree_node', 'slots')
         pointer_size = ram_dump.sizeof('struct radix_tree_node *')
 
         # if CONFIG_BASE_SMALL=0: radix_tree_map_shift = 6
         radix_tree_map_shift = 6
         radix_tree_map_mask = 0x3f
+        radix_tree_height_mask = 0xfff
         height_to_maxindex = [0x0, 0x3F, 0x0FFF,
                               0x0003FFFF, 0x00FFFFFF, 0x3FFFFFFF, 0xFFFFFFFF]
 
@@ -93,6 +98,9 @@ class IrqParse(RamParser):
         node_addr = ram_dump.read_word(root_addr + rnode_offset) & 0xfffffffffffffffe
         height = ram_dump.read_int(node_addr + rnode_height_offset)
 
+        if (ram_dump.major[0], ram_dump.major[1]) >= (3, 18):
+            height = height & radix_tree_height_mask
+
         if height > len(height_to_maxindex):
             return None
 
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index ca62cb5..ac48542 100644
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -466,6 +466,7 @@ class RamDump():
         self.ipc_log_debug = options.ipc_debug
         self.ipc_log_help = options.ipc_help
         self.use_stdout = options.stdout
+        self.major = [0, 0, 0]
         if options.ram_addr is not None:
             # TODO sanity check to make sure the memory regions don't overlap
             for file_path, start, end in options.ram_addr:
@@ -631,6 +632,12 @@ class RamDump():
                 print_out_str('!!! Could not match version! {0}'.format(b))
                 return False
             self.version = v.group(1)
+            match = re.search('(\d+)\.(\d+)\.(\d+)', self.version)
+            if match is not None:
+                self.major[0], self.major[1], self.major[2] = map(int, match.groups())
+            else:
+                print_out_str('!!! Could not extract version info! {0}'.format(self.version))
+
             print_out_str('Linux Banner: ' + b.rstrip())
             print_out_str('version = {0}'.format(self.version))
             return True
-- 
GitLab