diff --git a/linux-ramdump-parser-v2/parsers/workqueue.py b/linux-ramdump-parser-v2/parsers/workqueue.py
index 27b25ce92bf6bfe38c98a9752254d682b32ce366..51f07e673ef5dbfe77fc915f0106495983dc720c 100644
--- a/linux-ramdump-parser-v2/parsers/workqueue.py
+++ b/linux-ramdump-parser-v2/parsers/workqueue.py
@@ -10,6 +10,7 @@
 # GNU General Public License for more details.
 
 import re
+import linux_list
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
 
@@ -339,145 +340,104 @@ class Workqueues(RamParser):
                     if next_work_entry == worklist_addr:
                         break
 
-    def print_workqueue_state_3_10(self, ram_dump):
+    def walk_workers(self, worker_addr, state):
+        worker_task_offset = self.ramdump.field_offset('struct worker', 'task')
+        offset_comm = self.ramdump.field_offset('struct task_struct', 'comm')
+        current_work_offset = self.ramdump.field_offset(
+            'struct worker', 'current_work')
+        work_func_offset = self.ramdump.field_offset('struct work_struct', 'func')
+
+        worker_task_addr = self.ramdump.read_word(
+                                 worker_addr + worker_task_offset)
+
+        taskname = self.ramdump.read_cstring(
+                                 worker_task_addr + offset_comm, 16)
+        current_work_addr = self.ramdump.read_word(
+                                 worker_addr + current_work_offset)
+        try:
+            phys = self.ramdump.virt_to_phys(current_work_func)
+            current_work_func = self.ramdump.read_word(
+                                     current_work_addr + work_func_offset)
+            wname = self.ramdump.unwind_lookup(current_work_func)
+            if wname is not None:
+                worker_name, a = wname
+            else:
+                worker_name = 'Worker at 0x{0:x}'.format(
+                                    current_work_func)
+        except:
+            worker_name = '(None)'
+
         print_out_str(
-            '======================= WORKQUEUE STATE ============================')
+            '{2} Workqueue worker: {0} current_work: {1}'.format(taskname, worker_name, state))
+
+    def pending_list_walk(self, work):
+        work_func_offset = self.ramdump.field_offset('struct work_struct', 'func')
+        work_func_addr = self.ramdump.read_word(work + work_func_offset)
+
+        try:
+            # virt to phys may throw an exception if the virtual address is bad
+            # if that happens, just skip any printing
+            phys = self.ramdump.virt_to_phys(work_func_addr)
+            work_func_name, foo = self.ramdump.unwind_lookup(work_func_addr)
+            print_out_str(
+                'Pending entry: {0}'.format(work_func_name))
+        except:
+            pass
+
+    def print_workqueue_state_3_10(self, ram_dump):
         cpu_worker_pools_addr = ram_dump.addr_lookup('cpu_worker_pools')
 
         busy_hash_offset = ram_dump.field_offset(
             'struct worker_pool', 'busy_hash')
-        scheduled_offset = ram_dump.field_offset('struct worker', 'scheduled')
-        worker_task_offset = ram_dump.field_offset('struct worker', 'task')
         worker_entry_offset = ram_dump.field_offset('struct worker', 'entry')
-        offset_comm = ram_dump.field_offset('struct task_struct', 'comm')
         work_entry_offset = ram_dump.field_offset(
             'struct work_struct', 'entry')
         work_hentry_offset = ram_dump.field_offset('struct worker', 'hentry')
-        work_func_offset = ram_dump.field_offset('struct work_struct', 'func')
-        current_work_offset = ram_dump.field_offset(
-            'struct worker', 'current_work')
         pool_idle_offset = ram_dump.field_offset(
             'struct worker_pool', 'idle_list')
         worker_pool_size = ram_dump.sizeof('struct worker_pool')
         pending_work_offset = ram_dump.field_offset(
             'struct worker_pool', 'worklist')
 
+        hash_size = 2 ** self.ramdump.gdbmi.get_value_of('BUSY_WORKER_HASH_ORDER')
+
         s = '<'
-        for a in range(0, 64):
-            s = s + 'I'
+        if ram_dump.arm64:
+            pool_char = 'Q'
+        else:
+            pool_char = 'I'
+        for a in range(0, hash_size):
+            s = s + pool_char
 
         for i in ram_dump.iter_cpus():
             busy_hash = []
 
             worker_pool = cpu_worker_pools_addr + ram_dump.per_cpu_offset(i)
-            # Need better way to ge the number of pools...
-            for k in range(0, 2):
+            print_out_str('\nCPU {0}'.format(i))
+            n_pools = self.ramdump.gdbmi.get_value_of('NR_STD_WORKER_POOLS')
+            for k in range(0, n_pools):
+                print_out_str('pool {0}'.format(k))
                 worker_pool_i = worker_pool + k * worker_pool_size
                 busy_hashi = ram_dump.read_string(
                     worker_pool_i + busy_hash_offset, s)
                 for a in busy_hashi:
                     busy_hash.append(a)
 
-                for k in range(0, 64):
+                for k in range(0, hash_size):
                     next_busy_worker = busy_hash[k]
                     if busy_hash[k] != 0:
-                        cnt = 0
-
-                        while True:
-                            worker_addr = next_busy_worker - work_hentry_offset
-                            worker_task_addr = ram_dump.read_word(
-                                worker_addr + worker_task_offset)
-                            if worker_task_addr is None or worker_task_addr == 0:
-                                break
-                            taskname = ram_dump.read_cstring(
-                                worker_task_addr + offset_comm, 16)
-                            scheduled_addr = ram_dump.read_word(
-                                worker_addr + scheduled_offset)
-                            current_work_addr = ram_dump.read_word(
-                                worker_addr + current_work_offset)
-                            current_work_func = ram_dump.read_word(
-                                current_work_addr + work_func_offset)
-                            wname = ram_dump.unwind_lookup(current_work_func)
-                            if wname is not None:
-                                worker_name, a = wname
-                            else:
-                                worker_name = 'Worker at 0x{0:x}'.format(
-                                    current_work_func)
-                            print_out_str(
-                                'BUSY Workqueue worker: {0} current_work: {1}'.format(taskname, worker_name))
-                            if cnt > 200:
-                                break
-                            cnt += 1
-                            next_busy_worker = ram_dump.read_word(
-                                worker_addr + work_hentry_offset)
-                            if next_busy_worker == 0:
-                                break
+                        busy_list_walker = linux_list.ListWalker(ram_dump, next_busy_worker, work_hentry_offset)
+                        busy_list_walker.walk(next_busy_worker, self.walk_workers, 'BUSY')
 
                 idle_list_addr = worker_pool_i + pool_idle_offset
-                next_entry = ram_dump.read_word(idle_list_addr)
-                seen = []
-                while True:
-                    worker_addr = next_entry - worker_entry_offset
-                    worker_task_addr = ram_dump.read_word(
-                        next_entry - worker_entry_offset + worker_task_offset)
-                    if worker_task_addr is None or worker_task_addr == 0 or worker_task_addr in seen:
-                        break
-
-                    seen.append(worker_task_addr)
-
-                    taskname = ram_dump.read_cstring(
-                        (worker_task_addr + offset_comm), 16)
-                    scheduled_addr = ram_dump.read_word(
-                        worker_addr + scheduled_offset)
-                    current_work_addr = ram_dump.read_word(
-                        worker_addr + current_work_offset)
-                    next_entry = ram_dump.read_word(next_entry)
-                    if current_work_addr != 0:
-                        current_work_func = ram_dump.read_word(
-                            current_work_addr + work_func_offset)
-                        wname = ram_dump.unwind_lookup(current_work_func)
-                        if wname is not None:
-                            current_work_name, foo = wname
-                        else:
-                            current_work_name = 'worker at 0x{0:x}'.format(
-                                current_work_func)
-                    else:
-                        current_work_func = 0
-                        current_work_name = '(null)'
 
-                    if next_entry == idle_list_addr:
-                        break
-
-                    print_out_str(
-                        'IDLE Workqueue worker: {0} current_work: {1}'.format(taskname, current_work_name))
-                    if scheduled_addr == (worker_addr + scheduled_offset):
-                        continue
-
-                    if (next_entry == idle_list_addr):
-                        break
+                idle_list_walker = linux_list.ListWalker(ram_dump, idle_list_addr, worker_entry_offset)
+                idle_list_walker.walk(self.ramdump.read_word(idle_list_addr), self.walk_workers, 'IDLE')
 
                 worklist_addr = worker_pool_i + pending_work_offset
-                next_work_entry = worklist_addr
-                while ram_dump.read_word(next_work_entry) != next_work_entry:
-                    work_func_addr = ram_dump.read_word(
-                        next_work_entry - work_entry_offset + work_func_offset)
-                    next_work_temp = ram_dump.read_word(next_work_entry)
-                    if next_work_temp == next_work_entry:
-                        print_out_str('!!! Cycle in workqueue!')
-                        break
-                    next_work_entry = next_work_temp
 
-                    if ram_dump.virt_to_phys(work_func_addr) != 0:
-                        work_func_name, foo = ram_dump.unwind_lookup(
-                            work_func_addr)
-                        if i == 0:
-                            print_out_str(
-                                'Pending unbound entry: {0}'.format(work_func_name))
-                        else:
-                            print_out_str(
-                                'Pending bound entry: {0}'.format(work_func_name))
-                    if next_work_entry == worklist_addr:
-                        break
+                pending_list = linux_list.ListWalker(ram_dump, worklist_addr, work_entry_offset)
+                pending_list.walk(self.ramdump.read_word(worklist_addr), self.pending_list_walk)
 
     def parse(self):
             ver = self.ramdump.version