aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorvenkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com>2010-02-10 14:57:06 -0500
committerH. Peter Anvin <hpa@zytor.com>2010-02-18 18:41:21 -0500
commitbe5a0c126ad1dea2128dc5aef12c87083518d1ab (patch)
tree3bbec0573354513dc03ece303d82418aa281c2c7 /arch/x86/mm
parent17d9ddc72fb8bba0d4f67868c9c612e472a594a9 (diff)
x86, pat: Preparatory changes in pat.c for bigger rbtree change
Minor changes in pat.c to cleanup code and make it smoother to introduce bigger rbtree only change in the following patch. The changes are cleaup only and should not have any functional impact. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> LKML-Reference: <20100210195909.792781000@intel.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/pat.c170
-rw-r--r--arch/x86/mm/pat_internal.h28
2 files changed, 116 insertions, 82 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ae9648eb1c7f..628e507b7936 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -30,6 +30,8 @@
30#include <asm/pat.h> 30#include <asm/pat.h>
31#include <asm/io.h> 31#include <asm/io.h>
32 32
33#include "pat_internal.h"
34
33#ifdef CONFIG_X86_PAT 35#ifdef CONFIG_X86_PAT
34int __read_mostly pat_enabled = 1; 36int __read_mostly pat_enabled = 1;
35 37
@@ -53,19 +55,15 @@ static inline void pat_disable(const char *reason)
53#endif 55#endif
54 56
55 57
56static int debug_enable; 58int pat_debug_enable;
57 59
58static int __init pat_debug_setup(char *str) 60static int __init pat_debug_setup(char *str)
59{ 61{
60 debug_enable = 1; 62 pat_debug_enable = 1;
61 return 0; 63 return 0;
62} 64}
63__setup("debugpat", pat_debug_setup); 65__setup("debugpat", pat_debug_setup);
64 66
65#define dprintk(fmt, arg...) \
66 do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
67
68
69static u64 __read_mostly boot_pat_state; 67static u64 __read_mostly boot_pat_state;
70 68
71enum { 69enum {
@@ -132,17 +130,6 @@ void pat_init(void)
132 130
133#undef PAT 131#undef PAT
134 132
135static char *cattr_name(unsigned long flags)
136{
137 switch (flags & _PAGE_CACHE_MASK) {
138 case _PAGE_CACHE_UC: return "uncached";
139 case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
140 case _PAGE_CACHE_WB: return "write-back";
141 case _PAGE_CACHE_WC: return "write-combining";
142 default: return "broken";
143 }
144}
145
146/* 133/*
147 * The global memtype list keeps track of memory type for specific 134 * The global memtype list keeps track of memory type for specific
148 * physical memory areas. Conflicting memory types in different 135 * physical memory areas. Conflicting memory types in different
@@ -159,14 +146,6 @@ static char *cattr_name(unsigned long flags)
159 * memtype_lock protects both the linear list and rbtree. 146 * memtype_lock protects both the linear list and rbtree.
160 */ 147 */
161 148
162struct memtype {
163 u64 start;
164 u64 end;
165 unsigned long type;
166 struct list_head nd;
167 struct rb_node rb;
168};
169
170static struct rb_root memtype_rbroot = RB_ROOT; 149static struct rb_root memtype_rbroot = RB_ROOT;
171static LIST_HEAD(memtype_list); 150static LIST_HEAD(memtype_list);
172static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ 151static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */
@@ -349,6 +328,64 @@ static int free_ram_pages_type(u64 start, u64 end)
349 return 0; 328 return 0;
350} 329}
351 330
331static int memtype_check_insert(struct memtype *new, unsigned long *new_type)
332{
333 struct memtype *entry;
334 u64 start, end;
335 unsigned long actual_type;
336 struct list_head *where;
337 int err = 0;
338
339 start = new->start;
340 end = new->end;
341 actual_type = new->type;
342
343 /* Search for existing mapping that overlaps the current range */
344 where = NULL;
345 list_for_each_entry(entry, &memtype_list, nd) {
346 if (end <= entry->start) {
347 where = entry->nd.prev;
348 break;
349 } else if (start <= entry->start) { /* end > entry->start */
350 err = chk_conflict(new, entry, new_type);
351 if (!err) {
352 dprintk("Overlap at 0x%Lx-0x%Lx\n",
353 entry->start, entry->end);
354 where = entry->nd.prev;
355 }
356 break;
357 } else if (start < entry->end) { /* start > entry->start */
358 err = chk_conflict(new, entry, new_type);
359 if (!err) {
360 dprintk("Overlap at 0x%Lx-0x%Lx\n",
361 entry->start, entry->end);
362
363 /*
364 * Move to right position in the linked
365 * list to add this new entry
366 */
367 list_for_each_entry_continue(entry,
368 &memtype_list, nd) {
369 if (start <= entry->start) {
370 where = entry->nd.prev;
371 break;
372 }
373 }
374 }
375 break;
376 }
377 }
378 if (!err) {
379 if (where)
380 list_add(&new->nd, where);
381 else
382 list_add_tail(&new->nd, &memtype_list);
383
384 memtype_rb_insert(&memtype_rbroot, new);
385 }
386 return err;
387}
388
352/* 389/*
353 * req_type typically has one of the: 390 * req_type typically has one of the:
354 * - _PAGE_CACHE_WB 391 * - _PAGE_CACHE_WB
@@ -364,9 +401,8 @@ static int free_ram_pages_type(u64 start, u64 end)
364int reserve_memtype(u64 start, u64 end, unsigned long req_type, 401int reserve_memtype(u64 start, u64 end, unsigned long req_type,
365 unsigned long *new_type) 402 unsigned long *new_type)
366{ 403{
367 struct memtype *new, *entry; 404 struct memtype *new;
368 unsigned long actual_type; 405 unsigned long actual_type;
369 struct list_head *where;
370 int is_range_ram; 406 int is_range_ram;
371 int err = 0; 407 int err = 0;
372 408
@@ -423,42 +459,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
423 459
424 spin_lock(&memtype_lock); 460 spin_lock(&memtype_lock);
425 461
426 /* Search for existing mapping that overlaps the current range */ 462 err = memtype_check_insert(new, new_type);
427 where = NULL;
428 list_for_each_entry(entry, &memtype_list, nd) {
429 if (end <= entry->start) {
430 where = entry->nd.prev;
431 break;
432 } else if (start <= entry->start) { /* end > entry->start */
433 err = chk_conflict(new, entry, new_type);
434 if (!err) {
435 dprintk("Overlap at 0x%Lx-0x%Lx\n",
436 entry->start, entry->end);
437 where = entry->nd.prev;
438 }
439 break;
440 } else if (start < entry->end) { /* start > entry->start */
441 err = chk_conflict(new, entry, new_type);
442 if (!err) {
443 dprintk("Overlap at 0x%Lx-0x%Lx\n",
444 entry->start, entry->end);
445
446 /*
447 * Move to right position in the linked
448 * list to add this new entry
449 */
450 list_for_each_entry_continue(entry,
451 &memtype_list, nd) {
452 if (start <= entry->start) {
453 where = entry->nd.prev;
454 break;
455 }
456 }
457 }
458 break;
459 }
460 }
461
462 if (err) { 463 if (err) {
463 printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, " 464 printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
464 "track %s, req %s\n", 465 "track %s, req %s\n",
@@ -469,13 +470,6 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
469 return err; 470 return err;
470 } 471 }
471 472
472 if (where)
473 list_add(&new->nd, where);
474 else
475 list_add_tail(&new->nd, &memtype_list);
476
477 memtype_rb_insert(&memtype_rbroot, new);
478
479 spin_unlock(&memtype_lock); 473 spin_unlock(&memtype_lock);
480 474
481 dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n", 475 dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
@@ -937,28 +931,40 @@ EXPORT_SYMBOL_GPL(pgprot_writecombine);
937#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) 931#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
938 932
939/* get Nth element of the linked list */ 933/* get Nth element of the linked list */
940static struct memtype *memtype_get_idx(loff_t pos) 934static int copy_memtype_nth_element(struct memtype *out, loff_t pos)
941{ 935{
942 struct memtype *list_node, *print_entry; 936 struct memtype *list_node;
943 int i = 1; 937 int i = 1;
944 938
945 print_entry = kmalloc(sizeof(struct memtype), GFP_KERNEL);
946 if (!print_entry)
947 return NULL;
948
949 spin_lock(&memtype_lock);
950 list_for_each_entry(list_node, &memtype_list, nd) { 939 list_for_each_entry(list_node, &memtype_list, nd) {
951 if (pos == i) { 940 if (pos == i) {
952 *print_entry = *list_node; 941 *out = *list_node;
953 spin_unlock(&memtype_lock); 942 return 0;
954 return print_entry;
955 } 943 }
956 ++i; 944 ++i;
957 } 945 }
946 return 1;
947}
948
949static struct memtype *memtype_get_idx(loff_t pos)
950{
951 struct memtype *print_entry;
952 int ret;
953
954 print_entry = kzalloc(sizeof(struct memtype), GFP_KERNEL);
955 if (!print_entry)
956 return NULL;
957
958 spin_lock(&memtype_lock);
959 ret = copy_memtype_nth_element(print_entry, pos);
958 spin_unlock(&memtype_lock); 960 spin_unlock(&memtype_lock);
959 kfree(print_entry);
960 961
961 return NULL; 962 if (!ret) {
963 return print_entry;
964 } else {
965 kfree(print_entry);
966 return NULL;
967 }
962} 968}
963 969
964static void *memtype_seq_start(struct seq_file *seq, loff_t *pos) 970static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)
diff --git a/arch/x86/mm/pat_internal.h b/arch/x86/mm/pat_internal.h
new file mode 100644
index 000000000000..6c98780eb731
--- /dev/null
+++ b/arch/x86/mm/pat_internal.h
@@ -0,0 +1,28 @@
1#ifndef __PAT_INTERNAL_H_
2#define __PAT_INTERNAL_H_
3
4extern int pat_debug_enable;
5
6#define dprintk(fmt, arg...) \
7 do { if (pat_debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
8
9struct memtype {
10 u64 start;
11 u64 end;
12 unsigned long type;
13 struct list_head nd;
14 struct rb_node rb;
15};
16
17static inline char *cattr_name(unsigned long flags)
18{
19 switch (flags & _PAGE_CACHE_MASK) {
20 case _PAGE_CACHE_UC: return "uncached";
21 case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
22 case _PAGE_CACHE_WB: return "write-back";
23 case _PAGE_CACHE_WC: return "write-combining";
24 default: return "broken";
25 }
26}
27
28#endif /* __PAT_INTERNAL_H_ */