#include <asm/pat.h>
 #include <asm/io.h>
 
+#include "pat_internal.h"
+
 #ifdef CONFIG_X86_PAT
 int __read_mostly pat_enabled = 1;
 
 #endif
 
 
-static int debug_enable;
+int pat_debug_enable;
 
 static int __init pat_debug_setup(char *str)
 {
-       debug_enable = 1;
+       pat_debug_enable = 1;
        return 0;
 }
 __setup("debugpat", pat_debug_setup);
 
-#define dprintk(fmt, arg...) \
-       do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
-
-
 static u64 __read_mostly boot_pat_state;
 
 enum {
 
 #undef PAT
 
-static char *cattr_name(unsigned long flags)
-{
-       switch (flags & _PAGE_CACHE_MASK) {
-       case _PAGE_CACHE_UC:            return "uncached";
-       case _PAGE_CACHE_UC_MINUS:      return "uncached-minus";
-       case _PAGE_CACHE_WB:            return "write-back";
-       case _PAGE_CACHE_WC:            return "write-combining";
-       default:                        return "broken";
-       }
-}
-
 /*
  * The global memtype list keeps track of memory type for specific
  * physical memory areas. Conflicting memory types in different
  * memtype_lock protects both the linear list and rbtree.
  */
 
-struct memtype {
-       u64                     start;
-       u64                     end;
-       unsigned long           type;
-       struct list_head        nd;
-       struct rb_node          rb;
-};
-
 static struct rb_root memtype_rbroot = RB_ROOT;
 static LIST_HEAD(memtype_list);
 static DEFINE_SPINLOCK(memtype_lock);  /* protects memtype list */
        return 0;
 }
 
+static int memtype_check_insert(struct memtype *new, unsigned long *new_type)
+{
+       struct memtype *entry;
+       u64 start, end;
+       unsigned long actual_type;
+       struct list_head *where;
+       int err = 0;
+
+       start = new->start;
+       end = new->end;
+       actual_type = new->type;
+
+       /* Search for existing mapping that overlaps the current range */
+       where = NULL;
+       list_for_each_entry(entry, &memtype_list, nd) {
+               if (end <= entry->start) {
+                       where = entry->nd.prev;
+                       break;
+               } else if (start <= entry->start) { /* end > entry->start */
+                       err = chk_conflict(new, entry, new_type);
+                       if (!err) {
+                               dprintk("Overlap at 0x%Lx-0x%Lx\n",
+                                       entry->start, entry->end);
+                               where = entry->nd.prev;
+                       }
+                       break;
+               } else if (start < entry->end) { /* start > entry->start */
+                       err = chk_conflict(new, entry, new_type);
+                       if (!err) {
+                               dprintk("Overlap at 0x%Lx-0x%Lx\n",
+                                       entry->start, entry->end);
+
+                               /*
+                                * Move to right position in the linked
+                                * list to add this new entry
+                                */
+                               list_for_each_entry_continue(entry,
+                                                       &memtype_list, nd) {
+                                       if (start <= entry->start) {
+                                               where = entry->nd.prev;
+                                               break;
+                                       }
+                               }
+                       }
+                       break;
+               }
+       }
+       if (!err) {
+               if (where)
+                       list_add(&new->nd, where);
+               else
+                       list_add_tail(&new->nd, &memtype_list);
+
+               memtype_rb_insert(&memtype_rbroot, new);
+       }
+       return err;
+}
+
 /*
  * req_type typically has one of the:
  * - _PAGE_CACHE_WB
 int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                    unsigned long *new_type)
 {
-       struct memtype *new, *entry;
+       struct memtype *new;
        unsigned long actual_type;
-       struct list_head *where;
        int is_range_ram;
        int err = 0;
 
 
        spin_lock(&memtype_lock);
 
-       /* Search for existing mapping that overlaps the current range */
-       where = NULL;
-       list_for_each_entry(entry, &memtype_list, nd) {
-               if (end <= entry->start) {
-                       where = entry->nd.prev;
-                       break;
-               } else if (start <= entry->start) { /* end > entry->start */
-                       err = chk_conflict(new, entry, new_type);
-                       if (!err) {
-                               dprintk("Overlap at 0x%Lx-0x%Lx\n",
-                                       entry->start, entry->end);
-                               where = entry->nd.prev;
-                       }
-                       break;
-               } else if (start < entry->end) { /* start > entry->start */
-                       err = chk_conflict(new, entry, new_type);
-                       if (!err) {
-                               dprintk("Overlap at 0x%Lx-0x%Lx\n",
-                                       entry->start, entry->end);
-
-                               /*
-                                * Move to right position in the linked
-                                * list to add this new entry
-                                */
-                               list_for_each_entry_continue(entry,
-                                                       &memtype_list, nd) {
-                                       if (start <= entry->start) {
-                                               where = entry->nd.prev;
-                                               break;
-                                       }
-                               }
-                       }
-                       break;
-               }
-       }
-
+       err = memtype_check_insert(new, new_type);
        if (err) {
                printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
                       "track %s, req %s\n",
                return err;
        }
 
-       if (where)
-               list_add(&new->nd, where);
-       else
-               list_add_tail(&new->nd, &memtype_list);
-
-       memtype_rb_insert(&memtype_rbroot, new);
-
        spin_unlock(&memtype_lock);
 
        dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
 
 /* get Nth element of the linked list */
-static struct memtype *memtype_get_idx(loff_t pos)
+static int copy_memtype_nth_element(struct memtype *out, loff_t pos)
 {
-       struct memtype *list_node, *print_entry;
+       struct memtype *list_node;
        int i = 1;
 
-       print_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
-       if (!print_entry)
-               return NULL;
-
-       spin_lock(&memtype_lock);
        list_for_each_entry(list_node, &memtype_list, nd) {
                if (pos == i) {
-                       *print_entry = *list_node;
-                       spin_unlock(&memtype_lock);
-                       return print_entry;
+                       *out = *list_node;
+                       return 0;
                }
                ++i;
        }
+       return 1;
+}
+
+static struct memtype *memtype_get_idx(loff_t pos)
+{
+       struct memtype *print_entry;
+       int ret;
+
+       print_entry  = kzalloc(sizeof(struct memtype), GFP_KERNEL);
+       if (!print_entry)
+               return NULL;
+
+       spin_lock(&memtype_lock);
+       ret = copy_memtype_nth_element(print_entry, pos);
        spin_unlock(&memtype_lock);
-       kfree(print_entry);
 
-       return NULL;
+       if (!ret) {
+               return print_entry;
+       } else {
+               kfree(print_entry);
+               return NULL;
+       }
 }
 
 static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)